在使用TS开发时,一般我们会在tsconfig 中设置别名来让代码变得优雅一点。
将 import xx from '…/…/…/service/'改为import xx form ‘@service/’
tsconfig 别名设置
此时项目结构如下
一般我们可以通过baseUrl 和path两个字段来设置对应的别名
{
"include": ["./src"],
"compilerOptions": {
"module": "commonjs",
"allowJs": true,
"declaration": false,
"esModuleInterop": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": false,
"outDir": "./dist",
"baseUrl": ".",
"paths": {
// 设置对应的别名
"@service/*": ["./src/service/*"],
}
},
"exclude": ["node_modules"]
}
设置完之后我们就可以在controller/hello.ts代码中使用设置的别名了。
import HelloService from '@service/hello';
class HelloController {
private service: HelloService = new HelloService();
hello = async ctx => {
const params = ctx.request.query;
console.log(`接受到的参数为, name:${params.name}`);
ctx.body = await this.service.hello();
};
}
export default new HelloController();
但是当我们在本地开发启动服务调式时会报如下错误,ts-node 并不识别配置的别名@service,所以找不到该模块
开发(tsconfig-paths)
需要安装一个 tsconfig-paths 包来解决问题
npm i tsconfig-paths --save-dev
将启动命令修改为如下:
{
"watch": ["src"],
"ext": "ts",
"exec": "export NODE_ENV=dev && ts-node -r tsconfig-paths/register src/index.ts",
"ignore": ["./src/public"]
}
这里是使用的nodemon + ts-node 这个组合。解释一下
- export NODE_ENV = dev是设置node的环境变量
- -r 是node的一个命令行参数,-r详情
- tsconfig-paths/register:详情
可以看到,这么配置之后就可以正常的启动服务了。
打包(tsc-alias)
上面解决了开发时的问题,那如果开发完了把代码打包时,还是会遇到这个问题。我们看下直接使用tsc编译之后的结果是什么样的。
可以看到直接使用tsc编译之后,并没有将别名@service进行替换,运行node dist/index.js就会报下面的错误了
解决该问题需要安装一个 tsc-alias 的包,这个包其实是想tsc编译之后的文件进一步处理,将里面的别名替换掉。
npm i tsc-alias --save-dev
修改一下打包命令build,使用tsc编译完后再使用tsc-alias编译 ,内容如下
"scripts": {
"dev": "nodemon",
"build": "rm -rf dist && tsc && tsc-alias",
"cp": "cp -r src/public dist/public",
"start": "export NODE_ENV=prod && npm run build && npm run cp && npx pm2 start ecosystem.config.js",
},
其他
关于这个问题,在TypeScript的Github上有个issues。有兴趣的可以看下
issue查看