webpack 打包優化的四種方法(多進程打包,多進程壓縮,資源 CDN,動態 polyfill)

現在,webpack 毫無疑問是前端構建領域裏最耀眼的一顆星,不管你前端走哪條路線,都須要有很強的webpack 知識。webpack 的基本用法這裏就不展開講了。主要探討一下如何提升 webpack 的打包速度。css

這篇文章以 vue cli3.0+webpack4.0+nodejs10.0+ 這幾個版本爲例。html

1、打包分析

1.一、速度分析

咱們的目的是優化打包速度,那確定須要一個速度分析插件,此時 speed-measure-webpack-plugin 就派上用場了。它的做用以下:前端

  • 分析整個打包總耗時
  • 每一個 pluginloader 的耗時狀況

首先,安裝插件vue

npm i -D speed-measure-webpack-plugin

而後修改 vue.config.js 配置文件 (vuecli3+ 版本的配置文件統一在這個文件裏修改,若是沒有該文件,在根目錄新建一個)node

// 導入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

// 實例化插件
const smp = new SpeedMeasurePlugin();

module.exports = {
    configureWebpack: smp.wrap({
        plugins: [
            // 這裏是本身項目裏須要使用到的其餘插件
            new yourOtherPlugin()
        ]
    })
}

運行打包命令以後,能夠看到,打包總耗時爲 2min,51.99s
webpack

1.二、體積分析

分析完打包速度以後,接着咱們來分析打包以後每一個文件以及每一個模塊對應的體積大小。使用到的插件爲 webpack-bundle-analyzer,構建完成後會在 8888 端口展現大小。ios

首先,安裝插件web

npm i -D webpack-bundle-analyzer

修改 vue.config.js 配置文件vue-router

// 導入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

// 導入體積分析插件
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;

// 實例化速度分析插件
const smp = new SpeedMeasurePlugin();

module.exports = {
    configureWebpack: smp.wrap({
        plugins: [
            // 實例化體積分析插件
            new BundleAnalyzerPlugin()
        ]
    })
}

構建以後能夠看到,其中黃色塊 chunk-vendors 文件佔比最大,爲 1.34MB
vuex

2、打包優化

2.一、多進程多實例構建,資源並行解析

多進程構建的方案比較知名的有如下三個:

  • thread-loader (推薦使用這個)
  • parallel-webpack
  • HappyPack

這裏以 thread-loader 爲例配置多進程多實例構建
安裝 loader

npm i -D thread-loader

接下來在 vue.config.js 配置文件中使用該 loader

// 導入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

// 實例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
    configureWebpack: smp.wrap({
        module: {
            rules: [
                {
                    test: /\.js$/,
                    use: ['thread-loader']
                }
            ]
        }
    })
}

而後看下構建花費的時間, 2min,49.21s,相較於以前提高了 5s

2.二、公用代碼提取,使用 CDN 加載

對於vue,vuex,vue-router,axios,echarts,swiper等咱們能夠利用webpack的externals參數來配置,這裏咱們設定只須要在生產環境中才須要使用。
下面配置 vue.config.js

// 導入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

// 導入體積分析插件
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;

//判斷是否爲生產環境
const isProduction = process.env.NODE_ENV === 'production';

//定義 CDN 路徑,這裏採用 bootstrap 的 cdn
const cdn = {
    css: [
        'https://cdn.bootcss.com/Swiper/4.5.1/css/swiper.min.css'
    ],
    js: [
        'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
        'https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js',
        'https://cdn.bootcss.com/vuex/3.1.1/vuex.min.js',
        'https://cdn.bootcss.com/axios/0.19.0/axios.min.js',
        'https://cdn.bootcss.com/echarts/4.3.0/echarts.min.js',
        'https://cdn.bootcss.com/Swiper/4.5.1/js/swiper.min.js',
    ]
}

