背景:随着react的使用我俨然已经成为了ts的深度使用者,时下react+ts+webpack的组合拳简直不要太香。作为把手伸向服务端的前端来说node是必不可少的一部分伴随着这个想法ts-node也被我提上了日程。
问题:webpack中的alias给我们提供了路径简写并在打包的时候替我们寻找文件因此我们不需要去担心打包之后的路径问题。但是ts-node我并不是通过webpack进行搭建的,因此在设置了tsconfig.json的paths路径简写在ts编译成js之后原本的路径简写并没有替换成相对路径导致找不到相关的文件。
思路:观察了打包的文件之后可以通过node获取tsconfig.json中的paths对象然后,通过fs递归遍历读取打包后的文件夹中的文件内容,通过匹配paths参数并替换经过层级处理过后的相对路径,判断时候有命中paths,否的话就跳过文件重写优化代码是的话重新改写文件
代码实现:
const path = require("path");
const fs = require("fs");
const json = path.resolve(__dirname, "./tsconfig.json");
const data = fs.readFileSync(json, "utf-8");
let pathList = data.match(/"@.*?\]/gm);
let outDir = data.match(/(?<="outDir":.").*/g)[0].match(/.*(?=",)/g)[0]; // 前瞻后瞻选出ts编译出口
let handlePathList: string[] = [];
for (let i = 0; i < pathList.length; i++) {
handlePathList.push(
pathList[i]
.match(/".*?"/g)
.map((item: string) => item.replace(/"/g, "").replace(/\/\*/g, ""))
); // 处理paths为二维数组
}
function deepdir(path: string, usePath: string) {
fs.readdir(path, (err: any, files: string[]) => {
files.forEach((item: string) => {
try {
let isRewrite: boolean = false;
let content: string = fs.readFileSync(path + "\\" + item, "utf-8");
handlePathList.forEach((items: string) => {
// 替换字符串
const handleUsePath = usePath === "" ? "./" : usePath;
let url = items[1].startsWith("./")
? items[1].replace("./", handleUsePath)
: handleUsePath + items[1];
let matchRes: RegExpMatchArray = content.match(
new RegExp(items[0], "g")
);
if (matchRes) {
// 优化
content = content.replace(new RegExp(items[0], "g"), url);
isRewrite = true;
}
});
if (isRewrite) fs.writeFileSync(path + "\\" + item, content);
} catch {
deepdir(path + "/" + item, "../" + usePath);
}
});
});
}
deepdir(outDir, "");
命令:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc & ts-node ./replacePath.ts",
"dev": "nodemon --watch ./ --exec ts-node -r tsconfig-paths/register ./src/app.ts --files",
"start": "nodemon --watch ./ --exec ts-node -r tsconfig-paths/register --files ./src/app.ts",
"start:production": "nodemon --inspect ./dist/app.js",
"lint": "eslint --ext .ts --ext .js src",
"lint-fix": "eslint --fix --ext .ts --ext .js src"
},
tsconfig.json
{
"compilerOptions": {
"diagnostics": true, // 打印诊断信息
"target": "es5", // 目标语言的版本
"module": "commonjs", // 生成代码的模块标准
"esModuleInterop": true, // 允许编译 JS 文件(js、jsx)
"moduleResolution": "node", // 模块解析策略
"types": ["node"], // 指定要编译的@types包
"baseUrl": "./src/",
"noImplicitAny": true,
"outDir": "./dist/",
"allowJs": true,
// "sourceMap": true,
// "rootDir": "./src/",
"typeRoots": ["src/types.d.ts"],
"paths": {
"@/config/*": ["config/*"],
"@/router/*": ["./router/*"],
"@/model/*": ["./model/*"],
"@/graphql/*": ["./graphql/*"],
"@/controller/*": ["./controller/*"],
"@/middleware/*": ["./middleware/*"],
}
},
"include": ["src/**/*"],
"exclude": ["node_modules/**/*"]
}
项目目录结构
这是我的0-1搭建的ts-node项目git仓库地址欢迎clone
TS-node: TS-node