webpack 作为前端工具的重要一环,在webapck4中已经极大的简化了开发者的运营成功,但是对于webpack更加深入的了解;现在让我们一起来从底层来解读webpack.
# 运行机制与核心工作原理
# 项目的的整体结构
首先这里我们配置一个简单的webpack.config.js;
// import { Configuration } from 'webpack'
const HtmlWbapckPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
/**
* @type {Configuration}
*/
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js'
},
plugins: [
new HtmlWbapckPlugin({
template: './public/index.html',
filename: 'index.html'
}),
new CleanWebpackPlugin()
]
}
接下来我们执行
npx webpack
我们对打包后的文件进行拆解分析
打包后生成一个自执行函数,我们来看一下这个自执行函数
首先分析入口函数,它几首一个modules参数,调用的时候传入一个数组,我们可以看到传入进来的是一个对象。
然后再return中会找到我们对应的入口文件解析,开始webpack的工作。
# loader 运行机制
这里我们创建一个markdown-loader.js的文件,然后再module中引入
// webpackconfig.js
module: {
rules: [
{
test: /\.md$/,
use: './markdown-loader'
}
]
}
// markdown-loader.js
module.exports = source => {
console.log(source)
return "console.log('hello loader~')"
}
当匹配到到文件后缀名为**.md**的时候就会进入这个js文件,那为什么我需要返回一个js 格式的字符串呢?
这是因为webpack内部默认只能够处理JS模块代码,说白了,就是它默认把所有的文件都当成js代码来解析了。当然我们可以从后往前进行处理多个loader,最后到达webpack 输出打包文件

有一个比较有意思的地方,用过webpack都知道,加载css的时候需要加载css-loader,而且还需要加载style-loader
为什么要加载两个呢?可以阅读打包后的源码得知。
- css-loader 只会把 CSS 模块加载到 JS 代码中,而并不会使用这
- style-loader 会调用响应生成得css内容
# plugin 运行机制
webpack 相比loader的管道机制,plugin的作用或许来说更大,那么它是如何来实现的呢?
总结一句来说weabpack插件开发机制就是钩子机制
接下来开发一个自己的plugin
- 插件是由「具有 apply 方法的 prototype 对象」所实例化出来的。这个 apply 方法在安装插件时,会被 webpack compiler 调用一次
- 即插件要求必须是一个函数或者对象,且包含有apply方法
- 找到对应的钩子, comile=> 编译器 run=>运行期 emit => 输出文件执行
- tap 事件触发同步机制, tapAsync 触发异步机制 具体查看
- 必须将生成的文件的内容,和大小返回给webpack
class RemoveCommentsPlugin {
apply(compiler) {
console.log('Remove comments')
compiler.hooks.emit.tap('RemoveCommentsPlugin', compilation => {
// compilation 可以视为此次打包的上下文
for (const name in compilation.assets) {
// console.log(compilation.assets[name].source())
if (name.endsWith('.js')) {
const contents = compilation.assets[name].source();
const noComments = contents.replace(/\/\*{2,}\/\s?/g, '')
compilation.assets[name] = {
source: () => noComments,
size: () => noComments.length
}
console.log('你需要操作的文件:', name)
}
}
})
}
}
module.exports = RemoveCommentsPlugin
钩子机制即面向切切面编程
# 工作原理
这里主要从最开始的命令行开始说起,一般来说我们为再webpack打包的配置项目中配置**--mode=production**类似这样的参数。 那么带着这样的疑问,我们出发来寻找答案。
在webpack4中,webpack-cli被单独抽离出来了,入口文件即使webpack-cli中的 bin/cli.js
接着转换参数
# 创建complider对象
接着我们开始编译整个webpack的核心
导出compile函数
注册插件
# 开始构建
在构建的阶段结汇触发我们对应的钩子,已经相对应的loader 这个阶段会将我们之前所说的 调用对象的compile方法
# make 阶段
make 阶段主体的目标就是:根据 entry 配置找到入口模块,开始依次递归出所有依赖,形成依赖关系树,然后将递归到的每个模块交给不同的 Loader 处理。
形成语法树, 最后解析完成输出打包目标