今天在玩耍typescript
的时候,发现了一个有趣的问题,tsconfig.json
中的outDir
配置导致tsc命令无法编译,tsconfig.json
的配置是这样的:
1 | { |
再来看一下项目的目录结构(这里推荐一个在线生成项目目录结构的工具,是我自己写的,非常好用,如果大家有需要,不妨一试:https://ascii-tree.com/)
1 | my-app |
当我在terminal中使用tsc
命令编译项目时,顺利生成了add.js
文件, 于是我想,不如加上outDir
吧,于是我就加上了。
1 | { |
当我再次运行tsc
命令时,发现编译失败了,报错信息如下:
1 | No inputs were found in config file 'xxx/tsconfig.json'. Specified 'include' paths were '["**/*"]' and 'exclude' paths were '["xxx"]'. |
于是我把outDir
删除了,再次编译,又能成功编译了,太邪门了!索性去官网查了一下outDir
的详细说明: https://www.typescriptlang.org/tsconfig/#outDir
1 | If specified, .js (as well as .d.ts, .js.map, etc.) files will be emitted into this directory. The directory structure of the original source files is preserved; see rootDir if the computed root is not what you intended. |
这段话的大意是说:如果指定了outDir
,那么编译后的.js
文件会被输出到指定的目录中,并且会保留原始源文件的目录结构;如果没有指定outDir
,那么.js
文件会被输出到和.ts
文件相同的目录中。- 仔细看了两遍,没看出什么有用的信息。
后来问了一下Copilot,它说:outDir
指定的目录会自动加入exclude
中,也就是tsc不会编译该目录下的文件。这就说得通了,因为我指定了outDir
为./
,rootDir
为src/
,而src
目录是根目录的子目录,既然根目录被排除掉了,那么src
目录下的文件自然也会被排除掉,这相当于所有src
目录下的文件都不会参与编译!
所以我们最好将outDir
指定为一个和rootDir
没有任何交集的目录,通常我们指定为dist/
,也就是编译后的文件放在dist/
目录下,这样就不会和源文件有交集了。比如:
将outDir
改成了dist
, 再次编译,大功告成!
1 | { |
那么有人说了,如果我非要指定outDir
为./
呢?难道就没有办法编译了吗?当然不是,如果非要指定outDir
为./
,可以通过files
来指定需要编译的文件,因为files
指定的文件是不受exclude
选项影响的。
1 | { |
这样就可以编译了,当然你也可以指定多个文件,比如:
1 | { |
可是这样也有问题,随着项目的增大,文件会越来越多,而files
又不支持通配符,这导致我们需要将所有需要编译的文件都写到files
中,实在是太麻烦了。于是我们考虑用include
来指定需要编译的文件,比如将exclude设置为[],表示没有文件会被exclude。
1 | { |
但是运行tsc时你会发现,还是报错:error TS18003: No inputs were found in config file
, 为啥呢?因为outDir
指定的目录会自动加入exclude
中,outDir
指定的目录是./
,也就是项目的根目录,而src
目录是根目录的子目录,所以会被排除掉,导致报错。
我们可以通过显示指定exclude
来解决这个问题,比如:
1 | { |
结论
- 不指定
outDir
,tsc会在每个ts文件所在的目录生成对应的js文件。 - 指定
outDir
,tsc会在指定的目录生成对应的js文件。比如指定outDir
为dist/
,则会在dist/
目录下生成对应的js文件。 outDir
指定的目录会自动加入exclude
中,也就是tsc不会编译该目录下的文件。outDir
指定的目录必须和rootDir
不同,而且不能有交集,也就是不能有包含和被包含关系,否则会报错。- 当
outDir
和rootDir
有交集的时候,需要通过files
来指定需要编译的文件。注意不能使用include
,因为exclude
会排除掉outDir
目录下的文件。但是files
不受exclude
影响。