⚡ 30 秒速记
- 用解析器找
import,不要靠正则猜依赖 - 模块表记录源码与依赖路径映射
- 运行时实现局部
require、module、exports - 模块缓存既防重复执行,也参与处理循环依赖
- 演示打包器先约束输入,不假装覆盖完整模块语义
小型打包器最值得实现的是“找依赖”和“执行模块”这两端。 构建时解析入口,把依赖递归收集成模块表,并把模块语法转换成运行时认识的形式;执行时通过局部 require 找到对应模块,再返回导出对象。加入缓存后,同一模块不必重复执行。但路径解析、循环依赖、资源类型和异步加载都需要额外设计,完成一个示例并不等于实现了完整的 webpack。
版本校准: 旧文中的 webpack 4、JSONP 更新清单或 react-hot-loader 代码用于解释历史链路,不应直接复制到新项目。当前 webpack-dev-server 4+ 默认启用 HMR,严格 ESM 可使用 import.meta.webpackHot;生产环境不得携带 HMR runtime。以 webpack HMR 官方指南 和项目锁定版本为准。
该工具可以实现以下两个功能
- 将
ES6转换为ES5 - 支持在
JS文件中import CSS文件
通过这个工具的实现,大家可以理解到打包工具的原理到底是什么
实现
因为涉及到
ES6转ES5,所以我们首先需要安装一些Babel相关的工具
yarn add babylon babel-traverse babel-core babel-preset-env
接下来我们将这些工具引入文件中
const fs = require('fs')
const path = require('path')
const babylon = require('babylon')
const traverse = require('babel-traverse').default
const { transformFromAst } = require('babel-core')
首先,我们先来实现如何使用 Babel 转换代码
function readCode(filePath) {
// 读取文件内容
const content = fs.readFileSync(filePath, 'utf-8')
// 生成 AST
const ast = babylon.parse(content, {
sourceType: 'module'
})
// 寻找当前文件的依赖关系
const dependencies = []
traverse(ast, {
ImportDeclaration: ({ node }) => {
dependencies.push(node.source.value)
}
})
// 通过 AST 将代码转为 ES5
const { code } = transformFromAst(ast, null, {
presets: ['env']
})
return {
filePath,
dependencies,
code
}
}