今天在玩耍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影响。