webpack知识点整理及性能优化点

本文详细介绍了Webpack的loader和Plugin的作用,常见的Loader包括less-loader、css-loader、style-loader等,而Plugin如html-webpack-plugin、mini-css-extract-plugin用于优化打包。文章探讨了Webpack的优化手段,包括代码压缩、Tree Shaking、代码分离等,并讨论了Webpack4与Webpack5的区别,如Webpack5内置了terser-webpack-plugin进行JS压缩。此外,还提到了前端性能优化的策略,如CSS层优化、防抖节流、图片优化等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Webpack中loader的作用/ loader是什么?

Loader 是webpack中提供了一种处理多种文件格式的机制,因为webpack只认识JS和JSON,所以Loader相当于翻译官,将其他类型资源进行预处理。

loader文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译压缩等

处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个先执行

常见的loader有哪些?

  • less-loader:将less文件编译成css文件
  • css-loader:将css文件变成commonjs模块加载到js中,模块内容是样式字符串
  • style-loader: 创建style标签,将js中的样式资源插入标签内,并将标签添加到head中生效
  • ts-loader: 打包编译Typescript文件

2、Plugin有什么作用?/Plugin是什么

Plugin功能更强大,主要目的就是解决loader 无法实现的事情,比如打包优化和代码压缩等。
Plugin加载后,在webpack构建的某个时间节点就会触发plugin定义的功能,帮助webpack做一些事情。实现对webpack的功能扩展。

常见的Plugin有哪些

  1. html-webpack-plugin :处理html资源,默认会创建一个空的HTML,自动引入打包输出的所有资源(js/css)
  2. mini-css-extract-plugin: 打包过后的css在js文件里,该插件可以把css单独抽出来
  3. clean-webpack-plugin :每次打包时候,CleanWebpackPlugin 插件就会自动把上一次打的包删除
     

3、Webpack中Loader和Plugin的区别

  1. loader运行在编译阶段,是一个转换器,将a文件进行编译形成b文件,操作的是文件,例如a.less转为a.css
  2. plugins 在整个周期都起作用,针对loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,监听webpack打包过程中的某些点,执行广泛的任务

4、Webpack 做过哪些优化手段?有哪些优化手段?

如何利用webpack来优化前端性能? 问的是生产环境优化
如何提高webpack的构建速度? 问的是构建速度的优化

5、如何利用webpack来优化前端性能?

  1. JS代码压缩

  2. CSS代码压缩

  3. HTML文件压缩

  4. 文件大小压缩

  5. 图片压缩

  6. Tree Shaking 

  7. 代码分离

  8. Dll进行分包

JS代码压缩:

  1. uglifyjs-webpack-plugin:webpack4以上已经内置了js的压缩插件uglifyjs-webpack-plugin,如要修改插件的配置还是要下载之后再修改,默认打包之后已压缩js代码。
  2. terser-webpack-plugin:webpack5及以上已经内置了js的压缩插件terser-webpack-plugin,如要修改插件的配置还是要下载之后再修改,默认打包之后已压缩js代码。
  3. const TerserPlugin = require('terser-webpack-plugin')
    module.exports = {
        ...
        optimization: {
            minimize: true,
            minimizer: [
                new TerserPlugin({
                    parallel: true // 电脑cpu核数-1
                })
            ]
        }
    }
    

CSS代码压缩:

  • 使用optimize-css-assets-webpack-plugin,同时使用cssnano

 
 const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
 
module.exports = {
 
        plugins:[
            new OptimizeCssAssetsPlugin({
                assetNameRegExp: /\.css$/g,
                cssProcessor: require('cssnano')
            })
        ]
}

HTML文件压缩

  • 使用html-webpcak-plugin 
module.exports = {
    ...
    plugin:[
        new HtmlwebpackPlugin({
            ...
            minify:{
                minifyCSS:false, // 是否压缩css
                collapseWhitespace:false, // 是否折叠空格
                removeComments:true // 是否移除注释
            }
        })
    ]
}

文件压缩:对文件的大小进行压缩,减少http传输过程中宽带的损耗。

// npm install compression-webpack-plugin -D
new ComepressionPlugin({
    test:/\.(css|js)$/,  // 哪些文件需要压缩
    threshold:500, // 设置文件多大开始压缩
    minRatio:0.7, // 至少压缩的比例
    algorithm:"gzip", // 采用的压缩算法
})

