webpack面试2

平平丶淡淡 / 2024-03-15 / 原文

一、常用plugin

  1. html-webpack-plugin:生成一个html文件,该文件会自动引入所有生成的bundle。

    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
        ......
        plugins: [
            new HtmlWebpackPlugin({
                // 以 public/index.html 为模板创建文件
                // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
                template: path.resolve(__dirname, "public/index.html"),
            })
        ]
    }
    
  2. mini-css-extract-plugin:将css文件打包到单独的文件,而不是打包到js中。

    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    module.exports = {
        ......
        module: {
            rules: [
                {
                    // 用来匹配 .css 结尾的文件
                    test: /\.css$/,
                    // use 数组里面 Loader 执行顺序是从右到左
                    use: [MiniCssExtractPlugin.loader, "css-loader"], 
                }
            ]
        },
        ......
        plugins: [
                // 提取css成单独文件
                new MiniCssExtractPlugin({
                // 定义输出文件名和目录
                filename: "static/css/main.css",
        	}),
        ]
    }
    
  3. css-minimizer-webpack-plugin:css压缩

    const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
    
    module.exports = {
        ......
        plugins: [
            // css压缩
            new CssMinimizerPlugin()
        ]
    }
    
  4. image-minimizer-webpack-plugin:压缩图片

    const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
    
    module.exports = {
        ......
          optimization: {
              minimizer: [
              // css压缩也可以写到optimization.minimizer里面,效果一样的
              new CssMinimizerPlugin(),
              // 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了
              new TerserPlugin({
                parallel: threads, // 开启多进程
              }),
              // 压缩图片
              new ImageMinimizerPlugin({
                minimizer: {
                  implementation: ImageMinimizerPlugin.imageminGenerate,
                  options: {
                    plugins: [
                      ["gifsicle", { interlaced: true }],
                      ["jpegtran", { progressive: true }],
                      ["optipng", { optimizationLevel: 5 }],
                      [
                        "svgo",
                        {
                          plugins: [
                            "preset-default",
                            "prefixIds",
                            {
                              name: "sortAttrs",
                              params: {
                                xmlnsOrder: "alphabetical",
                              },
                            },
                          ],
                        },
                      ],
                    ],
                  },
                },
              }),
            ],
      	},
    }
    
  5. @vue/preload-webpack-plugin:在空闲时间加载后续需要使用的资源

    const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin");
    
    module.exports = {
        plugins: [
            new PreloadWebpackPlugin({
                rel: "preload", // preload兼容性更好
                as: "script",
                // rel: 'prefetch' // prefetch兼容性更差
            }),
        ]
    }
    
  6. workbox-webpack-plugin:提供离线访问功能,内部通过 Service Workers 技术实现

    const WorkboxPlugin = require("workbox-webpack-plugin");
    
    module.exports = {
        plugins: [
            new WorkboxPlugin.GenerateSW({
                // 这些选项帮助快速启用 ServiceWorkers
                // 不允许遗留任何“旧的” ServiceWorkers
                clientsClaim: true,
                skipWaiting: true,
            }),
        ]
    }
    
  7. terser-webpack-plugin:压缩和优化JavaScript代码

二、loader和plugin的不同

  • 作用不同
    1. Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
    2. Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
  • 用法不同
    1. Loadermodule.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options
    2. Pluginplugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。

三、webpack的构建流程

  1. 初始化参数:Webpack从配置文件(如webpack.config.js)和Shell语句中读取参数,并进行合并,得出最终的构建参数。这些参数为后续步骤提供了必要的配置信息。
  2. 开始编译:使用初始化参数中得到的配置,Webpack会初始化一个Compiler对象。这个对象会加载所有配置的插件,并执行其run方法,从而开始执行编译过程。
  3. 确定入口:Webpack会根据配置文件中的entry配置找出所有的入口文件。入口文件是构建过程的起点,Webpack会从这些文件开始解析依赖关系。
  4. 编译模块:从入口文件开始,Webpack会递归地解析每个模块,并根据配置文件中的loader配置对模块进行转换。这些loader可以将不同类型的文件(如CSS、图片等)转换为JavaScript模块,以便Webpack能够处理。同时,Webpack还会找出每个模块所依赖的其他模块,并递归地对这些依赖模块进行相同的处理,直到所有入口依赖的文件都经过了处理。
  5. 完成编译:经过loader的转换后,Webpack得到了每个模块被翻译后的内容以及它们之间的依赖关系。这些依赖关系会以特定的格式(如AST语法树)保存在内存中,为后续步骤提供必要的信息。
  6. 输出资源:根据入口文件和模块之间的依赖关系,Webpack会将这些模块组装成多个包含多个模块的chunk。然后,Webpack会将每个chunk转换为单独的文件,并加入到输出列表中。在这个过程中,Webpack还可以根据配置进行代码分割、优化等操作。
  7. 输出完成:确定输出内容后,Webpack会根据配置文件中的输出路径和文件名,将文件写入到指定的文件系统中。这标志着整个构建过程的结束。

四、如何用webpack优化前端性能

  1. 利用缓存
    • Webpack 5 引入了持久化缓存,通过生成一个唯一的哈希值来标识模块,只要模块的内容不变,就可以使用缓存的模块,避免重复编译。
    • 确保 output.deterministic 配置为 true,以便确保输出内容的确定性,从而有效利用缓存。
    • 使用 contenthash 替代 hash,以便只在内容变化时更新输出文件名。
  2. Tree Shaking
    • 利用 ES6 模块的静态结构特性,自动去除无用的代码,减少最终打包的体积
    • 确保你的代码使用 ES6 模块语法,并且 optimization.usedExportsoptimization.sideEffects 配置正确
  3. 代码分割
    • 使用 import() 语法进行动态导入,将代码拆分成多个块(chunks),按需加载
    • 配置 optimization.splitChunks 以优化代码分割策略
  4. 压缩和优化输出
    • 使用 TerserPlugin 进行 JavaScript 代码的压缩
    • 对于 CSS,可以使用 CssMinimizerPlugin
    • 启用 compression 插件,如 CompressionWebpackPlugin,进行 gzip 或 Brotli 压缩
  5. 利用模块联邦(Module Federation)
    • Webpack 5 引入了模块联邦,允许在不同的构建之间共享代码,而无需复制或安装相同的依赖
  6. 优化加载器
    • 减少不必要的加载器使用,只针对需要的文件类型使用加载器
    • 尝试使用更快的加载器或并行处理加载器(如 thread-loaderhappypack
  7. 使用 DLL Plugin
    • DLL Plugin 可以将特定的依赖模块提前构建,在后续构建中复用,减少构建时间
  8. 利用 Webpack Dev Server
    • 在开发环境中使用 Webpack Dev Server,它提供了热模块替换(HMR)功能,可以在不刷新整个页面的情况下更新模块,提高开发效率。
  9. 监控和分析构建
    • 使用 webpack-bundle-analyzer 插件来分析打包后的文件结构和大小,找出可能的优化点