问题由来
我们通常引用一个npm模块,直接引用模块的名称就可以了,如 import module from 'module'
。
但是如果引用自己开发的模块,往往要使用相对路径的方式找到目标模块,如 import myComponent from '../../../components/myComponent'
。
这种方式可以正常开发,可以完成业务需求,但是维护起来就很难弄了,因为通过这种相对路径的方式你很难一下定位这个组件在哪里,在项目复杂的时候,可能会产生预期外的结果。
别名设置
其实这个问题的解决方案已经很成熟了,从各种构建工具及命令中都有相应的设置。
我这里只针对 typescript
做说明,因为他提供的工具集有点坑。
假如我想实现 import myComponent from '@components/myComponent'
。
而我的目录结构为
./ └── src ├── components └── views └── app.ts
tsconfig.json
{ "compilerOptions": { "baseUrl": ".", "paths": { "@components/*": ["src/components/*"] } } }
这里的关键配置是 baseUrl
和 paths
具体说明可以参见文档
https://www.tslang.cn/docs/handbook/module-resolution.html#virtual-directories-with-rootdirs
webpack
假设有一个 webpack.config.js
文件在 ./
下面
resolve: { alias: { '@components': path.resolve(__dirname, './src/components'), } }
这个比较基础,直接查看webpack文档就可以了
https://www.webpackjs.com/configuration/resolve/#resolve-alias
通过tsc编译会产生的问题
该文章并不是要教你怎么使用别名,而是 typescript
的开发中有个坑。
用tsc编译的后,映射的路径不会处理,将导致编译后的代码找不到模块
比如上面的 import myComponent from '@components/myComponent'
,如果你使用 commonjs
模式编译后应该是 const myComponent require('@components/myComponent')
,结果就是找不到这个模块。
解决方案一:使用webpack等构建工具进行编译
可以通过 ts-loader
等组件进行编译,来规避掉这个问题
解决方案二:使用module-alias
我现在的场景是,就想使用 tsc -w
来进行开发,那么经过一番寻找,比较优秀的方案就是 module-alias
了。
https://www.npmjs.com/package/module-alias
最简单的用法就是将 const moduleAlias = require('module-alias')
放到你的项目入口处。
然后设置你的 package.json
,以前面的结构为例。
"_moduleAliases": { "@components" : "./src/components" }
这样就可以达到 tsc
编译后,仍然可以找到设置别名的路径了。
至于 module-alias
的原理是什么可以看一下他的npm模块的描述,我就不擅自翻译,免得误人子弟。