通过 程柳峰 老师的 视屏学习 webpack,这里记录一下 关于 webpack 的学习笔记
1、npm run build 发生了什么
- 会 从 node_module/.bin 中查找 webpack.cmd
- 查找 webpack-cli 或者 webpack-commond 是否安装
- 没有的话,就会 提示进行安装,如果安装了 一个,则正常运行,如果 装了两个,提示删掉一个
- 分析参数,组成 编译配置项,引入 webpack,进行编译构建
2、webpack插件
- 创建一个 Compiler 类,继承 Tapable ,这样的话 可以实现各种钩子函数 (据说 一共有 上百个 种钩子函数)
- 然后 实例化一个 childCompiler = new Compiler(this.context);
- 检查 是否有 plugins 以及 是否是数组
- 接着 将 每个 plugin 遍历 一遍 并执行 plugin.apply(childCompiler); 这样 的话,一个插件 就可以通过 监听 某一个钩子函数 确定自己的执行时机了,并且将 插件 挂载在 当前的 childCompiler 实例上面
// 记一个 最简单的 options
module.exports = class MyPlugin{
constructor(options) {
this.options = options;
}
apply(compiler) {
// 监听 一个 叫做 emit 的 钩子(在生成文件阶段)
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, cb) => {
for (let filename in compilation.assets) {
// 传进来的 代码
const source = compilation.assets[filename].source;
console.log(source)
// 可以在这个过程中 对 传入进来的代码做一点事情
// 然后 按照以下格式重写 assets 的内容
compilation.assets[name] = {
source: () => source,
size: () => source.length
}
cb()
}
})
}
}
3、Loader
- 执行的顺序 是 从 右往左 ,其实可以参考一下 redux 里面 处理 中间件 applyMiddleware 对 dispatch的处理 过程
- 将 上一个处理的 结果 返回给下一个 进行处理
- 例如 less-loader -> css-loader -> style-loader,这样才能 一步一步
- 其运行 原理就是 在 webpack 跑起来的时候,会 把匹配到的 文件 整个一股脑的塞给他,然后 丢给这 loader 去执行,执行完成之后 通过 callback 把执行 过得代码 丢出来
// 记一个 最简单 的 loader
// 作用 就是 把所有的 空格替换成 %20
module.exports = function (source) {
const json = JSON.stringify(source)
.replace(/ /g, '%20');
// 必须返回一个 js 的表达式
return `export default ${json}`;
// this.callback(null, json)
}
4、整体编译
- 从 entry 读入 文件
- 对模块 位置进行解析
- 将 loader 加载完成 的 module 进行编译,生成 AST 树
- 遍历 AST 树,遇到 require 或者 import 的时候,进行依赖收集,重新执行 第一步
- 所有依赖收集 build 完毕
- 首先 对 entry 中的 module 生成 一个新的 chunk,然后遍历 module 的 依赖列表,将 依赖的 module 也加入到 chunk 中
- 如果 一个 module 是动态引入的(require / import() ),那么就会 根据 这个module 创建 一个新的 chunk,继续遍历
- 输出 打包 好的文件
5、webpack config 的类型检查
// 一定记得运行 Webpack 前先注释掉这里。
// import { Configuration } from 'webpack'
/**
* @type {Configuration}
*/
const config = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
}
}
module.exports = config