本代码实验室是缩小和压缩网络有效负载代码实验室的扩展,并假定您熟悉压缩的基本概念。与其他压缩算法(如 gzip
)相比,本代码实验室探讨了 Brotli 压缩 (br
) 如何进一步降低压缩率和应用的总大小。
测量
在深入添加优化之前,最好先分析应用的当前状态。
- 点击 Remix to Edit(混合以编辑) 使项目可编辑。
- 要预览网站,请按 View App(查看应用)。然后按 Fullscreen(全屏)
。
在上一个缩小和压缩网络有效负载代码实验室中,我们将 main.js
的大小从 225 KB 减小到 61.6 KB。在本代码实验室中,您将探索 Brotli 压缩如何进一步减小此捆绑包大小。
Brotli 压缩
Brotli 是一种较新的压缩算法,可以提供比 gzip
更好的文本压缩结果。根据 CertSimple,Brotli 的性能是:
- 对于 JavaScript,比
gzip
小 14% - 对于 HTML,比
gzip
小 21% - 对于 CSS,比
gzip
小 17%
要使用 Brotli,您的服务器必须支持 HTTPS。 所有现代浏览器都支持 Brotli。支持 Brotli 的浏览器将在 Accept-Encoding
标头中包含 br
Accept-Encoding: gzip, deflate, br
您可以使用 Chrome 开发者工具 Network 选项卡中的 Content-Encoding
字段 (Command+Option+I
或 Ctrl+Alt+I
) 确定使用的压缩算法

如何启用 Brotli
如何设置 Web 服务器以发送 Brotli 编码的资源取决于您计划如何对它们进行编码。您的选项是在请求时使用 Brotli 动态压缩资源(动态),或提前对它们进行编码,以便在用户请求它们时它们已经被压缩(静态)。
动态压缩
动态压缩 涉及在浏览器请求资产时即时压缩它们。
优点
- 无需创建和更新资产的已保存压缩版本。
- 即时压缩对于动态生成的网页尤其有效。
缺点
- 以更高的级别压缩文件以实现更好的压缩率需要更长的时间。这可能会导致性能下降,因为用户在服务器发送资产之前等待资产压缩。
使用 Node 和 Express 进行动态压缩
server.js
文件负责设置托管应用的 Node 服务器。
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
中间件来加载 public/directory
中的所有静态 HTML、JS 和 CSS 文件(这些文件由 webpack 在每次构建时创建)。
为确保每次请求资产时都使用 brotli 压缩所有资产,可以使用 shrink-ray
模块。首先将其作为 devDependency
添加到 package.json
中
"devDependencies": {
// ...
"shrink-ray": "^0.1.3"
},
并将其导入到服务器文件 server.js
中
const express = require('express');
const shrinkRay = require('shrink-ray');
并在安装 express.static
之前将其添加为中间件
// ...
const app = express();
// Compress all requests
app.use(shrinkRay());
app.use(express.static('public'));
现在重新加载应用,并在 Network 面板中查看捆绑包大小

您现在可以在 Content-Encoding
标头中看到 brotli
从 bz
应用。main.bundle.js
从 225 KB 减小到 53.1 KB!与 gzip
(61.6 KB) 相比,这小了约 14%。
静态压缩
静态压缩背后的想法是提前压缩和保存资产。
优点
- 高压缩级别造成的延迟不再是问题。现在可以直接获取文件,无需即时压缩文件。
缺点
- 每次构建都需要压缩资产。如果使用高压缩级别,构建时间可能会显着增加。
使用 Node 和 Express 以及 webpack 进行静态压缩
由于 静态压缩 涉及提前压缩文件,因此可以修改 webpack 设置以在构建步骤中压缩资产。 brotli-webpack-plugin
可以用于此目的。
首先将其作为 devDependency
添加到 package.json
中
"devDependencies": {
// ...
"brotli-webpack-plugin": "^1.1.0"
},
像任何其他 webpack 插件一样,将其导入到配置文件 webpack.config.js
中
var path = require("path");
//...
var BrotliPlugin = require('brotli-webpack-plugin');
并将其包含在 plugins 数组中
module.exports = {
// ...
plugins: [
// ...
new BrotliPlugin({
asset: '[file].br',
test: /\.(js)$/
})
]
},
插件数组使用以下参数
asset
:目标资产名称。[file]
替换为原始资产文件名。test
:与此 RegExp 匹配的所有资产(即,以.js
结尾的 JavaScript 资产)都将被处理。
例如,main.js
将被重命名为 main.js.br
。
当应用重新加载和重建时,现在将创建主捆绑包的压缩版本。打开 Glitch Console 以查看最终 public/
目录(由 Node 服务器提供)中的内容。
- 点击 Tools(工具) 按钮。
- 点击 Console(控制台) 按钮。
- 在控制台中,运行以下命令以更改为
public
目录并查看其所有文件
cd public
ls -lh

捆绑包的 brotli 压缩版本 main.bundle.js.br
现在也保存在此处,并且比 main.bundle.js
小约 76%(225 KB 对比 53 KB)。
接下来,告知服务器在请求其原始 JS 版本时发送这些 brotli 压缩的文件。这可以通过在 server.js
中定义一个新路由来完成,在文件通过 express.static
提供之前。
const express = require('express');
const app = express();
app.get('*.js', (req, res, next) => {
req.url = req.url + '.br';
res.set('Content-Encoding', 'br');
res.set('Content-Type', 'application/javascript; charset=UTF-8');
next();
});
app.use(express.static('public'));
app.get
用于告知服务器如何响应对特定端点的 GET
请求。然后使用回调函数来定义如何处理此请求。路由的工作方式如下:
- 将
'*.js'
指定为第一个参数意味着这适用于每个触发以获取 JS 文件的端点。 - 在回调中,
.br
附加到请求的 URL,并将Content-Encoding
响应标头设置为br
。 Content-Type
标头设置为application/javascript; charset=UTF-8
以指定 MIME 类型。- 最后,
next()
确保序列继续到可能存在的任何下一个回调。
由于某些浏览器可能不支持 brotli 压缩,请通过检查 Accept-Encoding
请求标头是否包含 br
来确认 brotli 是否受支持,然后再返回 brotli 压缩的文件
const express = require('express');
const app = express();
app.get('*.js', (req, res, next) => {
if (req.header('Accept-Encoding').includes('br')) {
req.url = req.url + '.br';
console.log(req.header('Accept-Encoding'));
res.set('Content-Encoding', 'br');
res.set('Content-Type', 'application/javascript; charset=UTF-8');
}
next();
});
app.use(express.static('public'));
应用重新加载后,再次查看 Network 面板。

成功!您已使用 Brotli 压缩来进一步压缩您的资产!
结论
本代码实验室说明了 brotli
如何进一步减小应用的总大小。在支持的情况下,brotli
是一种比 gzip
更强大的压缩算法。