typescript 配置精讲 | moduleResolution

大家好,我是17。

moduleResolution 是 typescript 模块配置中最重要的一个配置,所以 17 单拿出来讲一下。如果你去看文档还是挺复杂的,但如果不去深究细节,只想知道如何配置还是很简单的。3 分钟就能学会。

moduleResolution 的作用

moduleResolution 是用来解决如何查找文件的。比如

import name from 'iam17'

这条语句首先要做的就是把 iam17 对应的文件找到。如何查找文件受到 moduleResolution 配置的景响。

配置 moduleResolution

为打包器量身定做的 Bundler 选项

前端主要的场景是使用 typescript 做类型检查,并不输出内容。把 ts 转换成 js 的工作是由打包工具来完成的。这种情况下,把 moduleResolution 设置为 Bundler 就行了。Bundler 的原意就是打包器的意思。现在流行的打包器 webpack,vite 等支持的特性,Bundler 选项都支持。Bundler 选项就是为打包工具量身定做的。

专为 node 开发的 node16 选项

还有一部分的前端开发场景是进行 nodejs 开发。最终的代码的运行环境是 node 环境。这个时候把 moduleResolution 设置为 node16 就行了。

其它的选项

之所以剩下的都归为其它,是因为其它的使用场景很少,了解即可。

如果不得不使用 node 老版本,只能用 Node10 选项了,也可以用 Node。 Node10 和 Node 是一个意思,可以认为是一个选项有两个名字。ts 5.0 中,把 Node rename 成了 Node10,为了让原来的配置文件有效,保留了 Node 选项。

NodeNext 目前等同于 Node16。如果之后有 Node17,那么 NodeNext 就等同于 Node17。NodeNext 总是指向 node 环境的最新配置。

还有一个选择 Classic。Classic 虽然还在出镜,但也仅限于名字本身了,几乎不会有使用的场景。ts 已经明确说明,在下个版本会移出 Classic 选项。各们同学就当他不存在就好。

到这里,如何配置 moduleResolution 就讲完了。这对于 99% 的同学来说已经够用了。但是作为 1% 的同学,还想有更高的追求,就需要了解一下配置的细节。比如 17 想写一个打包工具,不知道 ts 执行的细节 ,怎么和 ts 配合啊。就算没有写工具的需求,如果哪天 ts 报错了,总得知道怎么修改配置吧。还有一个理由,如果你去面试,问你 moduleResolution 的执行细节呢?虽然开发的时候用不到,但面试的时候不都是要求你会靠火箭的吗?其实呢,面试官也知道平时不用,这只是个加分项,可能是想知道你是不是爱学习。所以同学们,系好安全带,准备出发吧!

说到细节,首先要知道这些选项都是怎么来的,然后再理解这些选项都做了什么就水到渠成了。还要认清 TypeScript 的定位,TypeScript 是为了让 js 更加强大,更加好用,TypeScript 最终还是要编译成 js 才能用。所以在各个历史时期,ts 都是配合 js。对于解析文件路径,TypeScript 几乎总是从其输出JavaScript 文件的角度来考虑这些问题,而不是从其输入TypeScript(或 JavaScript!)文件的角度来考虑这些问题。

在解释这些查找细节之前,首先需要了解一下,ts 是如何自动补充文件名扩展名,自动解析文件夹模块的。

文件扩展名自动补充

import name from './iam17'
import name from './iam17.js'

两条语句一条带扩展名,一条不带,对于 ts 来说,.js 扩展名可以省略,

不带扩展名,和带 .js 扩展名, ts 查找相关文件策略是一样的。

ts 拿到文件名 iam17 后,会查找相关的文件。分两步

  1. 查找相关的类型文件,看有没有 iam17.ts,iam17.tsx,iam17.d.ts
  2. 查找相关的 js 文件,看有没有 iam17.js,iam17.jsx

ts 是会优先查找类型文件,如果没有类型文件才去查找 js 文件。

如果扩展名是 mjs

import name from './iam17.mjs'

ts 要查找的文件有所不同

  1. 查找相关的类型文件,看有没有 iam17.mts,iam17.d.mts
  2. 查找 iam17.mjs

