Appearance
对于tsconfig.json中的 compilerOptions#rootDirs 配置项的思考来自于 Module Resolution
这一节。
一开始实在是不太理解这一个字段的含义是什么,后面根据思考后得出:这个字段允许将多个目录文件假设存放在同一个目录下,通过配置 rootDirs,编译器可以解析并不存在的相对模块导入
,可以参考文档中国际化的示例,项目结构为:
bash
.
├── src
│ ├── de
│ │ └── messages.ts
│ ├── index.ts
│ └── zh
│ └── messages.ts
└── tsconfig.json
TIP
上面树形结构,使用下面命令:
bash
# -I 'dir1|dir2' 忽略目录
# -L 3 打印层级
tree -I 'node_modules|output|dist' -L 3
文件配置为:
typescript
import messages from './#{locale}/messages';
console.log(messages)
typescript
export default ["hello", "nice to meet you"];
typescript
export default ["您好吗", "很高兴认识你"];
其中 ./#{locale/messages}
并不存在,不设置 tsconfig.json#rootDirs
配置:
json
{
"compilerOptions": {
"target": "es2016",
/* Modules */
"module": "esnext",
/* Allow multiple folders to be treated as one when resolving modules. */
// "rootDirs": [],
/* Interop Constraints */
"esModuleInterop": true,
/* Type Checking */
"strict": true,
"skipLibCheck": true
},
"exclude": ["rollup.config.js"]
}
出现报错: 找不到模块 "./#{locale}/messages"
这也很好理解,因为根本就不存在 "./#{locale}/messages"
模块,但是,如果我们进行如下设置:
json
{
"compilerOptions": {
"target": "es2016",
/* Modules */
"module": "esnext",
/* Allow multiple folders to be treated as one when resolving modules. */
// "rootDirs": [],
"rootDirs": ["src/zh", "src/de", "src/#{locale}"],
/* Interop Constraints */
"esModuleInterop": true,
/* Type Checking */
"strict": true,
"skipLibCheck": true
},
"exclude": ["rollup.config.js"]
}
此时TypeScript不再报错🎉,这是因为,编译时,导入的相对路径会被转换为绝对路径,即项目 /ts-demo/src/#{locale}/messages
, 接着遍历 rootDirs
列表, 找出于这个路径相比最长的前缀匹配路径,最终确定的是 /ts-demo/src/#{locale}/
。将 /ts-demo/src/#{locale}/messages
与 /ts-demo/src/#{locale}/
相同的部分去掉,确定要加载的位置是 messages
。候选位置为 /ts-demo/src/${locale}/messages
,编译器将会按照相对路径模块导入的解析方法进行模块解析,不过 /ts-demo/src/${locale}/
目录并不存在,于是编译器会从 rootDirs
列表从上到下进行遍历(除去之前选定的那个目录),然后将 messages 与路径进行拼接,新的尝试的路径为 /ts-demo/src/zh/
,模块候选位置为 /ts-demo/src/zh/messages
,在此处找到了模块,因此将 /ts-demo/src/zh/messages.ts
作为模块解析结果。
WARNING
rootDirs
对编译输出并没有影响,只是让编译器知道模块的含义。
使用 tsc
进行打包,得到的 index.js
为:
js
import messages from './#{locale}/messages';
console.log(messages);
参考:
为了验证上面的说法,使用 rollup
对项目进行打包:
bash
pnpm i -D rollup @rollup/plugin-typescript
js
import { defineConfig } from 'rollup'
import typescript from '@rollup/plugin-typescript'
export default {
input: 'src/index.ts',
output: {
dir: 'output',
format: 'cjs'
},
plugins: [
typescript(),
]
}
然后执行:
bash
npx rollup -c
打包得到:
js
'use strict';
var messages = ["您好吗", "很高兴认识你"];
console.log(messages);
可以看出 /ts-demo/src/zh/messages.ts
作为了模块解析的结果。
可以通过调整 rootDirs
的顺序,对生成的结果进行调整:
json
{
"compilerOptions": {
"target": "es2016",
/* Modules */
"module": "esnext",
/* Allow multiple folders to be treated as one when resolving modules. */
"rootDirs": ["src/zh", "src/de", "src/#{locale}"],
"rootDirs": ["src/de", "src/zh", "src/#{locale}"],
/* Interop Constraints */
"esModuleInterop": true,
/* Type Checking */
"strict": true,
"skipLibCheck": true
},
"exclude": ["rollup.config.js"]
}
再使用 npx rollup -c
打包,得到的结果为:
js
'use strict';
var messages = ["hello", "nice to meet you"];
console.log(messages);
2023年02月24日20:55:00