亮神知识库 亮神知识库
首页
  • 手写代码

    • 手写代码系列
  • 基础知识

    • 基础
    • JS底层
    • CSS
  • 原理
  • 浏览器
  • HTTP
  • 网络安全
  • babel
  • webpack基础
  • webpack进阶
  • Vite
  • TypeScript
  • Vue2
  • Vue3
  • Node基础

    • glob
    • 模块化机制
    • 事件循环
    • KOA2框架原理
    • Node子进程
    • cluster原理(了解)
  • 教育行业2021

    • B端
    • C端
    • 工具
  • 游戏行业2025
  • 刷题
  • 杂(待整理)
  • 学习
  • 面试
  • 实用技巧
  • 心情杂货
  • 年度总结
  • 友情链接
关于
  • 分类
  • 标签
  • 归档
  • 收藏
GitHub (opens new window)

亮神

前程明亮,未来可期
首页
  • 手写代码

    • 手写代码系列
  • 基础知识

    • 基础
    • JS底层
    • CSS
  • 原理
  • 浏览器
  • HTTP
  • 网络安全
  • babel
  • webpack基础
  • webpack进阶
  • Vite
  • TypeScript
  • Vue2
  • Vue3
  • Node基础

    • glob
    • 模块化机制
    • 事件循环
    • KOA2框架原理
    • Node子进程
    • cluster原理(了解)
  • 教育行业2021

    • B端
    • C端
    • 工具
  • 游戏行业2025
  • 刷题
  • 杂(待整理)
  • 学习
  • 面试
  • 实用技巧
  • 心情杂货
  • 年度总结
  • 友情链接
关于
  • 分类
  • 标签
  • 归档
  • 收藏
GitHub (opens new window)
  • babel

  • webpack基础

  • webpack深入

    • 源码深入
    • 手写简易webpack
      • 流程
      • 代码解析
    • webpack-loader机制
    • webpack插件机制
    • webpack模块加载原理
    • 懒加载(未完全理解)
    • 热更新原理
    • webpack proxy原理
  • Vite

  • TypeScript

  • 打包工具
  • webpack深入
0zcl
2021-12-18
目录

手写简易webpack

# 流程

zcl-pack

# 代码解析

配置文件, 只要入口和出口就够了

module.exports = {
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'main.js'
  }
}
1
2
3
4
5
6
7

compiler.js

class Compiler {
  constructor(options) {
    const { entry, output } = options
    this.entry = entry
    this.output = output
    this.modules = []
  }

  run() {
    const entryModule = this.buildModule(this.entry, true)
    this.modules.push(entryModule)
    this.modules.map(_module => {
      _module.dependencies.map(dependency => {
        this.modules.push(this.buildModule(dependency))
      })
    })
    this.emitFiles()
  }
  
  buildModule(filename, isEntry) {
    let ast
    if (isEntry) {
      ast = getAST(filename)
    } else {
      let absolutePath = path.join(process.cwd(), './src', filename)
      ast = getAST(absolutePath)
    }
  
    return {
      filename,
      dependencies: getDependencies(ast),
      transformCode: transform(ast)
    }
  }

  emitFiles() {
    // ......
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

parse.js模块, 实现三个功能,生成AST语法树、traverse遍历、代码转换。parseSync (opens new window), transformFromAst (opens new window)

const babel = require('@babel/core')
const traverse = require('@babel/traverse').default
const fs = require('fs')

module.exports = {
  getAST: (path) => {
    const content = fs.readFileSync(path, 'utf-8')
    return babel.parseSync(content)
  },
  getDependencies: (ast) => {
    const dependencies = []
    traverse(ast, {
      ImportDeclaration: ({ node }) => {
        dependencies.push(node.source.value)
      }
    })
    return dependencies
  },
  transform: (ast) => {
    const { code, map } = babel.transformFromAst(ast, null, {
      'presets': ['@babel/preset-env']
    })
    console.log('code', code)
    console.log('map', map)
    return code
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

附Github (opens new window), parse模块需要对AST和Babel有一定了解,看不懂可以先看babel原理

编辑 (opens new window)
上次更新: 2025/07/20, 06:21:22
源码深入
webpack-loader机制

← 源码深入 webpack-loader机制→

最近更新
01
2024年
07-20
02
2023年
07-20
03
2022年
07-20
更多文章>
Theme by Vdoing | Copyright © 2025-2025 亮神 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式