• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

TypeScript 模块加载机制

武飞扬头像
不怕麻烦的鹿丸
帮助1

一、TS 文件的加载策略

TS 中的加载策略分为两种方式,分别为相对路径绝对路径两种方式。

1、相对路径

TypeScript 将 TypeScript 源文件扩展名(.ts.tsx.d.ts)覆盖在 Node 的解析逻辑上。同时TypeScript 还将使用 package.json named 中的一个字段 types 来镜像目的"main",编译器将使用它来查找“主”定义文件以进行查阅。

  1.  
    // 假设当前执行路径为 /root/src/modulea
  2.  
     
  3.  
    import { b } from './moduleb'

此时,TS 对于 ./moduleb 的加载方式其实是和 node 的模块加载机制比较类似:

  • 首先寻找 /root/src/moduleb.ts 是否存在,如果存在使用该文件。
  • 其次寻找 /root/src/moduleb.tsx 是否存在,如果存在使用该文件。
  • 其次寻找 /root/src/moduleb.d.ts 是否存在,如果存在使用该文件。
  • 其次寻找 /root/src/moduleB/package.json,如果 package.json 中指定了一个types属性的话那么会返回该文件。
  • 如果上述仍然没有找到,之后会查找 /root/src/moduleB/index.ts
  • 如果上述仍然没有找到,之后会查找 /root/src/moduleB/index.tsx
  • 如果上述仍然没有找到,之后会查找 /root/src/moduleB/index.d.ts

可以看到 TS 中针对于相对路径查找的规范是和 nodejs 比较相似的。

Ts 在寻找文件路径时,在某些条件下是会按照目录去查找 .d.ts 的。

2、绝对路径

  1.  
    // 假设当前文件所在路径为 /root/src/modulea
  2.  
     
  3.  
    import { b } from 'moduleb'
  • /root/src/node_modules/moduleB.ts
  • /root/src/node_modules/moduleB.tsx
  • /root/src/node_modules/moduleB.d.ts
  • /root/src/node_modules/moduleB/package.json(如果它指定了一个types属性)
  • /root/src/node_modules/@types/moduleB.d.ts
  • /root/src/node_modules/moduleB/index.ts
  • /root/src/node_modules/moduleB/index.tsx
  • /root/src/node_modules/moduleB/index.d.ts

typescript 针对于非相对导入的 moduleb 会按照以上路径去当前路径的 node_modules 中去查找,如果上述仍然未找到。

此时,TS 仍然会按照 node 的模块解析规则,继续向上进行目录查找,比如又会进入上层目录 /root/node_modules/moduleb.ts ...进行查找,直到查找到顶层 node_modules 也就是最后一个查找的路径为 /node_modules/moduleB/index.d.ts 如果未找到则会抛出异常 can't find module 'moduleb'

上述查找规则是基于 tsconfig.json 中指定的  moduleResolution:node,当然还有  classic 不过  classic 规则是 TS 为了兼容老旧版本,现代代码中基本可以忽略这个模块查找规则。

3、解析 *.d.ts 声明

日常开发中,有这样一种场景,在 TS 项目中我们需要引入一些后缀为 png 的图片资源,那么此时 TS 是无法识别此模块的。

解决方法也非常简单,通常我们会在项目的根目录中也就是和 tsconfig.json 平级的任意目录中添加对应的声明文件 image.d.ts

  1.  
    // image.d.ts
  2.  
     
  3.  
    declare module '*.png' {
  4.  
    const src: String;
  5.  
    export default src;
  6.  
    }
import logo from './assets/logo.png'

可以看到,通过定义声明文件的方式解决了我们的问题。

3.1 typescript模块加载机制是怎么查找到定义在项目目录中的 image.d.ts 呢?

本质上我们引入任何模块时,加载机制无非就是我们上边提到的两种加载方式。

不过,这里有一个细小的点即是 ts 编译器会处理 tsconfig.json 的 file、include、exclude 对应目录下的所有 .d.ts 文件:

简单来说,ts 编译器首先会根据 tsconfig.json 中的上述三个字段来加载项目内的 d.ts 全局模块声明文件,自然由于 '.png' 文件会命中全局加载的 image.d.ts 中的 声明的 module 所以会找到对应的文件。

include 在未指定 file 配置下默认为  **,表示 tsc 解析的目录为当前 tsconfig.json 所在的项目文件夹。

关于 file、include、exclude 三者本质上都是针对于 TSC 编译器处理的范围。
  1.  
    // tsconfig.json
  2.  
     
  3.  
    {
  4.  
    "compilerOptions": {
  5.  
    "outDir": "build/dist",
  6.  
    "module": "esnext",
  7.  
    "target": "esnext",
  8.  
    "lib": ["esnext", "dom"],
  9.  
    "sourceMap": true,
  10.  
    "baseUrl": ".",
  11.  
    "jsx": "react-jsx",
  12.  
    "resolveJsonModule": true,
  13.  
    "allowSyntheticDefaultImports": true,
  14.  
    "moduleResolution": "node",
  15.  
    "forceConsistentCasingInFileNames": true,
  16.  
    "noImplicitReturns": true,
  17.  
    "noImplicitAny": false,
  18.  
    "suppressImplicitAnyIndexErrors": true,
  19.  
    "noUnusedLocals": true,
  20.  
    "allowJs": true,
  21.  
    "skipLibCheck": true,
  22.  
    "experimentalDecorators": true,
  23.  
    "strict": true,
  24.  
    "paths": {
  25.  
    "@/*": ["./src/*"],
  26.  
    "@@/*": ["./src/.umi/*"]
  27.  
    }
  28.  
    },
  29.  
    "include": [
  30.  
    "mock/**/*",
  31.  
    "src/**/*",
  32.  
    "playwright.config.ts",
  33.  
    "tests/**/*",
  34.  
    "test/**/*",
  35.  
    "__test__/**/*",
  36.  
    "typings/**/*",
  37.  
    "config/**/*",
  38.  
    ".eslintrc.js",
  39.  
    ".stylelintrc.js",
  40.  
    ".prettierrc.js",
  41.  
    "jest.config.js",
  42.  
    "mock/*"
  43.  
    ],
  44.  
    "exclude": ["node_modules", "build", "dist", "scripts", "src/.umi/*", "webpack", "jest"],
  45.  
    "files": []
  46.  
    }
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbckia
系列文章
更多 icon
同类精品
更多 icon
继续加载