压缩前
压缩后
// 文件 /mixin/nitro-hooks.ts
import { Readable, pipeline } from 'node:stream';
import zlib from 'node:zlib';
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('beforeResponse', async (event, response) => {
compressResponse(event, response);
});
})
async function compressResponse(event: any, response: { body?: unknown }) {
if (typeof response.body !== 'string') {
return;
}
const acceptableEncoding =
getRequestHeader(event, 'accept-encoding') ?? 'deflate';
if (
!acceptableEncoding ||
!/\b(deflate|gzip|br)\b/.test(acceptableEncoding)
) {
return;
}
const originalBody = response.body;
const stream = Readable.from(response.body);
if (/\bbr\b/.test(acceptableEncoding)) {
setResponseHeader(event, 'Content-Encoding', 'br');
response.body = pipeline(
stream,
zlib.createBrotliCompress(),
event.node.res,
() => (response.body = originalBody)
);
} else if (/\bgzip\b/.test(acceptableEncoding)) {
setResponseHeader(event, 'Content-Encoding', 'gzip');
response.body = pipeline(
stream,
zlib.createGzip(),
event.node.res,
() => (response.body = originalBody)
);
} else {
setResponseHeader(event, 'Content-Encoding', 'deflate');
response.body = pipeline(
stream,
zlib.createDeflate(),
event.node.res,
() => (response.body = originalBody)
);
}
}
// 文件 nuxt.coonfig.ts
export default defineNuxtConfig({
// ......
nitro: {
compressPublicAssets: true,
plugins: [
'~/mixin/nitro-hooks.ts',
]
},
// ....其他配置
})