图片压缩:一般来说在打包之后,一些图片文件的大小是远远要比 js 或者 css 文件要来的大,所以图片压缩较为重要。

module: {
  rules: [
    {
      test: /\.(png|jpg|gif)$/,
      use: [
        {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]',
            outputPath: 'images/',
          }
        },
        {
          loader: 'image-webpack-loader',
          options: {
            // 压缩 jpeg 的配置
            mozjpeg: {
              progressive: true,
              quality: 65
            },
            // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
            optipng: {
              enabled: false,
            },
            // 使用 imagemin-pngquant 压缩 png
            pngquant: {
              quality: '65-90',
              speed: 4
            },
            // 压缩 gif 的配置
            gifsicle: {
              interlaced: false,
            },
            // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
            webp: {
              quality: 75
            }
          }
        }
      ]
    },
  ]
} 

Tree Shaking:在打包时移除掉javascript上下文中无用的代码,从而优化打包的结果

代码分离:splitChunksPlugin来实现,将代码分离到不同的bundle中,之后可以按需加载

Dll进行分包:DLLPlugin把所有的第三方库依赖打包到一个bundle的dll文件里面,

6、如何提高webpack的构建速度?

思路1:减少需要构建的文件或代码

  1. HMR(Hot Module Replacement) 模块热替换只重新构建发生变化的模块 – 开发环境中
  2. 缩小处理范围:合理利用这两个属性exclude:不需要处理的文件 和 include:需要处理的文件
  3. babel缓存 第二次构建时,会读取之前的缓存,只重新构建变化的文件
  4. 使用Dll进行分包 --> 分包方便按需加载

思路2:多进程进行构建

  • 多进程打包 thread-loader,将其放在费时的loader之前

缩小范围:在配置 loader 的时候,我们需要更精确的去指定 loader 的作用目录或者需要排除的目录,通过使用 include 和 exclude 两个配置项,可以实现这个功能

  • include:符合条件的模块进行解析
  • exclude:排除符合条件的模块,不解析,优先级更高

noParse:对于我们引入的一些第三方包,比如jQuery,在这些包内部是肯定不会依赖别的包,所以根本不需要webpack去解析它内部的依赖关系,使用 noParse 进行忽略的模块文件中不会解析 importrequire 等语法

module:{
    noParse:/jquery|lodash/
}

IgnorePlugin:有很多的第三方包内部会做国际化处理,包含很多的语言包,而这些语言包对我们来说时没有多大用处的,只会增大包的体积,我们完全可以忽略掉这些语言包,从而提高构建效率,减小包的体积。

  • requestRegExp 表示要忽略的路径。
  • contextRegExp 表示要忽略的文件夹目录。
  • new webpack.IgnorePlugin({ resourceRegExp, contextRegExp });
    
    

缓存:

webpack5新加了缓存项配置,具体如下

默认缓存路径在node_modules/.cache/webpack

// 缓存配置 
    cache: {
      type: 'filesystem',  // 开启持久化缓存
      version: createEnvironmentHash(env.raw),  // 参考react脚手架的配置 可以记录打包缓存的版本
      cacheDirectory: path.appWebpackCache, // 缓存路径
      store: 'pack',
      // 构建依赖,如果有文件修改,则重新执行打包流程
      buildDependencies: {
        defaultWebpack: ['webpack/lib/'],
        config: [__filename],
      },
    },

babel-loader 开启缓存

babel 在转译 js 过程中时间开销比价大,将 babel-loader 的执行结果缓存起来,重新打包的时候,直接读取缓存

缓存位置: node_modules/.cache/babel-loader

//支持转义ES6/ES7/JSX
{
  test: /\.jsx?$/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env', '@babel/react'],
        plugins: [
          [
            require('@babel/plugin-proposal-decorators'),
            { legacy: true },
          ],
        ],
        cacheDirectory: true, // 启用缓存
      },
    },
  ],
  include: path.resolve(__dirname, 'src'),
  exclude: /node_modules/,
},

cache-loader

缓存一些性能开销比较大的 loader 的处理结果, 缓存位置:node_modules/.cache/cache-loader

