模块解析策略

831 阅读3分钟

模块分类

  • 文件模块
  • 第三方模块
  • 核心模块

模块解析步骤

1、 路径分析
2、 文件定位
3、 编译执行

模块引入方式

非相对导入的模块路径开头一定要有./或../或者/,反之会当做核心模块或者第三方模块来解析

  • 相对导入
const test = require('test')

import test from 'test'
  • 非相对导入(相对路径形式)
const test = require('./test')

import test from './test'

node模块解析策略

node模块分类

1、核心模块
2、第三方模块
3、文件模块(路径模块)

node路径解析

1、核心模块

核心模块在node编译阶段被加载进来,所以核心模块不需要路径解析和文件定位

2、第三方模块

从当前目录的 node_modules 下查找,如果没有就去查找父级直到找到或到根目录也找不到为止

3、文件模块(路径模块)

直接根据指定的路径查找,require在加载模块时会把路径转化为硬盘上的真实路径,并且用这个路径作为索引将编译的结果进行缓存(索引: 文件名, 值: 模块对象)

node文件定位

路径分析完成,开始文件定位。对于核心模块不需要文件定位,文件模块(路径模块)和第三方模块定位规则相同

1、文件模块(路径模块)

/**
带扩展名
1、有则命中,反之报错
*/ 
require('./test.js') 

/**
不带扩展名
1、在命中的目录下按照.js、.node、.json的顺序逐一尝试
2、先以省略扩展名的声明形式来文件定位,如果没命中,则以不指定最终文件名定位,再没命中,才会报错。
*/ 
require('./test') 

/**
不指定最终文件名
首先会在命中的目录下寻找package.json这个文件,并取出json文件中的main属性的值,作为命中的文件 如果找不到package.json或对应的main属性,则会用index作为文件名,而后依旧按照.js、.node、.json顺序去尝试,如果未命中则报错
*/
require('./test') 

2、第三方模块

/**
不指定最终文件名
首先会在命中的目录下寻找package.json这个文件,并取出json文件中的main属性的值,作为命中的文件 如果找不到package.json或对应的main属性,则会用index作为文件名,而后依旧按照.js、.node、.json顺序去尝试,如果未命中则查找上一层目录下的node_modules继续找,直至命中或再无上一层
*/
require('test') 

node核心模块和第三方模块加载优先级

优先加载核心模块

node模块加载优化

所有文件只要被引用过一次,就会被缓存起来。下一次引用时,会先检查缓存中有没有对应的文件

ts模块解析策略

ts文件选择优先级

.ts > .tsx > .d.ts

ts解析策略

1、文件模块(路径模块)

/**
带扩展名
1、有则命中,反之报错
*/ 
import test from './test.ts'

/**
不带扩展名
1、在命中的目录下按照.ts、.tsx、.d.ts的顺序逐一尝试
2、先以省略扩展名的声明形式来文件定位,如果没命中,则以不指定最终文件名定位,再没命中,才会报错。
*/ 
import test from './test'

/**
不指定最终文件名
首先会在命中的目录下寻找package.json这个文件,并取出json文件中的types属性的值,作为命中的文件 如果找不到package.json或对应的types属性,则会用index作为文件名,而后依旧按照.ts、.tsx、.d.ts顺序去尝试,如果未命中则报错
*/
import test from './test'

2、第三方模块

/**
不指定最终文件名
首先会在命中的目录下寻找package.json这个文件,并取出json文件中的types属性的值,作为命中的文件 如果找不到package.json或对应的types属性,则会用index作为文件名,而后依旧按照.ts、.tsx、.d.ts顺序去尝试,如果未命中则查找上一层目录下的node_modules继续找,直至命中或再无上一层
*/
import test from 'test'