前端开发那些事儿

Webpack 知识点总结

2020-10-14  本文已影响0人  limengzhe

随着现代前端开发的规模日益庞大,几乎已经不能抛开诸如 React 或 Vue 等前端开发框架来独立开发了,这些框架很大程度上的提高了我们的开发效率,但是框架中所使用特殊文件,比如 jsxvuescssless 等,浏览器是无法直接识别的,必须经过编译后才能在浏览器中使用。于是在众多的前端工程化工具中,Webpack 脱颖而出成为了当今最流行的前端构建工具。 [1]

webpack

Webpack 配置模板:

// webpack.config.js
const path = require('path');
module.exports = {
  entry: "./app/entry", // string | object | array
  // Webpack打包的入口
  output: {  // 定义webpack如何输出的选项
    path: path.resolve(__dirname, "dist"), // string
    // 所有输出文件的目标路径
    filename: "[chunkhash].js", // string
    // 「入口(entry chunk)」文件命名模版
    publicPath: "/assets/", // string
    // 构建文件的输出目录
    /* 其它高级配置 */
  },
  module: {  // 模块相关配置
    rules: [ // 配置模块loaders,解析规则
      {
        test: /\.jsx?$/,  // RegExp | string
        include: [ // 和test一样,必须匹配选项
          path.resolve(__dirname, "app")
        ],
        exclude: [ // 必不匹配选项(优先级高于test和include)
          path.resolve(__dirname, "app/demo-files")
        ],
        loader: "babel-loader", // 模块上下文解析
        options: { // loader的可选项
          presets: ["es2015"]
        },
      },
  },
  resolve: { //  解析模块的可选项
    modules: [ // 模块的查找目录
      "node_modules",
      path.resolve(__dirname, "app")
    ],
    extensions: [".js", ".json", ".jsx", ".css"], // 用到的文件的扩展
    alias: { // 模块别名列表
      "module": "new-module"
      },
  },
  devtool: "source-map", // enum
  // 为浏览器开发者工具添加元数据增强调试
  plugins: [ // 附加插件列表
    // ...
  ],
}

Webpack 的运行流程是怎样的?

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:[2]
  1. 初始化参数:从配置文件 webpack.config.js 和命令行中读取与合并参数,初始化本次构建的配置参数,得出最终的参数;
  2. 开始编译:用上一步得到的参数初始化 Compiler 对象,加载配置文件的所有 plugin,执行对象的 run 方法开始执行编译;
  3. 确定入口:根据配置中的 entry 找出所有的入口文件,递归遍历所有的入口文件;
  4. 编译模块:从入口文件出发,调用所有配置的 loader 对模块进行编译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
  5. 输出资源:所有文件的编译及转化都已经完成,也就是最终输出的资源,其中包括即将输出的资源、代码块 Chunk 等等信息。
运行流程图:[3]
Webpack 运行流程图

Webpack 的 Loader 是什么?

Webpack 只能理解 JavaScriptJSON 文件,这是 Webpack 开箱可用的自带能力。loader 可以让 Webpack 能够去处理其他类型的文件,比如 .scss.ts,并将它们转换为有效的功能离散的 chunk 文件以供应用程序使用,以及被添加到依赖图中,也可将内联图像转换为 data URL。简单来说,loader 可以将一段代码转换成另一端代码,通常用来将一段特殊代码转换成一段浏览器可识别的代码。

loader从下到上地取值(evaluate)/执行(execute),也就是是从后往前执行。在下面的示例中,从 ts-loader开始执行,然后继续执行 css-loader,最后以 raw-loader 为结束。loader 有两个属性:test,正则表达式,用于识别出哪些文件会被转换,use 定义在进行转换时应该使用哪个 loader,可以是字符串、数组和对象。[4]

// webpack.config.js
module.exports = {
  output: {
    filename: "my-first-webpack.bundle.js",
  },
  module: {
    rules: [
      { test: /\.txt$/, use: "raw-loader" }, // 通过 npm 安装
      {
        test: /\\.css$/,
        use: [
          {
            loader: "css-loader", // 通过 npm 安装
            options: { modules: true },
          },
        ],
      },
      { test: /\\.ts$/, use: "ts-loader" }, // 通过 npm 安装
    ],
  },
};

有哪些常见的 Loader ?👉 Loaders

Webpack 的 Plugin 是什么?

loader 用于转换某些类型的模块,而 plugin(插件)则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。想要使用一个 plugin,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过 option 自定义,也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。[5]

// webpack.config.js
const webpack = require('webpack'); // 用于访问内置插件
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装

module.exports = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

有哪些常见的 Plugin ?Plugins

Webpack 的热更新原理是怎样的?

Webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。

HMR 工作流程
  1. Webpack 通过 Watch 模式可以侦听文件的变化,当文件发生改变时,会根据配置进行重新编译(Compile),并将编译后的代码保存在内存中。
  2. webpack-dev-server 也会对文件变化进行监控(需要配置 devServer.watchContentBase = true),但不会进行重新编译,而是监听这些配置文件中静态文件的变化,变化后会通知浏览器进行直接刷新,而不是 HMR
  3. 在浏览器和服务端之间有一个通过 SocketJs 建立的 websocket 长连接。webpack-dev-server 会将 Webpack 编译打包时的各个阶段的状态信息和 hash 值一并告知 webpack-dev-server/client(位于浏览器端)。
  4. 但是 webpack-dev-server/client 并不能够请求更新的代码,而是把这些工作交给了 webpack/hot/dev-serverwebpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传来的信息以及 dev-server 的配置决定是刷新浏览器还是 HMR
  5. HotModuleReplacement.runtime 是客户端 HMR 的中枢,它接收到 webpack/hot/dev-server 传递的新模块的 hash 值,通过 JsonpMainTemplate.runtimewebpack-dev-server 发送 Ajax 请求获取到返回的 Json,该 Json 包含了所有要更新的模块的 hash 值,之后通过 Jsonp 请求,获取到最新的模块代码。
  6. 接下来,HotModulePlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。
  7. 如果 HMR 失败,则通过刷新浏览器来获取最新打包代码。

  1. 关于webpack的面试题

  2. 「吐血整理」再来一打Webpack面试题

  3. Webpack揭秘

  4. loaders

  5. plugins

上一篇下一篇

猜你喜欢

热点阅读