const config = {
 module: { 
    // ...
    rules: [
      {
        test: /.(s[ac]|c)ss$/i, //匹配所有的 sass/scss/css 文件
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader,
          'cache-loader', // 获取前面 loader 转换的结果
          'css-loader',
          'postcss-loader',
          'sass-loader', 
        ]
      }, 
      // ...
    ]
  }
}

注意:

dll动态链接(已弃用)
在 webpack5.x 中已经不建议使用这种方式进行模块缓存,因为其已经内置了更好体验的 cache 方法

hard-source-webpack-plugin
hard-source-webpack-plugin 为模块提供了中间缓存,重复构建时间大约可以减少 80%,但是在 webpack5 中已经内置了模块缓存,不需要再使用此插件
 

7、webpack5 和 webpack4 的区别有哪些 ?

  1. webpack5的 mode=“production” 自动开启 tree-shaking。
  2. .webpack5内部本身就自带 js 压缩功能,他内置了 terser-webpack-plugin 插件,我们不用再下载安装。而且在 mode=“production” 的时候会自动开启 js 压缩功能。

  3. webpack5 内部内置了 cache 缓存机制。直接配置即可

  4. 对loader的优化

8、css代码层优化

  • 1、css压缩
  • 2、css单一样式更好,例如margin-bottom:10px;margin-top:10px;
  • 3、减少使用@import,建议使用link,link在页面加载时一起加载,@import等页面加载完成后再进行加载
  • 4、减少使用标签选择器,而是用class
  • 5、避免使用通配符选择器*{}
  • 6、了解哪些属性是可以通过继承而来的,然后避免对这些属性重复使用
  • 7、尽量减少页面的重排、重绘
  • 8、公共样式抽离出来,整合并通过class在页面中使用

9、避免重绘回流

注意:触发回流定会触发重绘,重绘不一定引发回流

引起回流:

  • 页面的首次渲染
  • 浏览器窗口大小发生变化
  • 元素内容发生变化
  • 元素的尺寸或者位置发生变化
  • 元素的字体大小发生变化
  • 添加或者删除可见的DOM元素
  • 激活css伪类

导致重绘:

  • color/background相关属性background-color,background-image等属性
  • outline相关属性outline-color,outline-width
  • border-radius/visibility/box-shadow

减少回流与重绘:

  • 尽量不使用table布局
  • 不要频繁操作元素的样式,可以采用修改类名
  • 使用absolute或者fixed,使元素脱离文档流
  • 将元素设置display:none,操作结束再把它显示出来。因为在display属性为none的元素上进行DOM操作不会引起回流和重绘

9、防抖节流

https://liulibin.blog.youkuaiyun.com/article/details/115230182

10、图片优化

jpg/jpeg

优点:有损压缩、体积小、加载快、不支持透明

有损压缩:当我们把图片体积压缩至原有体积的50%以下时,JPG仍然可以保持住60%的品质

使用场景:

适用于呈现色彩丰富的图片,在我们日常开发中,JPG 图片经常作为大的背景图、轮播图或 Banner 图出现

png-8/png-24

优点:无损压缩、质量高、体积大、支持透明

PNG(可移植网络图形格式)是一种无损压缩的高保真的图片格式。8 和 24,这里都是二进制数的位数。按照我们前置知识里提到的对应关系,8 位的 PNG 最多支持 256 种颜色,而 24 位的可以呈现约 1600 万种颜色。

PNG 图片具有比 JPG 更强的色彩表现力,对线条的处理更加细腻,对透明度有良好的支持。它弥补了上文我们提到的 JPG 的局限性,唯一的 BUG 就是体积太大。

PNG-8 与 PNG-24 的选择题?

什么时候用 PNG-8,什么时候用 PNG-24,这是一个问题。

理论上来说,当你追求最佳的显示效果、并且不在意文件体积大小时,是推荐使用 PNG-24 的。

但实践当中,为了规避体积的问题,我们一般不用PNG去处理较复杂的图像。当我们遇到适合 PNG 的场景时,也会优先选择更为小巧的 PNG-8。

