tsconfig.json文件说明

一般在typescript的项目中,我们都能看到tsconfig.json这个文件,它指定了此项目的编译选项,也指定了此项目的根目录,因此这个文件一般也是在项目的根目录下。既然如此,就单单typescript项目而言,它的编译一般有以下几种方式:

命令行直接输入tsc命令不带任何参数进行编译:

此时编译器会从当前目录开始查找tsconfig.json文件,如果当前目录没有发现该文件,则逐级向父级目录搜索。如果一直没有检索到该文件,编译器会给出使用提示。

命令行调用tsc带参数--project(或 -p)而指定一个目录:

编译器直接在该目录下查找tsconfig.json文件,如果没找到则报错。

命令行调用tsc后直接指定文件:

直接编译指定的文件。

各字段说明

tsconfig.json所包含的属性其实并不多,顶层属性只有几个。最重要的而且最多的应该属compilerOptions这个属性中的各个字段了。这个字段中的属性居多,而且中文官网讲述的很清晰。本篇文章重点来聊聊除此之外的顶层属性。

另外,需要注意的是,在命令行上指定的编译选项会覆盖在tsconfig.json文件里的相应选项。

1. files

数组类型,用于表示由ts管理的文件的具体路径,可以是相对或绝对路径。这些文件内部有依赖的模块(或者引入了哪些模块),编译器也会搜索到依赖模块进行编译。如果某些模块并没有在项目中引入,虽然在项目目录中也不会被编译。需要注意的是,files中不支持glob匹配模式的路径。

2. include 与 exclude

数组类型,include用于表示ts管理的文件。exclude用于表示ts排除的文件(即不被编译的文件)。其中的文件列表可以使用glob匹配模式列表,支持的glob通配符有:

*匹配0或多个字符(不包括目录分隔符)?匹配一个任意字符(不包括目录分隔符)**/递归匹配任意子目录

注意,这三者的优先级是这样的:files > exclude > include。如果不指定files,项目目录下的所有文件都会被编译器编译。如果同一个文件在三者中均指定,此文件一定会被编译器编译。而files中不指定而在exclude、include中同时指定的文件也会被编译,因为优先级是这样的exclude > include。另外,exclude默认情况下会排除node_modules,bower_components,jspm_packages和outDir目录。

3. compileOnSave

布尔类型,可以让IDE在保存文件的时候根据tsconfig.json重新生成编译后的文件。

4. extends

字符串类型,该值是一个路径,指定另一个配置文件用于继承tsconfig.json中的配置。在原文件里的配置最先被加载,原文件里的配置被继承文件里的同名配置所重写。 如果发现循环引用,则会报错。

5. typeAcquisition

对象类型,设置自动引入库类型定义文件。acquisition翻译过来是 “获得物、获得” 的意思。在整个项目中,如果存在用JavaScript写的库,ts会自动去compilerOptions.typeRoots指定的目录中寻找对应的类型声明文件。这个行为被称为typeAcquisition(类型获得)。这个行为可以通过enable来开启或关闭,且以库级别来指定应用的范围。但我在实践中,通过指定enable的值去控制这个行为并未有明显的感官,即使使用vscode修改配置后重启也并未生效。

当我使用jquery做测试的时候,将enable设为false且下载了@types/jquery的时候,vscode并未提示无法找到该声明,也无任何报错。但当我将其设为true,且删除@types/jquery时,vscode仍未提示无法找到该声明,鼠标悬浮引入的jquery提示在全局的typescript/3.8/node_modules/@types/目录下找到了该声明。

这个配置项在平时的开发中并不常用,大家也不必深究。

6. watchOptions

对象类型,typescript3.8以上新增加的配置,用来配置使用哪种监听策略来跟踪文件和目录。由于tsc的监听文件机制依赖于node的fs.watch/fs.watchFile。这两种方法的实现并不相同,前者是采用文件系统的事件做到通知,而后者使用轮询的机制。更多可以查阅node官方文档。

watchFile

字符串类型,配置单个文件的监听策略,必须为一下几个值:

useFsEvents(默认):采用系统的文件系统的原生事件机制监听文件更改

useFsEventsOnParentDirectory:采用系统的文件系统的原生事件机制监听修改文件所在的目录,这样修改一个文件实际上监听的是此文件所在的目录都被监听了,如此整个项目的文件监听器将显著减少,但可能导致监听并不准确。

dynamicPriorityPolling:创建一个动态队列去监听文件,修改频率较低的文件将被减少轮询监听的频率。

fixedPollingInterval:固定间隔的检查每个文件是否发生变化。

priorityPollingInterval:固定间隔的检查每个文件是否发生变化,但使用启发式监听的文件的检查频率要低于非启发式监听的文件。

watchDirectory

字符串类型,配置监听目录的策略,必须为以下几个值:

useFsEvents(默认)dynamicPriorityPollingfixedPollingInterval

以上三个和watchFile中相差不多

fallbackPolling

当采用系统的文件系统中原生事件机制监听文件时,此选项指定本机的文件监听器被耗尽或者不支持本机文件监听器是编译器采用的轮询策略,可以设置为以下几个值:

fixedPollingIntervaldynamicPriorityPollingpriorityPollingIntervalsynchronousWatchDirectory:禁用对目录的延迟监听。如果有大量的文件更改,比如在npm install时node_modules目录发生的变化,延迟监听是非常有用的。但总有些不常见的场景需要禁用延迟监听。

synchronousWatchDirectory

布尔类型,是否对目录延迟监听。如果配置为true,买手机号码当文件发生修改时同步的调用回调并更新目录监听器。