如果扩展名是 cjs

import name from './iam17.cjs'

ts 要查找的文件为

  1. 查找相关的类型文件,看有没有 iam17.cts,iam17.d.cts
  2. 查找 iam17.cjs

如果只有类型文件,没有 js 文件,ts 会报错吗?答案是不会。

目录模块

还是这条语句

import name from './iam17'

如果不带后缀名,ts 除了查找相关的文件外,还会检查 iam17 是不是一个文件夹。

如果 iam17 是一个文件夹,会解析根目录下的 package.json 文件。

  1. 解析 package.json 中的 types
  2. 解析 package.json 中的 typings
  3. 解析 package.json 中的 main

如果上面 3 步都找不到,查找根目录下的 index.ts,index.d.ts,index.tsx,index.js。

总的来说,也是先查找类型文件,找不到类型文件,再查找 js 文件。

typings 是历史遗留,不要使用

types 和 typings 直接指定类型文件。 main 指定 js 文件,ts 找到 main 指定的 js 文件后还会根据补充文件扩展名的规则查找类型文件。

有了 文件扩展名补充 和 文件夹模块 这两个基础知识,再理解 ts 的文件查找逻辑就容易多了。

选项 Classic

Classic 是第一个 moduleResolution 选项。因为已经几乎没有使用的场景,所以直接忽略。

选项 Node

当 nodeJs 的 commonJs 模块标准逐渐成为主流标准的时候,ts 适时的给出 node 选项。听这个名字就知道,ts 查找文件的方式和 nodeJs 差不多。因为 ts 有类型,所以在查找上,ts 是优先查找类型文件,其次才是查找实际的 js 文件。查找逻辑分下面几种

  1. 绝对路径
  2. 相对路径
  3. 安装包路径
  4. node 核心模块

绝对路径

以 / 开头的就是绝对路径。绝对路径是磁盘上的绝对物理路径。

import name from '/root/home/iam17'

ts 会判断 iam17 是文件夹还是文件,如果是文件夹就按文件夹模块查找,如果是文件,就按文件扩展名补充查找。

如果后面有扩展名,不会执行文件模块查找。

相对路径

项目内的模块必须用 前导 './' 或 '../' 来指示相对路径。

import name from './iam17'

ts 会以当前文件为基准进行查找。ts 会判断 iam17 是文件夹还是文件,如果是文件夹就按文件夹模块查找,如果是文件,就按文件扩展名补充方案查找。

如果后面有扩展名,不会执行文件模块查找。

安装包路径

如果没有前导 '/''./' 或 '../' 来指示文件,该模块会从 node_modules 文件夹加载。

import name from 'iam17'

ts 还是会优先查找 iam17 的类型声明,然后才是查找 js 文件。类型声明会先从模块中查,查不到,再到 @types/iam17 中查。

在模块中查找过程和 文件夹模块 查找逻辑一样。

和文件夹模块不同的是,ts 查找 node_modules 中的模块首先会在当前目录查,如果查不到,要到上级的 node_modules 目录查,直到根目录下的 node_modules。

node 选项还可以随意查找子路径 比如 import name from ‘iam17/work’

node 核心模块

ts 并不认识哪些是 node 核心模块。ts 会当普通模块处理,解决办法就是安装 node 类型声明

 npm install @types/node

typesVersions

如果你需要在多个 ts 版本中进行开发,可能需要多个版本的声明文件,因为不同版本 ts 的声明文件可能是不兼容的。

{"name": "pkg","version": "1.0.0","types": "./index.d.ts","typesVersions": {">=3.1": {"*": ["ts3.1/*"]}}
}

了解下即可,一般不会遇到需要配置 typesVersions 的情况。这种只是用来应急的,如果把它当作常态,你需要反思下项目管理了。

选项 Node16,NodeNext

typeScript 4.7 增加了 Node16,NodeNext 这两个选项,因为这个时期 ESM 模块已经成为标准。和 Node 选项相比,在解析路径方面新增加两条规则,删除了两条规则。

增加了 package.json “exports”

