效果展示

打包时间:缩短了 26.296s-20.586s=5.71s

先看两组测试数据,第一组是没有使用DllPlugin的打包测试数据,测量三次取平均值是26.296s
(25.72+25.56+27.61)/3≈26.296s

第二组是使用了DllPlugin的打包测试数据,测量三次取平均值是20.586s
(20.62+21.31+19.83)/3≈20.586s 

打包体积:减少了 8.72M-4.8M=3.92M

没用动态库之前是8.72M

用了动态库之后是1.8M+2958K≈4.8M
 

减少的原因是避免了在业务代码中重复引入第三方工具包。

为什么会快?

我们的项目代码,可以分为第三方工具包和业务代码,第三方工具包一般比较成熟,用webpack打包编译过,无需每次项目构建时都再次打包。可以把这部分代码从剥离出去,通过外链script标签引入,每次构建,只打包业务代码。所以能缩短整体打包时间。

如何实现

要想实现这样的效果,你需要在现有项目的基础上,做如下配置:

第一步,安装依赖

yarn add -D assets-webpack-plugin clean-webpack-plugin webpack-bundle-analyzer

第二步,编写生成dll库的webpack配置文件

const path = require("path");
const webpack = require("webpack");
const WebpackBar = require("webpackbar");
const AssetsPlugin = require("assets-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); // 打包前清空dll文件夹
// 读取package.json里的运行依赖包
const pkg = require("../package.json");
let dependencies = Object.keys(pkg.dependencies) || [];
dependencies = dependencies.length > 0 ? dependencies : []; console.log("dll", dependencies);
module.exports = {
entry: {
dll: dependencies,
},
mode: "production",
output: {
path: path.resolve(__dirname, "../dll"),
filename: "[name]_[hash:6].js",
library: "[name]_[hash:6]", // 暴露给外部使用
// libraryTarget 指定如何暴露内容,缺省时就是 var
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [path.resolve(__dirname, "../dll/*.*")],
}),
new webpack.DllPlugin({
path: path.resolve(__dirname, "../dll", "[name]-manifest.json"),
name: "[name]_[hash:6]", // name和library一致
}),
// 把带hash的dll.js插入到index.html中,和html-webpack-plugin插件配合使用,告诉html-webpack-plugin插入的dll.js文件名称
new AssetsPlugin({
filename: "dll-config.json",
path: "./dll/",
}),
// webpackbar可以在打包时实时显示打包进度
new WebpackBar(),
],
};

在package.json中,添加生成dll库的指令:

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

生成动态库

第三步:在index.html静态模板中,加载动态库

<!DOCTYPE html>
<html lang="zh-cn"> <head>
<meta charset="utf-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover" />
<meta name="theme-color" content="#000000" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<title></title>
</head> <body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="//at.alicdn.com/t/font_1343302_nuzqn1v7zae.js"></script>
<!-- 插入动态库 -->
<% if (htmlWebpackPlugin.options.dllJsName) { %>
<script src="<%= htmlWebpackPlugin.options.dllJsName %>"></script>
<% } %>
<!-- iconfont svg地址 -->
</body> </html>

第四步:在webpack.base.js中,配置动态库加载和库映射文件路径

// 是否为本地开发环境
const isDev = process.env.NODE_ENV === "development";
// 根目录
const basename = process.env.BASE_NAME ? `${process.env.BASE_NAME}/` : "/";
const publicPath = isDev ? "/" : `/${basename}`;
// 这里的路径与webpack文件夹下的dll.js配置文件中的路径保持一致
const dllConfig = require("../dll/dll-config.json");
const manifest = require("../dll/dll-manifest.json"); module.exports = {
plugins: [
new HtmlPlugin({
template: path.resolve(rootPath, "./index.html"),
favicon: path.resolve(rootPath, "./favicon.ico"),
// index.html中加载dll的script标签的src地址
dllJsName: isDev ? `${publicPath}dll/${dllConfig.dll.js}` : "",
// html压缩
minify: {
collapseWhitespace: true,
preserveLineBreaks: true,
},
}),
// 加载生成的dll库
isDev
? new webpack.DllReferencePlugin({
manifest,
})
: () => {},
],
};

打包构建时,查看打包内容和大小的配置

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; // 包分析工具
module.module.exports = () => {
return merge(webpackBaseConfig, {
plugins: [
process.argv.indexOf("--pa") !== -1
? new BundleAnalyzerPlugin()
: () => {},
],
});
};

没使用动态库之前入口文件大小是1.43M

使用了动态库之后入口文件大小是648K

问题与解答

首页加载速度对比:使用动态库之后,首页加载速度变慢了3.08 - 2.51 =0.57s

使用动态库之前,首页加载时间是2.51s

使用动态库之后,首页加载时间是3.08s

使用了动态库之后,如何不拖慢首页的加载速度?

首页加载速度变慢了一些,是由于打包的第三方库,不再是按需加载,而是在首页一次性加载,要改善这种情况,有两条思路:

1.缩小打包体积,只把每个页面都会用到的三方工具打包进动态库, 还有对打包之后的内容进行gzip压缩。

2.只在开发环境使用动态库功能。

