Angular 17 SSR结合Firebase Cloud Functions运行报错求助
Angular 17构建后生成了新格式的文件,此前Angular版本构建输出为index.js。原本使用如下Firebase Cloud Functions代码调用服务端文件:
const {onRequest} = require("firebase-functions/v2/https"); const logger = require("firebase-functions/logger"); const mainjsfile= require(__dirname+"/server/main"); exports.ngssr=onRequest(mainjsfile.app());
但现在因Angular 17输出为mjs文件,调用时出现错误:
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/nl/Desktop/program/ui/ssrproject/ui/dist/functions2/lib/server/server.mjs not supported.
Instead change the require of /Users/nl/Desktop/program/ui/ssrproject/ui/dist/functions2/lib/server/server.mjs to a dynamic import() which is available in all CommonJS modules.
at Object. (/Users/n****l/Desktop/program/ui/ssrproject/ui/dist/functions2/lib/index.js:16:19) {
code: 'ERR_REQUIRE_ESM'
}
如何在Angular 17应用中通过Cloud Functions调用服务端的mjs文件以解决该问题?
方法1:用动态import()加载ESM模块
你的Cloud Functions代码是CommonJS格式(依赖require),无法直接加载Angular 17输出的ESM模块(.mjs),改用动态import即可适配。调整代码如下:
const { onRequest } = require("firebase-functions/v2/https"); const logger = require("firebase-functions/logger"); exports.ngssr = onRequest(async (req, res) => { try { // 动态加载ESM模块,路径需对应实际生成的mjs文件位置 const serverModule = await import(__dirname + "/server/server.mjs"); const app = serverModule.app(); app(req, res); } catch (error) { logger.error("加载ESM模块失败", error); res.status(500).send("服务器内部错误"); } });
注意:动态import是异步操作,需将onRequest的处理函数改为async,用await等待模块加载完成,同时确认路径指向正确的.mjs文件。
方法2:将Cloud Functions转为ESM格式
如果希望统一使用ESM规范,可修改Cloud Functions的配置和代码:
- 在functions目录的package.json中添加:
"type": "module"
- 将require语法替换为import:
import { onRequest } from "firebase-functions/v2/https"; import logger from "firebase-functions/logger"; import { app } from "./server/server.mjs"; export const ngssr = onRequest(app());
- 若入口文件是index.js,设置"type": "module"后,.js文件会被当作ESM处理,无需改名。
方法3:调整Angular构建输出格式(可选)
如果不想修改Cloud Functions代码,可让Angular 17输出CommonJS格式文件:
在angular.json的server构建配置中,添加outputFormat参数:
"architect": { "server": { "builder": "@angular-devkit/build-angular:server", "options": { "outputPath": "dist/server", "main": "server.ts", "tsConfig": "tsconfig.server.json", "outputFormat": "commonjs" } } }
重新构建后,Angular会输出CommonJS格式文件,即可继续用原来的require方式加载。
内容的提问来源于stack exchange,提问作者Narender Paul

