「这是我参加 2022 首次更文挑战的第 1 天,流动详情查看:2022 首次更文挑战」。
Dear,大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~
通常在编写完 TypeScript 代码当前总是须要通过其内置的 CLI 来编译为 JavaScript 文件,再通过 node 来执行,当然也有简化操作的库,如:ts-node。上面就来摸索一下如何实现相似 ts-node 能够间接执行 TypeScript 的性能吧。
前提概要:
1. 波及知识点:
- NodeJs:require 函数
-
TypeScript:Compiler API
2. 工作拆解:
- 如何让 Node 意识 Ts 文件;
-
如何让 Ts 文件变为 Js 文件。
3. require 函数的执行过程: module.js
-
Module.prototype.require(path):
- 依据传入 path 来确定待加载模块的绝对路径;
- 执行模块加载(程序:1. 优先缓存,2. 内置模块,3. 生成实例并存入缓存)
-
Module.prototype.load(filename):
- 通过文件名称辨认后缀为.js,.json,.node 的文件并读取内容;
-
通过 Module 内置的_compile 函数进行模块化编译。
如何辨认 ts 文件:
-
module 中如何辨认 js 文件:
Module._extensions['.js'] = function(module, filename) {var content = fs.readFileSync(filename, 'utf8'); module._compile(stripBOM(content), filename); };
-
仿照 module 的源码解决来实现辨认 ts 文件:
const fs = require('fs'); require.extensions['.ts'] = function (module, filename) {var content = fs.readFileSync(filename, 'utf8'); console.log(filename); console.log(content); }; require('./index.ts')
将 TypeScript 代码本义为 JavaScript 代码,下图为 Ts Compiler API 的 Wiki 内容截图提供了最简略的实现 API:
const ts = require('typescript'); // 编译前的 Ts 内容 const content = ` enum PersonType { MAN = 1, WOMAN = 2, } if (PersonType.MAN === 1) {console.log('hello ts'); } `; const {outputText} = ts.transpileModule(content, {compilerOptions: { module: ts.ModuleKind.CommonJS} }) // 编译后的 Js 内容:/* var PersonType; (function (PersonType) {PersonType[PersonType["MAN"] = 1] = "MAN"; PersonType[PersonType["WOMAN"] = 2] = "WOMAN"; })(PersonType || (PersonType = {})); if (PersonType.MAN === 1) {console.log('hello ts'); } */ console.log(outputText);
Ts 执行器残缺代码:
// ts-actuator.js
const path = require('path');
const fs = require('fs');
const ts = require('typescript');
// 从命令行获取下标为 2 的参数 (待执行的 ts 文件名称)
const filePath = process.argv[2];
// 减少反对.ts 文件后缀的检测
require.extensions['.ts'] = function (module, filename) {
// 失去相对 ts 文件的门路并读取内容
const fileFullPath = path.resolve(__dirname, filename);
const content = fs.readFileSync(fileFullPath, 'utf-8');
// 通过 Ts 提供的 transpileModule 将 Ts 字符串转为 Js 字符串
const {outputText} = ts.transpileModule(content, {compilerOptions: { module: ts.ModuleKind.CommonJS}
})
// 将失去的 Js 字符串进行模块编译
module._compile(outputText, filename);
}
// 执行模块的 require 函数
require(filePath);
结语:
看了光哥的文章,本人写了两遍找了找感觉,很神奇,光哥的文章地址:手写一个 ts-node 来深刻了解它的原理
欢送关注我的公众号“前端小鑫同学”,原创技术文章第一工夫推送。