webpack实现原理

B站影视 韩国电影 2025-09-22 09:43 1

摘要:读取 webpack.config.js 配置文件。初始化 Compiler 对象(全局唯一,负责调度整个打包过程)。注册各种插件(plugins),把钩子函数挂载到生命周期。

好的,我来帮你系统梳理一下 Webpack 的实现原理。Webpack 本质上是一个 模块打包工具,它的核心思想就是:

一切资源皆模块,通过 依赖图(dependency graph) 把项目中各个模块串起来,最终打包成浏览器可运行的 bundle。

Webpack 的运行可以分为 初始化 → 编译 → 输出 三个阶段:

读取 webpack.config.js 配置文件。初始化 Compiler 对象(全局唯一,负责调度整个打包过程)。注册各种插件(plugins),把钩子函数挂载到生命周期。从入口开始
Webpack 根据 entry 找到入口文件,调用 loader 对代码做转换(比如 TS → JS,CSS → JS)。递归解析依赖使用 AST(抽象语法树)解析代码(依赖 @babel/parser 或 Acorn 等库)。找到 require / import 语句。把依赖的文件路径加入依赖图,继续递归编译。构建依赖图(Dependency Graph)
每个模块都会成为图中的一个节点,节点之间通过依赖关系连接起来。Loader 处理Loader 本质是一个函数,接收源代码字符串,返回处理后的代码。可以链式执行,比如:scss-loader → css-loader → style-loader。插件介入
插件通过 tapable 提供的钩子系统,在不同生命周期介入,例如:compilation:模块编译阶段emit:输出文件前done:构建完成(3) 输出根据依赖图,Webpack 把所有模块打包成一个或多个 bundle。bundle 内部会有一个 模块加载器(runtime),负责模拟 require 的功能,保证模块能在浏览器中按需加载。Webpack 不认识 import,需要 AST 分析。通过 AST 遍历,找到依赖路径,递归处理。

例子(简化版 AST 解析):

import a from './a.js';console.log(a);

Webpack 解析后会知道:main.js → a.js。

(2) 模块包装

Webpack 会把每个模块包装成一个函数,放到对象里,类似:

{'./src/index.js': function(require, module, exports) {const a = require('./a.js');console.log(a);},'./src/a.js': function(require, module, exports) {module.exports = 'hello webpack';}}

打包后的 bundle 里有个简易版的 require:

(function(modules) {function __webpack_require__(moduleId) {const module = { exports: {} };modules[moduleId].call(module.exports, __webpack_require__, module, module.exports);return module.exports;}return __webpack_require__('./src/index.js');})({'./src/index.js': function(require, module, exports) { ... },'./src/a.js': function(require, module, exports) { ... }});

这样浏览器里就能像 Node.js 一样运行模块了。

本质是一个函数,输入源码字符串,输出新代码。支持链式调用,顺序是 从右到左。module.exports = function(source) {return source.replace('var', 'let');}class MyPlugin {apply(compiler) {compiler.hooks.emit.tap('MyPlugin', compilation => {console.log('emit 阶段:生成文件前');});}}

Webpack 的核心原理就是:从入口文件出发 → 构建依赖图 → 把模块打包成一个 bundle,并通过 loader 转换资源、plugin 插入扩展能力,最终在浏览器里用 runtime 来模拟模块系统。

来源:阿橘的小九九

相关推荐