搞一波webpack打包优化

1,433 阅读3分钟

Image

简述一波


最近前端面试被考webpack优化的应该不少,无疑webpack的优化是我们前端必须掌握的知识点之一,所以该文从打包速度分析打包优化入手。webpack的基础用法就不举例了,直接走一波好吧。

一、打包分析

1.1 打包速度分析

这里用到了speed-measure-webpack-plugin可以看每个pluginloader打包时间,用来对比优化前后差距的,安装就对了:

npm i speed-measure-webpack-plugin -D

配置的话cli2、跟cli3是有区别的

	//webpack.config.js ------------->cli2
	const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
    const smp = new SpeedMeasurePlugin();

    module.exports = smp.wrap(webpackConfig, {
      plugins: [
      	//所用到的插件
      ]
	});

	// cli3
    const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
    const smp = new SpeedMeasurePlugin({
      outputFormat: 'human'
    })
    module.exports = {
      configureWebpack: smp.wrap({
        plugins: []
      })
    }

配置完再跑项目就可以看到致死量: 打包

1.2 打包体积

看完打包速度,还要看下模块的大小。安装插件webpack-bundle-analyzer,安装完后可以在端口8888

配置的话直接简单,引入然后直接写进plugins就ok了

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const webpackConfig:{
	...
    plugins: [
	...
    new BundleAnalyzerPlugin()  //一定要放在其他插件的后面
  ]
}


二、打包优化

2.1 多线程打包

目前用的比较多的多线程打包有这三:
  • thread-loader (webpack4.0推荐使用这个)

  • parallel-webpack

  • HappyPack

我的项目比较老就用了:HappyPack. 就能让 Webpack 做到这点,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。安装

npm install --save-dev happypack
//webpack.config.js
const HappyPack = require('happypack')
const os = require('os')
//os.cpus返回一个对象数组,包含所安装的每个 CPU/内核的信息
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })


const webpackConfig:{
	...
    plugins: [
	...
    new BundleAnalyzerPlugin()  //一定要放在其他插件的后面
    ++++
    new HappyPack({
      id: 'happy-js',
      loaders: ['babel-loader?cacheDirectory=true'],
      threadPool: happyThreadPool,//共享进程池
    })
  ]
  ...
    module: {
		rules:[
        	 {
              test: /\.js$/,
              // loader: 'babel-loader', //用happypack替代
              loader: 'happypack/loader?id=happy-js', // 增加新的HappyPack构建loader
              include: [resolve('./'), resolve('test'), resolve('../../node_modules/webpack-dev-server/client')],
            },
        ]
    }
}

2.2 代码压缩

webpack版本比较老用uglifyjs-webpack-plugin,比较新的用terser-webpack-plugin。 我们这里用uglifyjs-webpack-plugin

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')


plugins:[
	 new UglifyJsPlugin({
        uglifyOptions: {
          mangle: {      
            safari10: true    
        },
          compress: {
            warnings: false,
            drop_debugger: false,//去除debug和console
            drop_console: false,
            parallel: true,  //使用多进程并行运行来提高构建速度
          }
        },
        sourceMap: config.build.productionSourceMap,
        cache: true,
        parallel: true
    }),
]
        

2.3 开启缓存

2.3.1 hard-source-webpack-plugin

在webpack4.0开始就可以用hard-source-webpack-plugin使用方法也很简单,安装

npm i -D hard-source-webpack-plugin
//	webpack.config.js
  	const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

    module.exports = {
      // ......
      plugins: [
        new HardSourceWebpackPlugin() // <- 直接加入这行代码就行
      ]
    }

2.3.2 dllPlugin

目前dll已经不维护了,主要原理就是把第三方依赖提前打包,把打包好的json映射文件引入项目,这样就可以不用每次都去打包这些没改变的第三方依赖

使用方法比hardSourceWebpackPlugin繁琐:

	//新建webpack.dll.conf.js
    const webpack = require('webpack');
	const path = require('path');
    
    module.exports = {
        entry: {
            vendor: ['vue', 'vuex','vue-router',...所需依赖]
        },
        output: {
        	path: path.resolve(__dirname, '../static/js'),
            filename: 'dll.[name].js'
        },
        plugins: [
            new webpack.DllPlugin({
                path: '[name]-manifest.json'name: '[name]',      
	            context: __dirname 
            })
        ]
    }

执行webpack --config ./build/webpack.dll.conf.js会在static/js文件夹下生成dll.vendor.js以及在根目录下生成mainfest.json,接着在webpack.config.js中引入

     // webpack.base.conf.js
     const manifest = require('../manifest.json')    

     // 插件中引入
     plugins: [
       new webpack.DllReferencePlugin({
           mainfest
        })
     ]

最后再index.html中映入就可以了

<script type="text/javascript" src="/static/js/dll.vendor.js"></script>