// 實例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
    chainWebpack: config => {
        // 生產環境配置
        if (isProduction) {
            // 生產環境注入 cdn
            config.plugin('html')
                .tap(args => {
                    args[0].cdn = cdn;
                    return args;
                });
        }
    },
    configureWebpack: smp.wrap({
        module: {
            rules: [
                {
                    test: /\.js$/,
                    use: ['thread-loader']
                }
            ]
        },
        plugins: [
            new BundleAnalyzerPlugin()
        ],
        //生產環境注入 cdn
        externals: isProduction && {
            'vue': 'Vue',
            'vuex': 'Vuex',
            'vue-router': 'VueRouter',
            'axios': 'axios',
            'echarts': 'echarts',
            'swiper': 'Swiper'
        } || {}
    })
}

緊接着,改造 html 頁面。用於讓咱們配置的 cdn 路徑注入到 html 頁面

<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <!-- 使用 CDN 的 CSS 文件 -->
  <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
    <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
  <% } %>
</head>

<body>
  <noscript>
    <strong>We're sorry but eye-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->

 <!-- 使用 CDN 的 JS 文件 -->
  <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
    <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
  <% } %>
</body>

</html>

最重要的一步,看下效果,能夠看到如今耗時 1min,39.19s,整整提高了 1 分多鐘!

2.三、多進程多實例並行壓縮

並行壓縮主流有如下三種方案

  • 使用 parallel-uglify-plugin 插件
  • uglifyjs-webpack-plugin 開啓 parallel 參數
  • terser-webpack-plugin 開啓 parallel 參數 (推薦使用這個,支持 ES6 語法壓縮)

安裝插件依賴

npm i -D terser-webpack-plugin

接下來在 vue.config.js 配置文件中使用插件,最終的配置文件以下

// 導入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

// 導入代碼壓縮插件
const TerserPlugin = require("terser-webpack-plugin");

// 導入體積分析插件
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;

//判斷是否爲生產環境
const isProduction = process.env.NODE_ENV === 'production';

//定義 CDN 路徑,這裏採用 bootstrap 的 cdn
const cdn = {
    css: [
        'https://cdn.bootcss.com/Swiper/4.5.1/css/swiper.min.css'
    ],
    js: [
        'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
        'https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js',
        'https://cdn.bootcss.com/vuex/3.1.1/vuex.min.js',
        'https://cdn.bootcss.com/axios/0.19.0/axios.min.js',
        'https://cdn.bootcss.com/echarts/4.3.0/echarts.min.js',
        'https://cdn.bootcss.com/Swiper/4.5.1/js/swiper.min.js',
    ]
}

// 實例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
    chainWebpack: config => {
        // 生產環境配置
        if (isProduction) {
            // 生產環境注入 cdn
            config.plugin('html')
                .tap(args => {
                    args[0].cdn = cdn;
                    return args;
                });
        }
    },
    configureWebpack: smp.wrap({
        module: {
            rules: [
                {
                    test: /\.js$/,
                    use: ['thread-loader']
                }
            ]
        },
        plugins: [
            new BundleAnalyzerPlugin()
        ],
        //生產環境注入 cdn
        externals: isProduction && {
            'vue': 'Vue',
            'vuex': 'Vuex',
            'vue-router': 'VueRouter',
            'axios': 'axios',
            'echarts': 'echarts',
            'swiper': 'Swiper'
        } || {},
        optimization: {
            minimizer: [
                new TerserPlugin({
                    parallel: 4
                })
            ]
        }
    })
}

2.四、使用 polyfill 動態服務

動態 polyfill 指的是根據不一樣的瀏覽器,動態載入須要的 polyfillPolyfill.io 經過嘗試使用 polyfill 從新建立缺乏的功能,能夠更輕鬆地支持不一樣的瀏覽器,而且能夠大幅度的減小構建體積。

Polyfill Service 原理

識別 User Agent,下發不一樣的 Polyfill

使用方法:在 index.html 中引入以下 script 標籤

<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>

3、完結

At last,看完以後有什麼不懂的,能夠留言反饋。

轉載請註明出處:https://www.jianshu.com/p/481e7214a134
做者:TSY
我的空間:https://hxkj.vip

相關文章
相關標籤/搜索