webpack面试2
一、常用plugin
-
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"), }) ] } -
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", }), ] } -
css-minimizer-webpack-plugin:css压缩
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); module.exports = { ...... plugins: [ // css压缩 new CssMinimizerPlugin() ] } -
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", }, }, ], }, ], ], }, }, }), ], }, } -
@vue/preload-webpack-plugin:在空闲时间加载后续需要使用的资源
const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin"); module.exports = { plugins: [ new PreloadWebpackPlugin({ rel: "preload", // preload兼容性更好 as: "script", // rel: 'prefetch' // prefetch兼容性更差 }), ] } -
workbox-webpack-plugin:提供离线访问功能,内部通过 Service Workers 技术实现
const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = { plugins: [ new WorkboxPlugin.GenerateSW({ // 这些选项帮助快速启用 ServiceWorkers // 不允许遗留任何“旧的” ServiceWorkers clientsClaim: true, skipWaiting: true, }), ] } -
terser-webpack-plugin:压缩和优化JavaScript代码
二、loader和plugin的不同
- 作用不同
- Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到
loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。 - Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
- Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到
- 用法不同
- Loader在
module.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options) - Plugin在
plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。
- Loader在
三、webpack的构建流程
- 初始化参数:Webpack从配置文件(如webpack.config.js)和Shell语句中读取参数,并进行合并,得出最终的构建参数。这些参数为后续步骤提供了必要的配置信息。
- 开始编译:使用初始化参数中得到的配置,Webpack会初始化一个Compiler对象。这个对象会加载所有配置的插件,并执行其run方法,从而开始执行编译过程。
- 确定入口:Webpack会根据配置文件中的entry配置找出所有的入口文件。入口文件是构建过程的起点,Webpack会从这些文件开始解析依赖关系。
- 编译模块:从入口文件开始,Webpack会递归地解析每个模块,并根据配置文件中的loader配置对模块进行转换。这些loader可以将不同类型的文件(如CSS、图片等)转换为JavaScript模块,以便Webpack能够处理。同时,Webpack还会找出每个模块所依赖的其他模块,并递归地对这些依赖模块进行相同的处理,直到所有入口依赖的文件都经过了处理。
- 完成编译:经过loader的转换后,Webpack得到了每个模块被翻译后的内容以及它们之间的依赖关系。这些依赖关系会以特定的格式(如AST语法树)保存在内存中,为后续步骤提供必要的信息。
- 输出资源:根据入口文件和模块之间的依赖关系,Webpack会将这些模块组装成多个包含多个模块的chunk。然后,Webpack会将每个chunk转换为单独的文件,并加入到输出列表中。在这个过程中,Webpack还可以根据配置进行代码分割、优化等操作。
- 输出完成:确定输出内容后,Webpack会根据配置文件中的输出路径和文件名,将文件写入到指定的文件系统中。这标志着整个构建过程的结束。
四、如何用webpack优化前端性能
- 利用缓存
- Webpack 5 引入了持久化缓存,通过生成一个唯一的哈希值来标识模块,只要模块的内容不变,就可以使用缓存的模块,避免重复编译。
- 确保
output.deterministic配置为true,以便确保输出内容的确定性,从而有效利用缓存。 - 使用
contenthash替代hash,以便只在内容变化时更新输出文件名。
- Tree Shaking
- 利用 ES6 模块的静态结构特性,自动去除无用的代码,减少最终打包的体积
- 确保你的代码使用 ES6 模块语法,并且
optimization.usedExports和optimization.sideEffects配置正确
- 代码分割
- 使用
import()语法进行动态导入,将代码拆分成多个块(chunks),按需加载 - 配置
optimization.splitChunks以优化代码分割策略
- 使用
- 压缩和优化输出
- 使用 TerserPlugin 进行 JavaScript 代码的压缩
- 对于 CSS,可以使用 CssMinimizerPlugin
- 启用
compression插件,如CompressionWebpackPlugin,进行 gzip 或 Brotli 压缩
- 利用模块联邦(Module Federation)
- Webpack 5 引入了模块联邦,允许在不同的构建之间共享代码,而无需复制或安装相同的依赖
- 优化加载器
- 减少不必要的加载器使用,只针对需要的文件类型使用加载器
- 尝试使用更快的加载器或并行处理加载器(如
thread-loader或happypack)
- 使用 DLL Plugin
- DLL Plugin 可以将特定的依赖模块提前构建,在后续构建中复用,减少构建时间
- 利用 Webpack Dev Server
- 在开发环境中使用 Webpack Dev Server,它提供了热模块替换(HMR)功能,可以在不刷新整个页面的情况下更新模块,提高开发效率。
- 监控和分析构建
- 使用
webpack-bundle-analyzer插件来分析打包后的文件结构和大小,找出可能的优化点
- 使用