构建工具webpack
-
主要配置
import path from "path"; const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = {entry: "./src/index.js", //入口文件output: {//出口文件path: path.resolve(__dirname, "dist"),filename: "bundle.js",},mode: "development", //模式// development 开发模式速度块,内置调试工具// production 生产模式,打包慢,会进行压缩优化// none 原始模式plugins: [//plugin 配置区域new HtmlWebpackPlugin({//它是一个类,需要实例化,作用是把html文件处理以及打包到我们的出口template: path.join(__dirname, "./index.html"),}),],module: {// loader 配置区域rules: [//规则数组{test: /\.js$/, //匹配需要处理的文件类型exclude: /node_modules/, //排除目录include: /src/, //包含目录use: [ //use多个loader 处理使用数组,单个loader使用字符串或者对象"style-loader", // 插入 <style> 这里默认配置"css-loader", // 解析 CSS 这里使用默认配置{loader: "sass-loader", // 转换 Sass → CSS 手动配置options: { //loader 需要的参数 loader实现内部 使用 loader-uitls 的 getOptions获取sourceMap: true,},},],},],}, };
-
loader对比plugin
- loader 把不同的文件翻译成webpack 能理解的模块,在文件被导入(import/require)的时候触发;
- plugin是在webpack 的生命周期中做扩展或者优化。
-
手写loader
//一个简单的markdown转html //配置webpack.config {test: /\.md$/,exclude: /node_modules/,use: {loader: path.resolve(__dirname, "loader/md-loader.js"),}, }, // loader/md-loader 文件 import { marked } from 'marked'; export default (source) => {const html = marked.parse(source);return `module.exports = ${JSON.stringify(html)}`; //转出html字符串 }; // index.js使用 import readme from "./readme.md"; //md const div = document.createElement("div"); div.innerHTML = readme; document.body.appendChild(div);
-
手写plugin
// 自定义一个构建的时间的监控 // plugin/build-time.js class BuildTimePlugin {constructor(options) {this.options = options;this.startTime = null;}apply(compiler) {//compiler 提供了很多钩子供我们使用compiler.hooks.beforeRun.tap("BuildTimePlugin", () => {this.startTime = Date.now();console.log("开始构建...");});compiler.hooks.done.tap("BuildTimePlugin", stats => {const endTime = Date.now();const buildTime = (endTime - this.startTime) / 1000;console.log(`构建完成!耗时: ${buildTime.toFixed(2)}s`);});} } export default BuildTimePlugin; // webpack.config import BuildTimePlugin from "./plugin/build-time.js";plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, "index.html"),meta: {charset: { charset: "UTF-8" }, //防止乱码viewport: "width=device-width, initial-scale=1.0",},}),new BuildTimePlugin(), //构建时间监控new CleanWebpackPlugin() //自动删除输出目录中的旧文件,确保输出目录只包含最新的构建文件 ],
-
webpack运行机制
- 初始化阶段
- 合并命令行参数和配置文件
- 创建Compoler, 核心编译器实例,控制构建的生命周期
- 注册插件(plugin),调用插件的apply方法,挂载到各个钩子上
- 编译阶段
- 入口解析,从entry 出发
- 模块构建
- 读取文件内容
- loader 处理
- AST 分析,webpack内部解析为AST, 分析依赖关系
- 依赖收集,找到所有导出的模块(import/require)
- 递归对于模块进行上述模块构建的步骤
- module.exports.pitch 函数的执行顺序相反
- chunk生成,根据代码分割规则将模块分组到不同的chunk
- optimization中配置代码分割规则
optimization:{splitChunks: {chunks: 'all', } }
- optimization中配置代码分割规则
- 输出阶段
- 将chunk转换为最终的文件内容
- 将生成的js、css 等写入输出目录
- 初始化阶段
-
HMR 热更新
- devServer 启动 注入 HMR runtime
- 页面首次加载建立一个 ws 连接
- webpcak 监听文件变化,会执行变化模块的complier,增量更新,并且推送hash 和 ok 事件
- 浏览器接收到 ok 事件,会拉取更新清单以及更新代码
- 加载更新的模块
- 执行模块的 module.hot.accept() 回调函数