webpack性能优化小结

121 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

前言

身为一个前端小菜鸟,总是有一个飞高飞远的梦想,因此,每点小成长,我都想要让它变得更有意义,为了自己,也为了更多值得的人

开开心心学技术大法~~

开心

来了来了,他真的来了~

正文

js压缩

默认情况下,mode为production时自动压缩。

也可以手动在webpack的optimizatin利配置,此时需要用到terser-webpack-plugin插件

const TerserWebpackPlugin = require('terser-webpack-plugin')

// ...
optimization:{
    minimize:true,
    minimizer:{
        new TerserWebpackPlugin({
            // 开启缓存
            cache: true,
            // 开启多进程打包压缩
            parallel: true,
            // 启动source-map
            sourceMap: true
        });
    },
}

css压缩

需要用到optimize-css-assets-webpack-plugin插件

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')


// ...
plugins:[
    new OptimizeCssAssetsWebpackPlugin()
]

gzip压缩

因为浏览器需要从服务器端下载资源然后再进行其他操作,这些资源也都是可以压缩的。


new CompressionWebpackPlugin({
  // asset: '[path].gz[query]',
  filename: '[path].gz[query]',
  algorithm: 'gzip',
  test: new RegExp(
    '\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
  ),
  threshold: 10240,
  minRatio: 0.8
})

强缓存和协商缓存

在服务端和nginx端配置所有不常变动文件为强缓存,打包资源为协商缓存

服务端

res.setHeader('max-age': '3600 public') 
res.setHeader(etag: '5c20abbd-e2e8') 
res.setHeader('last-modified': Mon, 24 Dec 2018 09:49:49 GMT)

nginx端

add_header Cache-Control "max-age=3600"

PWA渐进式

配置PWA渐进式应用程序,目的是用户在离线情况下也能访问到页面。需要用到浏览器的serviceWorker功能,所以依赖于浏览器各自的功能


// webpack.config.js

plugins:[
    new WorkboxWebpackPlugn.GenerateSW({
      clientsClaim: true,
      skipWaiting: true,
    }),
]

// 入口文件

if('serviceWorker' in navigator){
  window.addEventListener('load',()=>{
    navigator.serviceWorker.register('/service-worker.js').then(()=>{
      console.log('sw注册成功了');
    }).catch(()=>{
      console.log('sw注册失败了');
    });
  })
}

代码分隔

需要用到webpack的code split功能


optimization:{
    chunks:'all'
}

一般情况下,用默认的就可以。

tree shaking

webpacktree shaking的生效规则是:

  • 通过es6语法引入模块
  • mode为production
  • 代码中通过动态import语句引入,也就是import('xxx').then(console.log('加载成功'))

大文件管理

比如向react、lodash、jquery这些不会经常变动的包,通常建议用externals排除掉,不打包到目标资源中。但是相应的,要通过cdn引入目标资源

dll

externals的作用类似,不过是将资源文件优先打包成dll静态资源,然后通过add-asset-html-webpack-plugin插件自动帮打包好的dll资源引入到html中

具体实现需要用到webpack自带的插件DllPluginDllReferencePlugin。需要先新建一个webpack.dll.js文件,在打包前线执行下该配置文件用于生成dll资源文件。然后再在webpack.config.js中配置入口即可。

/*
  使用dll技术,对某些库(第三方库:vue、react、jquery...)进行单独打包
  当你运行webpack时,默认使用的webpack.config.js配置文件
  使用dll时,得先通过 --config webpack.dll.js 来先执行下dll的配置文件
    --> 先通过运行webpack.dll.js配置文件来生成dll的静态资源和映射文件manifest.json
    --> 然后再走正常的webpack --config webpack.config.js 配置文件,走正常的webpack打包路径即可
*/

const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    // 最终生成的[name] --> jquery
    // ['jquery'] --> 要打包的库是jquery
    jquery: ['jquery']
  },
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'dll'),
    library: '[name]_[hash]' // 打包的库里面向外暴露出去的内容叫什么名字,如:jquery本身暴露出去的是$或者jQuery,我们这里改成[name]_[hash]的形式
  },
  module: {},
  plugins: [
    // 打包生活一个manifest.json的文件 --> 提供上面ouput的库的映射关系
    new webpack.DllPlugin({
      name: '[name]_[hash]', // 映射库的export的名称,对应上之前output的库
      path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
    })
  ],
  mode: 'production'
}


// webpack.config.js
plugins:[
    // 将dll的静态资源通过manifest.json文件做映射
    new webpack.DllReferencePlugin({
      manifest: resolve(__dirname, 'dll/manifest.json'),
    }),
]

结语

往期好文推荐「我不推荐下,大家可能就错过了史上最牛逼vscode插件集合啦!!!(嘎嘎~)😄」