AWS Lambda+Serverless部署Vuetify:自定义字体无法渲染问题排查
问题根源
Lambda搭配API Gateway部署时,若未正确配置二进制文件处理规则,会把字体这类二进制文件当成UTF-8文本传输,导致文件字节被错误转码。最终浏览器收到的字体文件已损坏,出现OTS parsing error: Size of decompressed WOFF 2.0 is less than compressed size这类解码错误。而S3默认支持二进制文件直接传输,只要Content-Type设置正确就不会出现转码问题,这就是S3能正常渲染图标的原因。
解决方案
1. 配置API Gateway支持二进制媒体类型
在Serverless Framework的配置文件serverless.yml中,添加API Gateway的二进制类型声明,覆盖字体文件对应的MIME类型:
provider: name: aws runtime: nodejs18.x apiGateway: binaryMediaTypes: - 'application/font-woff' - 'application/font-woff2' - 'font/woff' - 'font/woff2' - 'binary/octet-stream'
配置完成后,重新执行serverless deploy使设置生效。
2. 确保Express正确返回二进制文件及响应头
使用express.static托管静态文件时,手动指定字体文件的Content-Type,避免Express自动推断错误:
const express = require('express'); const serverless = require('serverless-http'); const path = require('path'); const app = express(); // 托管dist目录,为字体文件设置正确响应头 app.use(express.static(path.join(__dirname, 'dist'), { setHeaders: (res, filePath) => { if (filePath.endsWith('.woff') || filePath.endsWith('.woff2')) { res.setHeader('Content-Type', filePath.endsWith('.woff2') ? 'application/font-woff2' : 'application/font-woff'); res.setHeader('Cache-Control', 'public, max-age=31536000'); // 可选,添加缓存策略 } } })); // 处理SPA路由,返回index.html app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'dist', 'index.html')); }); module.exports.handler = serverless(app);
注意不要用res.send()返回二进制文件,优先用res.sendFile()或res.end(Buffer),确保二进制数据不被转成字符串。
3. 验证构建产物完整性
确认Vuetify的字体文件(materialdesignicons.woff等)在dist目录中完整,构建工具(如Webpack、Vue CLI)没有对字体文件进行错误压缩或转码。可以直接对比本地dist中的字体文件和部署后下载的文件大小,若大小不一致则说明传输过程中被损坏。
4. 检查API Gateway部署状态
配置二进制媒体类型后,必须重新部署API Gateway才能生效。如果通过Serverless Framework部署,执行serverless deploy即可;如果手动在AWS控制台配置,需点击API Gateway的「部署」按钮更新生效。
内容的提问来源于stack exchange,提问作者Jeff Headley

