Webpack系列——打包的性能优化

1.跟上技术的迭代(Node, Npm, Yarn)

对Webpack、Node、Npm、Yarn等技术进行版本的升级,相关技术的版本更新,官网都会做出优化,升级技术可以一定程度的提高打包的性能

2.在模块上尽可能少的应用 Loader

合理的使用 exclude / include 可以降低使用 loader 的频率从而提高打包速度,如 exclude: /node_modules/ 因为 node_modules 中的代码是已经被转换过的代码,可以不必使用 loader 做二次转换。也即尽可能的让 Loader 的作用范围缩小,代码分析的范围少了,性能也就能得到提升。

3.Plugin 尽可能精简并确保可靠

插件需要合理的需用,对于没有意义的插件或冗余的插件应去掉。在使用插件时应首选官方推荐或社区认可的插件。例如在开发环境中不使用插件对 CSS 代码进行压缩,仅在正式环境时才使用,因此,在开发时,代码的打包速率在一定程度上会得到提升。在使用插件时尽可能采用webpack官方推荐的插件,因为这些插件官方进行推荐的话是经过一定的测试验证的。个人或第三方插件的性能并不一定能得到保证。

4.resolve 参数合理配置

在 resolve 中配置解析的顺序:

webpack.config.js

module.exports = {
    entry: {
        main: './src/index.js'
    },
    resolve: {
        extensions: ['.js', '.jsx']
    }
}

index.js

import child from './child/child'

在上面的引入中,因为配置了 resolve.extensions ,所以在引入时没有写上后缀时,webpack 会在 child 文件夹中首先解析是否存在 child.js 文件,如果不存在则继续寻找是否存在 child.jsx文件,如果都不能存在就会报错。extensions 配置的数组列表中不应配置过多的列表项。

在 resolve 中通过 alias 为文件夹设置别名:

webpack.config.js

module.exports = {
    // ...
    resolve: {
        alias: {
            @: path.resolve(__dirname, 'src')
        }
    }
}

index.js

import child from '@/child/child.js'

5.使用 DllPlugin 提高打包速度

因为第三方的库文件等是不会变化的,不必每次打包时都分析,所以对可以对第三方模块只打包一次,生成 dll 文件,引入第三方模块时去使用 dll 文件引入

index.js

import React, { Component } from 'react';
import ReactDom from 'react-dom';
import _ from 'lodash';
​
class App extends Component {
    render() {
        return (
            
{_.join(['This', 'is', 'App'], ' ')}
) } } ​ ReactDom.render(, document.getElementById('root'));

webpack.config.dll.js

const path = require('path');
const webpack = require('webpack');
​
module.exports = {
    mode: 'production',
    entry: {
        vendors: ['lodash'],
        react: ['react', 'react-dom'],
        jquery: ['jquery']
    },
    // 打包成库,通过变量的形式暴露出去
    output: {
        filename: '[name].dll.js',
        path: path.resolve(__dirname, '../dll'),
        library: '[name]'
    },
    // 打包时做一个dll文件分析的映射
    plugins: [
        new webpack.DllPlugin({
            name: '[name]',
            path: path.resolve(__dirname, '../dll/[name].manifest.json'),
        })
    ]
}

package.json

{
    // ...
    "script": {
        // ...
        "build:dll": "webpack --config ./build/webpack.config.dll.js"
        // ...
    }
}

运行命令 npm run build:dll 进行打包

安装 add-asset-html-webpack-plugin 插件,用于在 index.html 中增加静态资源

webpack.config.common.js

const path = require('path');
const fs = require('fs');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
const webpack = require('webpack');
​
const plugins = [
    new HtmlWebpackPlugin({
        template: 'src/index.html'
    }), 
    new CleanWebpackPlugin(['dist'], {
        root: path.resolve(__dirname, '../')
    })
];
​
// 引入第三方模块的时候,去使用打包好的 dll 文件进行引入
const files = fs.readdirSync(path.resolve(__dirname, '../dll'));
files.forEach(file => {
    // 将打包好的 dll 文件引入使用
    if(/.*\.dll.js/.test(file)) {
        plugins.push(new AddAssetHtmlWebpackPlugin({
            filepath: path.resolve(__dirname, '../dll', file)
        }))
    }
    // 分析dll中第三方模块的映射关系进行使用
    // 如果不配置,打包是第三方模块将依旧从 node_modules 中寻找分析
    if(/.*\.manifest.json/.test(file)) {
        plugins.push(new webpack.DllReferencePlugin({
            manifest: path.resolve(__dirname, '../dll', file)
        }))
    }
})
​
module.exports = {
    entry: {
        main: './src/index.js',
    },
    resolve: {
        extensions: ['.js', '.jsx'],
    },
    module: {
        rules: [{ 
            test: /\.jsx?$/, 
            include: path.resolve(__dirname, '../src'),
            use: [{
                loader: 'babel-loader'
            }]
        }, {
            test: /\.(jpg|png|gif)$/,
            use: {
                loader: 'url-loader',
                options: {
                    name: '[name]_[hash].[ext]',
                    outputPath: 'images/',
                    limit: 10240
                }
            } 
        }, {
            test: /\.(eot|ttf|svg)$/,
            use: {
                loader: 'file-loader'
            } 
        }]
    },
    plugins,
    optimization: {
        runtimeChunk: {
            name: 'runtime'
        },
        usedExports: true,
        splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10,
            name: 'vendors',
        }
      }
    }
    },
    performance: false,
    output: {
        path: path.resolve(__dirname, '../dist')
    }
}

6.控制包文件大小

在进行打包时应尽可能让包文件小如不引入不必要的模块代码,去除掉冗余代码,对代码进行 splitChunk 代码拆分,或者 tree-shaking 去除不必要的代码。

7.thread-loader, parallel-webpack, happypack 多进程打包

webpack 默认是通过 node.js 来运行的,是一个单进程的打包过程,可以借助 node 中的多进程提高打包速度。可以借助 thread-loader、happypack利用到 node 中的多进程和多个 CPU 提升打包速度。如果是进行多页应用的打包,还可以借助 parallel-webpack ,对多个页面同时进行打包。

8.合理利用 sourceMap

对于 sourceMap,如果越详细,打包的速度就会越慢,因此可以合理利用 sourceMap 的配置提升打包速度。

9.结合 stats 分析打包结果

命令生成打包的 stats.json 进行分析,对相关的可优化项进行优化。

10.开发环境内存编译

开发环境时使用内存编译,即使用 webpack-dev-server

11.开发环境剔除无用插件

在开发环境,对于一些无用的插件不使用,如不使用代码压缩的插件等

你可能感兴趣的:(webpack,webpack,性能优化,npm)