excludeFiles

字符串数组,用于指定不需要被监听变化的文件

excludeDirectories

字符串数组,用于指定不需要被监听变化的目录

7. reference

项目引用是TypeScript3.0的新特性,它支持将TypeScript程序的结构分割成更小的组成部分。

这是typescript官网中的描述,那怎么理解这句话呢。我们通过一个场景认识新出这种的reference特性。

假设我们要开发一个类似于lodash的工具库,并在项目中使用,而且后期很有可能还要在业界推广。为了保证这个工具的顺利开发及推广,我们必须要做相应的单元测试。那这个工具库可以看做一个项目,对其中的每个功能的测试也可作为一个独立的项目。但整个过程中,工具库的开发和测试应该是属于同一个项目下 “分项目” 的。那这种情况下reference就很棒了。首先我们搭一个目录出来:

|---- src/
|---- index.ts // 整个工具库的入口
|---- copyDeep.ts // 其中定义了copyDeep方法
|---- test/
|---- copyDeep.test.ts // copyDeep的单元测试
|---- package.json
|---- tsconfig.json

在copyDeep.test.ts中肯定要引用src/copyDeep,也就是说test的项目是依赖于src的。如果src中的代码发生了变化,整个工具库项目应该重新编译,而test项目不应该再被编译,这本来就是合理的。如果test项目中的代码发生了变化,那test项目应该被重新编译,而src项目不应该再被编译。如何在一个项目中配置而做到分别编译相应的子项目呢?首先最先想到的应该是在tsconfig.json文件中引入include字段配置,我们先尝试一下下面的配置:

{
"files": [
"./src/index.ts"
],
"include": [
"./test/**/*.test.ts"
],
"compilerOptions": {
"outDir": "./dist/"
}}

我们来分析这样配置的会有哪些问题:

首先,从整个项目层面,确实做到了修改任意文件重新编译的功能。但注意,编译的是全量的ts文件。随着日后项目的增大,在*.test.ts文件中引入也将逐渐变大。修改了src//**/*.ts的内容,test/**/*.ts也将作为输出,这是我们不希望看到的。

此时,reference将解决上述的每一个问题,我们修改项目结构如下:

|---- src/
|---- index.ts // 整个工具库的入口
|---- copyDeep.ts // 其中定义了copyDeep方法
|---- tsconfig.json // 工具库的编译配置文件
|---- test/
|---- copyDeep.test.ts // copyDeep的单元测试
|---- tsconfig.json // 测试的编译配置文件
|---- package.json
|---- tsconfig.json

并修改为以下配置:

// 根目录下的 /tsconfig.json{
"compilerOptions": {
"declaration": true, // 为子项目生成.d.ts声明文件
"outDir": "./dist",
}}// src目录下的 /src/tsconfig.json{
"extends": "../tsconfig",
"compilerOptions": {
"composite": true // 必须设置为true,表明该文件夹为一个子项目
}}// test目录下的 /src/tsconfig.json{
"extends": "../tsconfig",
"references": [
{ "path": "../src" } // 表示引用了工具库项目
]}

这样配置后,如果src项目已经编译完成并且输出了编译后的文件, 那在test项目中,实际加载的是src项目声明的.d.ts文件,而且这个声明文件是对test项目可见的。另外,如果开启了watch模式,修改了内容只会编译相应的项目而不会全量编译。这会显著的加速类型检查和编译,减少编辑器的内存占用。而且在代码结构层命有了一个很清晰的规划。

总结来讲,refrence的作用是将两个项目关联起来作为一个项目开发,当某个项目代码修改后还能单独编译相应的项目而不是整个项目。再说的简单点,就是实现了关联项目间的懒编译。

总结

本篇文章先到这里,总结一下:tsconfig.json这个文件是用来界定ts项目的根目录,也用来配置tsc在编译ts文件时的一些选项。files、exclude、include用来配置需要编译哪些文件;compilerOnSave是指定IDE保存后是否重新编译的;extends用来扩展当前的配置;扩展配置文件中的字段会覆盖当前文件的相同字段;typeAcquisition用来指定某些库的类型声明文件,如:

"typeAcquisition": {
"jquery": "@/types/jquery"}

watchOptions用来配置tsc的监听策略;reference指定关联项目,从而提高编译速度。

另外:

文中若有表述不妥或是知识点有误之处,欢迎留言批评指正,共同进步!

更多相关文章

  1. 聊聊springcloud项目同时存在多个注册中心客户端采坑记
  2. 详解ThinkPHP怎么实现图片上传
  3. 【前端】如何在vue项目中的utils.js封装防抖节流函数
  4. File、Blob、dataURL 和 canvas 的应用与转换
  5. 前端PDF文件转图片方法
  6. 如何开发一款前端工具
  7. 详解PHP使用OSS上传文件
  8. coreldraw破解版百度网盘附云盘补丁下载及序列号
  9. Python将CSV文件转化为HTML文件的操作方法

随机推荐

  1. Zend Framework 2:活动菜单项。
  2. 如何使用Javascript ajax发送网址? [重复]
  3. 解决Apache2+PHP上传文件大小限制的问题
  4. 如何在PHP 5.4.33 Apache服务器上启用mbs
  5. 解析错误:语法错误,E:\xampp\htdocs\on
  6. 访问控制允许原点 - 不工作
  7. 如何使用ChromePhp Logger记录数组
  8. 最佳做法,PHP,每天跟踪数百万次展示
  9. 使用PHP和MySQL开发“测试”Web应用程序
  10. 如何获取关联数组的当前元素数?