Typescript项目别名(alias)配置清单
综述
新手写Typescript项目,别名配置是经常出问题的环节,有的人遇到这种问题,如果一时半会儿解决不了,干脆就不用别名了,这显然是不合理的。本文给出一个Typescript项目各种环节的别名配置清单,如果遇到问题,可以对照着检查一下。
Typescript项目需要识别别名的环节,主要包括:vscode语法检查、tsc编译、单元测试、lint、webpack打包。如果是node项目,还要考虑node运行时的别名识别。
其中,vscode语法检查、tsc编译,以及单元测试,这三个环节依赖的是tsconfig.json中的别名配置;webpack打包依赖的是webpack.config.js中的别名配置;node的别名识别需要载入一个叫做module-alias的包。
tsconfig
tsconfig中负责别名配置的是两个字段:
"baseUrl": "./",
"paths": {
"~/*": ["./src/*"]
}
其中baseUrl用来描述计算相对路径时的根目录,paths用来描述路径别名。注意: 如果配置了paths,就一定要配置baseUrl,否则后面会遇到问题 。
tsconfig配置好之后,如何生效呢?vscode语法检查和tsc编译基本上不需要操心,自动生效。比较容易搞错的是单元测试,确切地说不是单元测试,而是ts-node这个工具。在默认状态下,ts-node不会受tsconfig中别名配置的影响,想要让ts-node配置别名,需要安装一个包:
npm i tsconfig-paths --save-dev
ts-node和mocha使用:
# ts-node使用
ts-node -r tsconfig-paths/register main.ts
#mocha配合ts-node使用
mocha -r ts-node/register -r tsconfig-paths/register "test/**/*.ts"
其实node也可以使用tsconfig-paths/register识别别名,但是node命令行应用项目不建议使用,因为它依赖于node启动应用的命令添加参数。
另外提醒一句,不要因为觉得tsconfig要对单测文件生效,就把test目录配置到includes里面去,会导致tsc把单测文件也编译到交付目录里去。
lint
eslint的别名配置,是比较容易出错的。首先,你要安装一个包:
npm i eslint-import-resolver-alias --save-dev
这个包是一个配合eslint-plugin-import使用的resolver,用来resolve带别名的路径。
然后你的.eslintrc要添加相应的配置:
module.exports = {
settings: {
'import/resolver': {
alias: {
map: [['~', './src']],
extensions: ['.tsx', '.ts', '.jsx', '.js'],
其中extensions是查找无后缀名文件时的后缀名列表。
webpack
webpack的别名配置使用resolve字段,写法如下:
config.resolve = {
alias: {
"~": path.resolve(cwd, "./src/")
extensions: [".tsx", ".ts", ".jsx", ".js"]
这个配置很常用,一般不会出错。
值得注意的是 与样式文件有关的别名 ,这里面有三种情况:
第一种是你在ts文件里面使用import加载css。这没什么可说的,跟import ts文件一样,使用上面的resolve字段就能解决。
第二种是你在css文件里面使用@import语句加载另一个css。由于按照css @import语法的规定,这里的路径会被当做相对路径,所以如果你打算让webpack的别名配置在这里生效,或者你想加载node_modules目录中的css,你得在路径前面加个波浪线“~”,webpack才会把这个css路径当做module去resolve,比如这样:
@import "~antd/es/button/style/index.css";
我最近试了一下,发现用比较新的webpack和css-loader其实不加波浪线也可以。我用的版本是:
css-loader: 4.2.2
webpack: 4.44.1
第三种情况是你在css文件里面使用别名加载图片等静态资源,比如这样:
.foobar{
background: url(~/128x128.png);
}
这时候要使用css-loader自己的别名配置,才能支持这种写法。配置方法:
{
loader: 'css-loader',
options: {
alias:{
'~':path.resolve(__dirname, './src/assets')
node运行时
如果你开发的是一个node命令行程序,你还需要让node在运行时识别你配置的别名,刚才说过tsconfig-paths具备这个功能,但是我不推荐使用,我推荐另一个包:
npm i module-alias --save
这个包通过直接import进项目,在运行时生效,读取package.json的别名配置。它改写了Module._resolveFilename,从而解决别名问题。
按照文档,把如下代码放入你的入口文件(就是package.json里面那个main字段指向的文件),就可以了:
require('module-alias/register')
但是实际用的时候,如果你的入口文件不在项目根目录(我比较习惯把入口文件也放到src里,编译完了在lib目录里),你得自己传入根目录的路径:
import path from "path";
import alias from "module-alias";
alias(path.resolve(__dirname, "../"));
module-alias的别名配置位于package.json中,语法如下:
{
// Aliases
"_moduleAliases": {
"@root" : ".", // Application's root
"@deep" : "src/some/very/deep/directory/or/file",
"@my_module" : "lib/some-file.js",
"something" : "src/foo", // Or without @. Actually, it could be any string