此 Codelab 探讨了如何缩减和压缩 JavaScript bundle 来降低页面性能, 应用的请求大小
测量
在深入研究如何进行优化之前,最好先分析 应用的当前状态。
- 如需预览网站,请按查看应用。然后按 全屏 。
此应用也在“移除未使用的” “代码”Codelab,可让您为自己最喜欢的代码投票 小猫。🐈
现在,我们来看看此应用的大小:
- 按 `Ctrl+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
- 点击网络标签页。
- 选中停用缓存复选框。
- 重新加载应用。
尽管在“移除未使用的代码”部分已经取得了很多进展, 缩减此 bundle 的大小,225 KB 仍相当大。
缩减大小
请参考以下代码块。
function soNice() {
let counter = 0;
while (counter < 100) {
console.log('nice');
counter++;
}
}
如果将此函数保存在它自己的文件中,则文件大小大约为 112 B(字节)。
如果移除所有空格,生成的代码将如下所示:
function soNice(){let counter=0;while(counter<100){console.log("nice");counter++;}}
现在,文件大小约为 83 B。如果减少 更改名称的长度以及修改某些表达式,那么最终代码 最终将如下所示:
function soNice(){for(let i=0;i<100;)console.log("nice"),i++}
文件大小现已达到 62 B。
每一步,代码的阅读难度都会增加。不过,浏览器的 JavaScript 引擎会以完全相同的方式解读上述每项信息。通过 以这种方式混淆代码的优势有助于缩小文件 尺寸。112B 开始时其实并不多,但仍然有 50% !
在此应用中,webpack版本 4 用作
模块打包器。具体版本可在 package.json
中查看。
"devDependencies": {
//...
"webpack": "^4.16.4",
//...
}
默认情况下,版本 4 在生产模式下已缩减 bundle 的大小。它使用
TerserWebpackPlugin
是 Terser 的插件。
Terser 是一种用于压缩 JavaScript 代码的常用工具。
要了解缩减后的代码是什么样的,请继续并点击
main.bundle.js
(同时仍位于开发者工具的 Network 面板中)。现在,点击
响应标签页。
经过缩减和破坏的最终形式代码会显示在响应正文中。
如需了解软件包在不缩减大小的情况下的大小,请打开
webpack.config.js
并更新 mode
配置。
module.exports = {
mode: 'production',
mode: 'none',
//...
重新加载应用,并通过 开发者工具 Network 面板
差异很大!😅
请务必先还原此处的更改,然后再继续。
module.exports = {
mode: 'production',
mode: 'none',
//...
在应用中加入缩减代码大小的流程取决于所使用的工具 所用资源:
- 如果使用的是 webpack v4 或更高版本,则无需执行任何其他操作 因为在生产模式下,代码默认会被缩减。👍
- 如果使用的是旧版 Webpack,请安装并包含
TerserWebpackPlugin
添加到 Webpack 构建流程中文档 将对此进行详细介绍 - 还有其他缩减大小插件,可以改用。 例如 BabelMinifyWebpackPlugin 和 ClosureCompilerPlugin。
- 如果根本没有使用模块打包器,请使用 Terser 作为 CLI 工具,或直接将其添加为依赖项。
压缩
虽然术语“压缩”有时用于解释代码的 它实际上并不会在压缩过程中压缩 字面意义。
压缩通常是指使用数据修改的代码 压缩算法。与收缩功能不同 有效代码,则需要先将压缩后的代码解压缩,然后才能使用。
对于每个 HTTP 请求和响应,浏览器和网络服务器都可以将
要包含的标题
有关正在提取或接收的资源的其他信息。可以是
可在开发者工具 Network 面板内的 Headers
标签页中查看,其中有三种类型
示例:
- General 表示与整个请求-响应相关的常规标头 互动
- Response Headers 显示实际响应的专属标头列表 。
- Request Headers 会显示 客户端。
查看 Request Headers
中的 accept-encoding
标头。
accept-encoding
:浏览器使用 accept-encoding
来指定
编码格式或压缩算法。有很多
文本压缩算法,但只有三种
用于压缩(和解压缩)HTTP 网络请求:
- Gzip (
gzip
):最常用的压缩工具 服务器和客户端交互的格式。它建立在 Deflate 的基础上, 算法,目前所有的浏览器均支持此功能。 - Deflate (
deflate
):不常用。 - Brotli (
br
):较新的压缩方法 旨在进一步提高压缩比的算法, 提高网页加载速度在 大多数浏览器的最新版本。
本教程中的示例应用与 移除未使用的代码 Codelab,但以下情况除外: Express 现在用作服务器框架。在未来 我们只探讨了静态压缩和动态压缩两个部分。
动态压缩
动态压缩涉及在素材资源生成时即时对其进行压缩 。
优点
- 创建和更新已保存的压缩版素材资源无需 完成。
- 实时压缩功能特别适用于 动态生成的图片。
缺点
- 在较高级别压缩文件以实现更好的压缩比 用时更长在用户等待素材资源更新时,这可能会导致性能下降 在服务器发送之前对其进行压缩。
使用 Node/Express 进行动态压缩
server.js
文件负责设置用来托管的节点服务器
应用。
const express = require('express');
const app = express();
app.use(express.static('public'));
const listener = app.listen(process.env.PORT, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
目前所做的就是导入 express
并使用 express.static
加载网页中的所有静态 HTML、JS 和 CSS 文件,
public/
目录(这些文件由 webpack 在每次构建时创建)。
为了确保所有资源在每次收到请求时都会进行压缩,
压缩中间件库可以
。首先,在 package.json
中将其添加为 devDependency
:
"devDependencies": {
//...
"compression": "^1.7.3"
},
将其导入服务器文件 server.js
:
const express = require('express');
const compression = require('compression');
在装载 express.static
之前,将其添加为中间件:
//...
const app = express();
app.use(compression());
app.use(express.static('public'));
//...
现在,重新加载应用,并在 Network 面板中查看 bundle 大小。
从 225 KB 到 61.6 KB!现在,在 Response Headers
中,content-encoding
标头显示服务器正在发送这个使用 gzip
编码的文件。
静态压缩
静态压缩背后的理念是压缩和保存资源 。
优点
- 高压缩级别导致的延迟不再是问题。 无需实时进行压缩,因为现在可直接提取文件。
缺点
- 每次构建时都需要压缩资源。构建时间可能会增加 如果使用高压缩级别,则会出现明显的差异。
使用 Node/Express 和 webpack 进行静态压缩
由于静态压缩涉及预先压缩文件,因此 webpack
可以在构建步骤中修改设置,以压缩资源。
CompressionPlugin
可以用于实现这一点
首先,在 package.json
中将其添加为 devDependency
:
"devDependencies": {
//...
"compression-webpack-plugin": "^1.1.11"
},
与任何其他 webpack 插件一样,请将其导入配置文件,
webpack.config.js:
const path = require("path");
//...
const CompressionPlugin = require("compression-webpack-plugin");
并将其包含在 plugins
数组中:
module.exports = {
//...
plugins: [
//...
new CompressionPlugin()
]
}
默认情况下,该插件会使用 gzip
压缩 build 文件。一睹为快
参阅文档
以了解如何添加选项,以便使用其他算法或包含/排除选项
特定文件
当应用重新加载并重新构建时,系统会生成主软件包的压缩版本
已创建完成。打开 Glitch 控制台,查看
最终的 public/
目录。
- 点击工具按钮。
- 点击控制台按钮。
- 在控制台中,运行以下命令以切换到
public
目录并查看其中的所有文件:
cd public
ls
压缩包的 Gzip 版本 main.bundle.js.gz
现在在此处另存为
。默认情况下,CompressionPlugin
还会压缩 index.html
。
接下来需要做的是告诉服务器
文件的原始 JS 版本。为此,
方法是在 server.js
中定义一个新路由,然后再使用
express.static
。
const express = require('express'); const app = express(); app.get('*.js', (req, res, next) => { req.url = req.url + '.gz'; res.set('Content-Encoding', 'gzip'); next(); }); app.use(express.static('public')); //...
app.get
用于告知服务器如何响应
特定端点。然后,使用回调函数来定义如何处理
请求。路线的运作方式如下:
- 指定
'*.js'
作为第一个参数意味着这适用于每个 用于提取 JS 文件而触发的端点。 - 在回调中,
.gz
会附加到请求的网址,并且Content-Encoding
响应标头设置为gzip
。 - 最后,
next()
可确保序列继续执行任何回调 可能是下一个。
应用重新加载后,请再次查看 Network
面板。
和以前一样,软件包大小显著减小!
总结
此 Codelab 介绍了缩减和压缩源代码的过程。 这两种技术已成为许多工具中的默认技术, 因此重要的是,确定您的工具链是否已 还是您应该自行开始同时采用这两个流程。