⚡ 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
  }
}
webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
点击侧边栏下一篇
折叠侧边栏
收起全部