关闭

webpack打包优化的四种方法(多进程打包,多进程压缩,资源 CDN,动态 polyfill)

时间: 2019-11-16阅读: 1132标签: 打包

如今,webpack 毫无疑问是前端构建领域里最耀眼的一颗星,无论你前端走哪条路线,都需要有很强的webpack 知识。webpack 的基本用法这里就不展开讲了。主要探讨一下如何提高 webpack 的打包速度。这篇文章以 vue cli3.0+,webpack4.0+,nodejs10.0+ 这几个版本为例。


一、打包分析

1.1、速度分析

我们的目的是优化打包速度,那肯定需要一个速度分析插件,此时 speed-measure-webpack-plugin 就派上用场了。它的作用如下:

  • 分析整个打包总耗时
  • 每个 plugin 和 loader 的耗时情况

首先,安装插件

npm i -D speed-measure-webpack-plugin

然后修改 vue.config.js 配置文件 (vuecli3+ 版本的配置文件统一在这个文件里修改,如果没有该文件,在根目录新建一个)

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

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

module.exports = {
    configureWebpack: smp.wrap({
        plugins: [
            // 这里是自己项目里需要使用到的其他插件
            new yourOtherPlugin()
        ]
    })
}

运行打包命令之后,可以看到,打包总耗时为 2min,51.99s

1.2、体积分析

分析完打包速度之后,接着我们来分析打包之后每个文件以及每个模块对应的体积大小。使用到的插件为 webpack-bundle-analyzer,构建完成后会在 8888 端口展示大小。

首先,安装插件

npm i -D webpack-bundle-analyzer

修改 vue.config.js 配置文件

// 导入速度分析插件
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


二、打包优化

2.1、多进程多实例构建,资源并行解析

多进程构建的方案比较知名的有以下三个:

  • 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.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.3、多进程多实例并行压缩

并行压缩主流有以下三种方案

  • 使用 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.4、使用 polyfill 动态服务

动态 polyfill 指的是根据不同的浏览器,动态载入需要的 polyfill。 Polyfill.io 通过尝试使用 polyfill 重新创建缺少的功能,可以更轻松地支持不同的浏览器,并且可以大幅度的减少构建体积。

Polyfill Service 原理

识别 User Agent,下发不同的 Polyfill

使用方法:在 index.html 中引入如下 script 标签

<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>
转载请注明出处:https://www.jianshu.com/p/481e7214a134
作者:TSY,个人空间:https://hxkj.vip

 

站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/6473

关闭

使用 pkg 打包 ThinkJS 项目

在 ThinkJS 的用户群里,经常有开发者提出需要对源码进行加密保护的需求。我们知道 JavaScript 是一门动态语言,不像其他静态语言可以编译成二进制包防止源码泄露。所以就出现了 pkg、nexe 之类的工具

Webpack 打包含动态加载的类库

在编写库的时候,我们有时候会希望按需加载某些依赖,例如如果代码的运行环境不支持某些功能的话,就加载相关的Polyfill。webpack作为当前最流行的打包工具,早已支持动态加载的功能了。本文将讨论一种用webpack打包含动态加载的类库的方法。

在前端中如何更好地优化打包资源

在前端中但凡谈到打包,肯定要提及到 webpack,毕竟它现在已经是最为流行的打包工具。但 webpack 更多地是表现在 术 上,于是我决定写这篇文章,更多地讲解一些关于 道 的。对于一个前端而言,生产环境的静态资源优化,它既是面试中的高频问题

前端js打包工具

打包工具可以更好的管理html,css,javascript,使用可以锦上添花,不使用也没关系。html好比是房子的地基,css和 javascript是房子的建筑材料,这三个部分一起组成个漂亮的房子

基于vue-cli的webpack打包优化实践及探索

webpack打包工具成为了前端开发中必备工具,曾经一度的面试题都是问,请问前端页面优化的方式有哪些?大家也是能够信手拈来的说出缓存、压缩文件、CSS雪碧图以及部署CDN等等各种方法

Js模块打包 exports和require 与 export和import 的用法和区别

CommoneJS规定每个文件是一个模块。将一个JavaScript文件直接通过script标签引入页面中,和封装成CommonJS模块最大的不同在于:前者的顶层作用域是全局作用域,在进行变量及函数声明时会污染全局环境;

解决webpack打包速度慢的解决办法

webpack在打包的时候第一次总是会做很长的准备工作,包括加载插件之类的。在刚接触webpack的时候总是webpack一下-测一下-改一下-再webpack一下,这种方式最后让很多人崩溃了觉得webpack一点都不好用

vue实现分环境打包步骤

在新建好的项目中,一般执行npm run build就是打包了,但此时只能打包到一个环境,不同环境需要配置不同的地址,可以手动更改接口的地址,也可以自行配置命令而不需要每次打包进行地址切换

Webpack安装配置及打包详细过程

前端经过漫长的发展,涌现出了很多实践方法来处理复杂的工作流程,让开发变得更加简便,其中,模块化可以使复杂的程序细化成为各个小的文件,而webpack并不强制你使用某种模块化方案,而是通过兼容所有模块化方案让你无痛接入项目

webpack打包原理

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!