当 moduleResolution 设置为 node16, nodenext, or bundler,并且 resolvePackageJsonExports(tsconfig.json 中的配置)没有设置为 false,ts 会解析 package.json 的 “exports” 信息。

当 moduleResolution 设置为 node16, nodenext, or bundler 的时候,resolvePackageJsonExports 默认是开启的。为什么 ts 要增加 resolvePackageJsonExports 这个配置。原因是为了照顾老项目。
resolvePackageJsonExports 了解一下即可,一般不需要手动修改它。

关于 exports 详细规范大家可以去 node 官网上去查,17 贴心的直接给出地址 点这里查看 export 详情

在 node exports 规范的基础上,ts 还会查找 types ,default 两个用户导出条件。关于用户导出条件可以看我写的上一篇文章 typescipt 配置精讲 | customConditions

增加了 package.json “imports” and self-name imports

当 moduleResolution 设置为 node16, nodenext, or bundler,并且 resolvePackageJsonImports(tsconfig.json 中的配置)没有设置为 false,ts 会解析 package.json 的 “exports” 信息。

当 moduleResolution 设置为 node16, nodenext, or bundler 的时候,resolvePackageJsonImports 默认是开启的。resolvePackageJsonImports 也是为了照顾老项目设置的。

resolvePackageJsonImports 了解一下即可,一般不需要手动修改它。

详情可以参阅 ts 文档,点这里

简单来说 #imports 相当于是给子路径起了一个别名。先查找 package.json,找到 imports,再找到相应的 key,根据 key 的内容去查找类型。了解下即可。

删除了文件扩展名自动补充

因为 在 node 的 ESM 模块中,引用模块是必须要写文件扩展名。

import name from './iam17'

这样写会报错,必须要补全后面的 .js,这样写才行:./iam17.js

删除了目录模块的支持

设置为 node16 后,ts 不再进行文件夹模块的尝试。

node 在 ESM 模块下,找不到文件就会报错,不再做其它尝试。 ts 也只是查找相关的类型文件,找不到就报错。

17 觉得 ESM 要求明确写出扩展名是个好事,这样会大大简化查找文件的逻辑。但是,这只能是一个理想,因为目前已经存在的老项目都是没写扩展名的。这就导致 Node16 只能在新项目里用。很多同学都习惯了不写扩展名,现在让他们写扩展名,会觉得不习惯。最后的结果就是新项目也没人愿意用 Node16。

Bundle 选项

由于 Node16 让很多同学不习惯,所以 ts 在 5.0 又推出了 Bundle 选项。反正有打包工具打底,Bundle 选项索性支持所有特性,把文件扩展名自动补充,目录模块的规则又加了回来,也支持 “imports”,“exports"。

到这所有选项就讲完了,可是路径解析的故事还没有结束,小伙伴们再坚持一下,马上到终点了。

虽然本篇文章讲的是 moduleResolution 配置,但如果不讲 paths,baseUrl,typeRoots,types 和全局类型声明,ts 的路径解析逻辑是不完整的。

paths,全局路径映射

如果每次都写相对路径还是很不方便的,这时可以用 paths 简化。

{"compilerOptions": {"module": "esnext","moduleResolution": "bundler","paths": {"@/*": ["./src/*"]}}}

有了这个配置后,就可以这样写路径了,无论是在哪个文件里

import name from '@/iam17'

无论是哪个文件里,都会被解析成到项目根目录/src/iam17。这个配置还是挺常用的,实际项目里,一般都会加上这样的配置。

更多 paths 的详情 点这里查看

注意:如果不打算用打包工具,不要用 paths 配置,ts 不会对 path 设置的映射做转换

baseUrl

这是历史遗留的产物,不要使用,同学们当它不存在就好。

如果想了解一下详情,可以 看这里

typeRoots

ts 首先会查找类型文件,在模块里查不到会到 @types 目录去查,这个@types 就是默认的 typeRoots,一般不需要修改 typeRoots, 了解下就好。查看详情

types

types 相当于一个白名单,只有加入白名单的模块, ts 才会到 typeRoots 中查找。types 限制了 ts 在 typeRoots 中的查找范围。一般也不会用到这个配置,了解下就好。里查看详情

全局类型声明

