YIngChenIt/Blogs

webpack性能优化

Opened this issue · 0 comments

webpack性能优化

这个文章记录一下一些webpack层面的优化方式

noParse

当我们项目使用一些第三方库像jquery的时候,webpack回去解析jquery是否依赖其他模块,增加了打包时间,这个步骤其实是没有必要的,我们可以设置noParsewebpack不去解析jquery

module: {
    noParse: /jquery/,
    rules: [...]
}

lgnorePlugin

项目中一般都是用了moment这个时间插件,但是这个时间插件会引入全部的语言包,增大了很多打包之后文件的体积,这个时候我们可以用webpack内置的插件lgnorePlugin忽略掉引入的语言包

plugins: [
    new webpack.IgnorePlugin(/\.\/locale/, /moment/)
]

忽略掉moment包中对./locale的引入,就是忽略语言包的引入,然后我们在手动引入需要的语言就好了

import 'moment/locale/zh-cn'

dllPlugin

react项目为例,我们可以通过动态链接库将react react-dom抽离出来,这样的话开发的时候就不会每次都打包这2个库了

首先我们需要新起一个webpack打包配置,将react react-dom先进行打包

// webpack.react.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
    mode: 'development',
    entry: {
        react: ['react', 'react-dom']
    },
    output: {
        filename: '_dll_[name].js',
        path: path.resolve(__dirname, 'dist'),
        library: '_dll_[name]'
    },
    plugins: [
        new webpack.DllPlugin({
            name: '_dll_[name]',
            path: path.resolve(__dirname, 'dist', 'manifest.json')
        })
    ]
}
//  library: '_dll_[name]' 的作用是将打包出来的自执行函数赋值给_dll_react
//  DllPlugin 插件会生成一个清单文件`'manifest.json`

然后我们配置一下正式的webpack配置

// webpack.config.js
plugins: [
    new webpack.DllReferencePlugin({
        manifest: path.resolve(__dirname, 'dist', 'manifest.json')
    })
]

我们还需要在模板html文件中手动引入打包好的react文件

// index.html
<script src="/_dll_react.js"></script>

这样的话每次打包的时候会先根据清单去我们的动态链接库找react,如果有就使用,没有在自己解析打包

happypack

我们的webpack可以通过happypack进行多线程打包

const Happypack = require('happypack')
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'Happypack/loader?id=js'
            }
        ]
    },
    plugins: [
        new Happypack({
            id: 'js',
            use: [
                {
                    loader: 'babel/loader',
                    options: {
                        presets: [
                            '@babel/preset-env'
                        ]
                    }
                }
            ]
        })
    ]
}

通过id表示,开启一个新的线程来单独打包js文件,在项目中我们可以为js、css等开启各自的线程进行打包

tree-shaking

tree-shakingwebpack自带的优化手段,用于生产模式下会自动去除掉没有使用到的代码

这里需要注意的一点是

import unit from './unit.js'
const unit require('./unit.js')

unit.add()

这2种写法是有区别的,用import会触发tree-shaking,即unit中除了add方法以外的都不会打包,而require不会触发tree-shaking

抽离公用代码

当我们打包多页应用的时候我们可以将一些公共代码和公用第三方模块进行抽离

module.exports = {
    optimization: {
        splitChunks: {
            cacheGroups: {
                common: { //公共代码
                    chunks: 'initial',
                    minSize: 0, // 大小超过0kb就抽离
                    minChunks: 2, //使用超过2次就抽离
                },
                vendor: {
                    priority: 1, //权重是1 表示先抽离第三方模块在抽离公共代码
                    test: /node_modules/,// 抽离的位置
                    chunks: 'initial',
                    minSize: 0, // 大小超过0kb就抽离
                    minChunks: 2, //使用超过2次就抽离
                }
            }
        }
    }
}

这样就可以实现代码抽离了

懒加载

我们可以使用一种提案语法实现懒加载import

但是需要引入一个第三方模块@babel/plugin-syntax-dynamic-import

我们可以这样使用

import('./a.js').then((data) => {
    ....
})

不管是vue还是react的路由懒加载都是利用的这个语法import,其实这个语法内部是通过jsonp来实现的

热更新

我们可以配置热更新,这样的话就不用每次改代码都刷新页面了

devServer: {
    port: 3000,
    hot: true,
},
plugins: [
    new webpack.NamedModluesPlugin(), //打印更新的路径
    new webpack.HotModuleReplacementPlugin() // 热更新的插件
]