如何确定一张图片是该用 PNG-8 还是 PNG-24 去呈现呢?好的做法是把图片先按照这两种格式分别输出,看 PNG-8 输出的结果是否会带来肉眼可见的质量损耗,并且确认这种损耗是否在我们(尤其是你的 UI 设计师)可接受的范围内,基于对比的结果去做判断。

使用场景:

前面我们提到,复杂的、色彩层次丰富的图片,用 PNG 来处理的话,成本会比较高,我们一般会交给 JPG 去存储。

考虑到 PNG 在处理线条和颜色对比度方面的优势,我们主要用它来呈现小的 Logo、颜色简单且对比强烈的图片或背景等。

此时我们再次把目光转向性能方面堪称业界楷模的淘宝首页,我们会发现它页面上的 Logo,无论大小,还真的都是 PNG 格式

svg矢量图(iconfont)

优点:文本文件、体积小、不失真、兼容性好

最经典的小图标解决方案——雪碧图(CSS Sprites)

webp

优点:支持有损压缩和无损压缩

WebP 像 JPEG 一样对细节丰富的图片信手拈来,像 PNG 一样支持透明,像 GIF 一样可以显示动态图片——它集多种图片文件格式的优点于一身。

WebP 的官方介绍对这一点有着更权威的阐述:

与 PNG 相比,WebP 无损图像的尺寸缩小了 26%。在等效的 SSIM 质量指数下,WebP 有损图像比同类 JPEG 图像小 25-34%。 无损 WebP 支持透明度(也称为 alpha 通道),仅需 22% 的额外字节。对于有损 RGB 压缩可接受的情况,有损 WebP 也支持透明度,与 PNG 相比,通常提供 3 倍的文件大小。

我们开篇提到,图片优化是质量与性能的博弈,从这个角度看,WebP 无疑是真正的赢家。

缺点:兼容性差,兼容主流浏览器,谷歌兼容最好

11、懒加载和预加载的区别

懒加载:也叫延迟加载,用户需要访问时再加载

预加载:将所需的资源提前请求加载到本地,这样以后直接从缓存里面读取资源

12、babel的原理是什么?

  • 解析Parse:将代码解析生成抽象语法树ast,即词法分析和语法分析的过程
  • 转换Transform:对于AST进行转换一系列操作,babel接受得到AST并通过babel-traverse对其进行遍历,在此过程中进行添加更新移除等操作
  • 生产Generate:将转换的ast在转换为js代码,使用到的模块是babel-generator

13、webpack的构建流程?

1.初始化参数:从配置文件和shell语句中读取与合并参数,得出最终的参数

2.开始编译:从上一步得到的参数初始化Compiler对象,加载所有配置的插件,执行对象的run方法开始执行编译

3.确定入口:根据配置中的entry找出所有的入口文件

4.编译模块:从入口文件出发,调用所有配置的loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过本步骤的处理;

比如UglifyPlugin 会在 loader 转换递归完对结果使用 UglifyJs 压缩覆盖之前的结果。

5.输出资源:根据⼊⼝和模块之间的依赖关系,组装成⼀个个包含多个模块的Chunk,再把每个 Chunk 转换成⼀个单独的⽂件加⼊到输出列表,这步是可以修改输出内容的最后机会;

6。输出完成:在确定好输出内容后,根据配置确定输出的路径和⽂件名,把⽂件内容写⼊到⽂件系统。

14、热更新原理

  1. 监听文件变化
  2. 服务器与客户端通信
  3. 替换过程
  4. 降级操作

监听文件变化

webpack监听文件变化主要是通过webpack-dev-middleware这个库来完成,它负责本地文件的编译、输出和监听,

webpack-dev-middleware中执行了compiler.watch方法,它主要做了两件事情

  1. 对本地文件编译打包
  2. 编译结束之后,开启监听,文件发生变化时重新编译,并持续进行监听

每次代码修改后,保存都会在控制台出现compiling…字样,可以在控制台中观察到:

如果没有任何改动,直接保存,控制台输出编译打包信息,Hash 值没有发生变化,仍旧是 4f8c0eff7ac051c13277。 

通过webpack-dev-server的依赖,在浏览器和服务端直接建立一个websocket长连接,将webpack编译打包的各个阶段的状态信息告知浏览器,浏览器根据这些信息进行不同的操作。服务端传递的最主要的信息是hash值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浏览器翻译官~

你的励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值