在项目中,如果在 ts , .d.ts 文件中没有 import ,export 语句,文件中定义的类型就会成为全局的类型。以这种方式定义的模块全局可用。

用 declare module 来定义模块。这个定义是全局的。

在项目中添加 index.d.js

declare module 'iam17' {const name: stringexport default { name }
}

在项目中的任意 .ts 文件中都可以解析到 iam17 模块

image.png

本文到这里就结束了,撤花~

参考

  • CommonJS 模块
  • ECMAScript 模块
  • TS Modules - Reference

番外

17 觉得,随着时间的推移,Node,Node10 两个选项可能会被移除。就和 Classic 的结局一样,它们都只是过渡值,最终肯定是 ESM 模块一统天下。

对于 ESM 规定必须写文件后缀名这事,17 是非常赞同的。只是使用者不会管你后面的逻辑有多复杂,用着爽就好。所以虽然规范不再支持,但打包工具依然会把这个逻辑补充上。如果一直这样,不知道后面规范会不会把自动补后缀名的逻辑再加回来。

如果不考虑历史原因,js 模块路径解析也并不复杂。 但 js 曾经的模块方案终究还是留下了自己的印记。

17 花了两天,周末都在写。本来打算半天就写好了,但实际上内容特别繁杂。如果你一直扎进文档,可能会越看越晕,所以 17 写这篇文章进行梳理。关于解析路径的内容很多,如果都放上,那就成一本书的规模了。多数内容文档上都有,没必要搬来搬去的。17 尽量压缩内容,但保证所有关键点都写到,让大家在最短的时间内对 ts 路径解析有一个整体的把握。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/16617.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32无源蜂鸣器播放音乐

开发板:野火霸天虎V2 单片机:STM32F407ZGT6 开发软件:MDKSTM32CubeMX 文章目录 前言一、找一篇音乐的简谱二、确定音调三、确定节拍四、使用STM32CubeMX生成初始化代码五、代码分析 前言 本实验使用的是低电平触发的无源蜂鸣器 无源蜂鸣器是…