Dll和External的区别

对于如下的引用, Dll直接将库的应用指向xxx库,不会再把xxx/lib/module打包,而External则认为 import Foo from 'xxx' 和 import AA from 'xxx/lib/module',是引用了两个不同的库,因此xxx在项目中已经存在的情况下, xxx/lib/module还会被打包进项目。用import Foo from 'xxx/lib/module'这样的方式引用模块,使用动态库是比较吃亏的。

import Foo from 'xxx/lib/module'

WebPack系列--开启HappyPack之后,再将项目打包速度缩短5秒的更多相关文章

  1. sencha touch 入门系列 扩展篇之sencha touch 项目打包压缩

    经常有新手同学抱怨说sencha touch的项目加载速度为什么这么慢,经常要10秒左右的时间甚至更多, 大家都知道,sencha touch开发的项目中引用了大量的js文件,当我们打开项目时,st的 ...

  2. vue+webpack+element-ui项目打包优化速度与app.js、vendor.js打包后文件过大

    从开通博客到现在也没写什么东西,最近几天一直在研究vue+webpack+element-ui项目打包速度优化,想把这几天的成果记录下来,可能对前端牛人来说我这技术比较菜,但还是希望给有需要的朋友提供 ...

  3. vue项目打包文件配置(vue-clli3)

    练手项目完结打包的时候遇到一些问题,特此记录 先贴我的vue.config.js文件的代码(vue-cli3构建的项目默认是没有此文件的,需手动添加)更多详细配置参考官方配置文档,我的项目不大不小,这 ...

  4. Vue实战Vue-cli项目构建(Vue+webpack系列之一)

    用Vue比较长一段时间了,大大小小做了一些项目,最近想总结一下知识点,出一个Vue+webpack系列,先从项目构建说起--vue-cli. 由于是Vue+webpack这里就不赘述git那些东西,默 ...

  5. 深入浅出的webpack构建工具---HappyPack优化构建(九)

    阅读目录 一:什么是HappyPack? 作用是什么? 二:如何在配置中使用HappyPack? 回到顶部 一:什么是HappyPack? 作用是什么? Webpack是允许在NodeJS中的,它是单 ...

  6. Webpack系列-第三篇流程杂记

    系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 本文章个人理解, 只是为了理清webpack流程, 没有关注内部过多细节 ...

  7. 实战webpack系列03

    03.Webpack的强大功能 一.生成Source Maps(使调试更容易) 通过简单的配置,webpack就可以在打包时为我们生成的source maps,这为我们提供了一种对应编译文件和源文件的 ...

  8. 【webpack 系列】基础篇

    Webpack 基础篇 基本概念 Webpack 是一个现代 JavaScript 应用程序的静态模块打包器.当 webpack 处理应用程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每 ...

  9. 【webpack 系列】进阶篇

    本文将继续引入更多的 webpack 配置,建议先阅读[webpack 系列]基础篇的内容.如果发现文中有任何错误,请在评论区指正.本文所有代码都可在 github 找到. 打包多页应用 之前我们配置 ...

随机推荐

  1. linux调度全景指南

  2. KMP(超详细复杂度分析)

    从 stackoverflow中找到了一个时间复杂度分析很棒的链接 https://www.inf.hs-flensburg.de/lang/algorithmen/pattern/kmpen.htm ...

  3. Elastic App Search 快速构建 ES 应用

    公号:码农充电站pro 主页:https://codeshellme.github.io App Search 是 Elastic 家族中的一个产品,它可以帮助我们(基于 ES)快速高效的构建搜索应用 ...

  4. POJ-1459(最大流+EK算法)

    Power Network POJ-1459 这题值得思索的就是特殊的输入,如何输入一连串字符.这里采用的方法是根据输入已知的输入格式,事先预定好要接受的数据类型. 这里套用的板子也是最大流的模板,但 ...

  5. Apache配置 1. 默认虚拟主机

    编辑httpd.conf搜索httpd-vhosts,去掉#号 # vi /usr/local/apache2.4/conf/httpd.conf Include conf/extra/httpd-v ...

  6. vue 弹窗禁止底层滚动

    原因:底层视图高度超出百分百,加入弹窗后再苹果浏览器隐藏上下栏的情况下遮罩层没有完全遮住底层. 处理:打开弹窗后禁止底层滚动调用stop事件,关闭则开启底层滚动调用move事件. let mo=fun ...

  7. java 实现快速排序

    package leetcode;public class Singleton { public static void sort(int[] array,int low,int high){ int ...

  8. POJ1562_Oil Deposits(JAVA语言)

    思路:bfs.水题,标记下计数就完了. Oil Deposits Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22928 ...

  9. P1177【模板】快速排序(JAVA语言)

    import java.util.Scanner; import java.util.ArrayList; import java.util.Collections; import java.util ...

  10. 使用C# (.NET Core) 实现命令设计模式 (Command Pattern)

    本文的概念内容来自深入浅出设计模式一书. 项目需求 有这样一个可编程的新型遥控器, 它有7个可编程插槽, 每个插槽可连接不同的家用电器设备. 每个插槽对应两个按钮: 开, 关(ON, OFF). 此外 ...