效果展示

打包时间:缩短了 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. Spring-03 依赖注入(DI)

    Spring-03 依赖注入(DI) 依赖注入(DI) 依赖注入(Dependency Injection,DI). 依赖 : 指Bean对象的创建依赖于容器,Bean对象的依赖资源. 注入 : 指B ...

  2. 从HashMap面试聊聊互联网内卷

    微信公众号:大黄奔跑 关注我,可了解更多有趣的面试相关问题. 写在之前 毫无疑问,回想2020年有什么词出现在眼前最多的,无疑是"996"和"内卷",从马老师的 ...

  3. Java基本概念:继承

    一.简介 描述: 现实世界中的继承无处不在.比如:动物细分有哺乳动物.爬行动物等,哺乳动物细分有灵长目.鲸目等. 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模. 继承是类和类之间的一种关 ...

  4. 后端程序员之路 45、nginx CORS 跨域

    在提供api给其它应用使用时,有时我们会要限制它的跨域使用,而有时,我们又要用CORS来打破AJAX只能同源使用的限制 跨域资源共享 CORS 详解 - 阮一峰的网络日志http://www.ruan ...

  5. 清晰图解深度分析HTTPS原理

    前言 很高兴遇见你~ Https现在基本已经覆盖所有的http请求了,作为一个伟大的发明,保障了我们的通信安全.在Android中对于HTTPS其实感知不多,因为这些内容都有成熟的框架帮我们完成了,例 ...

  6. Linux速通01 操作系统安装及简介

    操作系统 # a)操作系统的定义:操作系统是一个用来协调.管理和控制计算机硬件和软件资源的系统程序,它位于硬件和应用程序之间. # 操作系统分为 系统调用接口 和 系统内核 # b)操作系统内核的定义 ...

  7. 【H264】视频编码发展简史

    一.常见视频编码格式 编码格式有很多,如下图: 目前比较常用的编码有: H26x系列:由ITU(国际电传视讯联盟)主导,侧重网络传输 MPEG系列:由ISO(国际标准组织机构)下属的MPEG(运动图象 ...

  8. JVM之基础概念(运行时数据区域、TLAB、逃逸分析、分层编译)

    运行时数据区域 JDK8 之前的内存布局 JDK8 之后的 JVM 内存布局 JDK8 之前,Hotspot 中方法区的实现是永久代(Perm),JDK8 开始使用元空间(Metaspace),以前永 ...

  9. pip软件包管理工具介绍及基本使用

    pip软件包管理工具介绍及基本使用 一分耕耘,一分收获,要收获得好,必须耕耘得好.-- 徐特立 一.pip软件包管理工具介绍: 定义:pip是Python包管理工具 作用:对Python包的查找.下载 ...

  10. 7、Spring教程之使用注解开发

    1.说明 在spring4之后,想要使用注解形式,必须得要引入aop的包 <dependency> <groupId>org.springframework</group ...