【模拟面试问答】深入解析力扣163题:缺失的区间(线性扫描与双指针法详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣! 推荐:数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航: LeetCode解锁100…

华为OD机试 - 寻找最富裕的小家庭(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷C卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试…

C语言对一阶指针 二阶指针的本质理解

代码&#xff1a; #include <stdio.h>char a 2; char* p &a; char** d &p;int main(){printf("a -> %d, &a -> %p\n", a, &a);printf("*p -> %d, p -> %p, &p -> %p\n", *p, p, &p);printf(&qu…

【JavaEE初阶】网络初识|局域网和广域网|交换机和路由器|IP地址|端口号

&#x1f4a1;推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击跳转到网站】 关键概念 1.局域网LAN和广域网WAN &#xff08;1&#xff09;局域⽹&#xff0c;即Local Area Network&#xff0…

嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

【代码随想录】动态规划经典题

前言 更详细的在大佬的代码随想录 (programmercarl.com) 本系列仅是简洁版笔记&#xff0c;为了之后方便观看 做题步骤 含义公式初始化顺序检查 确定dp数组以及下标的含义递推公式dp数组如何初始化遍历顺序打印dp数组&#xff08;看哪里有问题&#xff09; 斐波那契数 c…

乐理学习-音及音名

1. 我觉得练习题很重要。我要得到一个反馈 所以我想没学习完书中的一节就要把练习题做下来&#xff0c;虽然慢点也可以。 2. 做个小计划。 今天计算了一下学完《基本乐理-李重光》如果每天3张。也要80天干完&#xff0c;希望能有一天可以学习7张的速度的时候。 3. 练习记录…

STM32H7系统窗口看门狗 (WWDG)应用方法介绍

目录 概述 1 认识窗口看门狗 (WWDG) 1.1 窗口看门狗定义 1.2 WWDG 主要特性 2 WWDG 功能说明 2.1 WWDG框图 2.2 WWDG 内部信号 2.3 控制递减计数器 2.4 看门狗中断高级特性 2.5 如何设置看门狗超时 3 WWDG 寄存器 3.1 控制寄存器 (WWDG_CR) 3.2 配置寄存器 (W…

MicroLED:苹果对知识产权的影响

Yole的洞察揭示&#xff0c;MicroLED IP在经历了七年的爆炸式增长后&#xff0c;已然屹立于行业之巅。苹果公司&#xff0c;作为微LED领域的先行者&#xff0c;早在2014年便敏锐地捕捉到Luxvue这家初创公司的潜力&#xff0c;将其纳入麾下&#xff0c;引发了业界的广泛关注。然…

【Springboot系列】SpringBoot 中的日志如何工作的,看完这一篇就够了

文章目录 强烈推荐引言Spring Boot 中的日志是怎么工作日志框架选择配置文件日志级别自定义日志配置集成第三方日志库实时监控和日志管理 Log4j2工作原理分析1. 核心组件2. 配置文件3. Logger的继承和层次结构4. 日志事件处理流程5. 异步日志 总结强烈推荐专栏集锦写在最后 强烈…

每日练习之矩阵乘法——斐波那契公约数

斐波那契公约数 题目描述 运行代码 #include <iostream> #include <vector> using namespace std; const long long mod 1000000007;// 矩阵乘法函数 vector<vector<long long>> matrixMultiply(const vector<vector<long long>>& …

移动端特效

一&#xff0c;触屏事件 1.触屏touch事件 2.触摸事件对象 如果侦听的是一个DOM元素&#xff0c;他俩是一样的 如果手指离开了&#xff0c;不能侦听到前两者&#xff0c;能侦听到第三个 我们一般都是触摸元素&#xff0c;所以一般都是第二个比较常用 第一个&#xff1a;屏幕…

Leetcode 力扣92. 反转链表 II (抖音号:708231408)

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a;[1,4,3,2…

简单的基于信号处理的心电信号ECG特征波分割方法(MATLAB)

正常的心电图中&#xff0c;每个心跳周期内包含三个主要的特征波&#xff1a;&#xff30;波、QRS波和&#xff34;波&#xff0c;如下图所示。心电特征波能够反映心脏的生理状态信息&#xff0c;通过对其形状、幅值和持续时间的分析&#xff0c;可以用来辅助诊断心血管疾病。对…

vs2019 c++20 规范的 STL 库的智能指针 shared、unique 、weak 及 make_** 函数的源码注释汇总,和几个结论

智能指针的源码都在 《memory》 头文件中。因为头文件太长&#xff0c;再者本次整理是基于以前的零散的模板分析。故相当于抽取了该头文件中关于智能指针的源码进行分析&#xff0c;注释。 &#xff08;1 探讨一&#xff09;当独占指针指向数组时&#xff0c;其默认的删除器是…

mysql表约束基础 【default | 主键 | 外键 | 唯一键】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;MySQL之旅_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;表的约…

vue3快速入门(局部使用)

目录 前置知识JavaScript-导入导出 入门操作 变量渲染页面 局部使用vue的实现步骤 vue指令 v-for v-bind v-if v-show v-on v-model 生命周期 前置知识JavaScript-导入导出 正常情况在html导入js文件是全部导入&#xff0c;这样会导致性能上的损失 。 JS提供的…

STM32F1之OV7725摄像头·SCCB总线代码编写附带源码详解

STM32F1之OV7725摄像头-CSDN博客 STM32F1之OV7725摄像头像素数据输出时序、FIFO 读写时序以及摄像头的驱动原理详解-CSDN博客 目录 1. 硬件设计 1.1 SCCB 控制相关 1.2 VGA 时序相关 1.3 FIFO 相关 1.4 XCLK 信号 2. 代码设计 2.1 SCCB总线软件实现 2.1.1 宏定…

AI图书推荐:ChatGPT解码—人工智能增强生活指南

《ChatGPT解码—人工智能增强生活指南》&#xff08;ChatGPT Decoded. A Beginners Guide to AI-Enhanced Living &#xff09;是一本由 大卫维恩斯&#xff08;David Wiens &#xff09;所著的书籍&#xff0c;旨在帮助读者了解并有效利用GPT-4语言模型这一强大工具来提升日常…