实战:使用 Angular Universal 与 Express 构建 Firebase 应用)
后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载导读本文基于 AngularFire 官方指南讲解如何将 Angular Firebase 应用接入 Angular Universal实现服务端渲染SSR与预渲染Prerendering。你将掌握从生成 Universal 服务模块、编写 Express 服务器、配置 Webpack 打包到落地构建脚本的完整流程并了解当前仓库 sample 项目中现代 Angular AngularFire SSR 的演进写法最终让搜索引擎爬虫与链接机器人稳定、可靠地索引页面内容。什么是服务端渲染SSR服务端渲染Server-Side RenderingSSR是在请求到达时将 JavaScript 应用转换为纯 HTML 的过程。与纯客户端渲染不同SSR 让搜索引擎爬虫和链接机器人linkbot能够不依赖浏览器执行 JavaScript 即可可靠地理解页面内容这是 SEO 与社交分享链接预览的关键前提。在 AngularFire 语境下SSR 的典型应用场景包括需要被搜索引擎稳定索引的内容型应用博客、文档站、电商列表页需要快速首屏内容的低性能设备或弱网环境将渲染入口托管到 Firebase Hosting / Cloud Functions 的云端部署方案。关联文档site/src/universal/getting-started.md 是本篇的官方基础配套的预渲染与云端部署方案见 site/src/universal/prerendering.md 与 site/src/universal/cloud-functions.md。前置条件开始前请确认环境满足以下版本要求依赖版本要求angular/cli v6.0angular/fire v5.0.0Angular CLI 用于生成 Universal 服务模块与执行构建angular/fire提供 Firebase 与 Angular 的集成层。当前仓库的 sample 示例项目已使用 Angular 21 AngularFire 21 的现代技术栈见 sample/package.json但本文的 Express 手动接入方案与旧版流程依然适用于需要自定义服务器控制权的场景。生成 Angular Universal 服务模块首先用 Angular CLI 生成服务端模块。在项目根目录执行ng generate universal --client-project your-project其中your-project替换为angular.json中定义的客户端项目名称。该命令会为项目添加server.ts入口与AppServerModule相关骨架后续步骤将在此基础之上编写自定义 Express 服务器。使用 ExpressJS 构建服务器ExpressJS 是一个轻量级 Web 框架能够在 Node 环境中处理 HTTP 请求充当 Angular Universal 的渲染宿主。官方流程使用nguniversal/express-engine等包接入先安装开发依赖npm install --save-dev nguniversal/express-engine nguniversal/module-map-ngfactory-loader express webpack-cli ts-loader ws xhr2各依赖的作用nguniversal/express-engine将 Angular Universal 渲染绑定到 Express 模板引擎nguniversal/module-map-ngfactory-loader为懒加载路由提供模块工厂映射expressHTTP 服务器框架webpack-cli与ts-loader把server.ts及其依赖打包为 Node 可执行文件ws与xhr2Node 环境下 Firebase SDK 正常工作所需的 WebSocket 与 XMLHttpRequest 补齐实现polyfill。然后在项目根目录创建server.ts// These are important and needed before anything else import zone.js/dist/zone-node; import reflect-metadata; import { enableProdMode } from angular/core; import { ngExpressEngine } from nguniversal/express-engine; import { provideModuleMap } from nguniversal/module-map-ngfactory-loader; import * as express from express; import { join } from path; import { readFileSync } from fs; // Polyfills required for Firebase (global as any).WebSocket require(ws); (global as any).XMLHttpRequest require(xhr2); // Faster renders in prod mode enableProdMode(); // Export our express server export const app express(); const DIST_FOLDER join(process.cwd(), dist); const APP_NAME YOUR_PROJECT_NAME; // TODO: replace me! const { AppServerModuleNgFactory, LAZY_MODULE_MAP } require(./dist/${APP_NAME}-server/main); // index.html template const template readFileSync(join(DIST_FOLDER, APP_NAME, index.html)).toString(); app.engine(html, ngExpressEngine({ bootstrap: AppServerModuleNgFactory, providers: [ provideModuleMap(LAZY_MODULE_MAP) ] })); app.set(view engine, html); app.set(views, join(DIST_FOLDER, APP_NAME)); // Serve static files app.get(*.*, express.static(join(DIST_FOLDER, APP_NAME))); // All regular routes use the Universal engine app.get(*, (req, res) { res.render(join(DIST_FOLDER, APP_NAME, index.html), { req }); }); // If were not in the Cloud Functions environment, spin up a Node server if (!process.env.FUNCTION_NAME) { const PORT process.env.PORT || 4000; app.listen(PORT, () { console.log(Node server listening on http://localhost:${PORT}); }); }关键点拆解导入顺序不可颠倒zone.js/dist/zone-node与reflect-metadata必须在任何其他代码之前导入这是 Angular Universal 在 Node 环境正常启动的硬性要求Firebase 的 Node 补齐ws与xhr2挂到global上保证 Firebase SDK 在 Node 中可用。这也是官方 Webpack 配置将firebase相关依赖标记为 externals 的原因之一见下文enableProdMode()跳过开发模式的变更检测开销加快渲染速度懒加载模块映射LAZY_MODULE_MAP由module-map-ngfactory-loader在编译期生成配合provideModuleMap注入确保懒加载路由在服务端渲染时也被正确解析静态资源与路由分流app.get(*.*, ...)优先以静态文件方式响应带扩展名的请求其余请求全部交给 Universal 引擎渲染Cloud Functions 兼容通过process.env.FUNCTION_NAME判断是否运行在 Firebase Functions 环境中——若在云函数环境中则不启动独立监听端口而由云函数入口调用导出的app。这正是 site/src/universal/cloud-functions.md 中functions.onRequest包装require(...server).app的原理基础。值得说明的是随着版本演进当前仓库 sample 项目已采用更现代的angular/ssr方案基于AngularNodeAppEngine处理请求、通过initializeServerApp注入认证令牌见 sample/src/server.ts、sample/src/app/app.config.server.ts。传统nguniversal/express-engine手动方案仍然有效且对希望完全掌控 Express 中间件与部署形态的团队更具参考价值。添加 Express 服务器的 Webpack 配置创建webpack.server.config.js将上一步的server.ts及其依赖打包成 Node 可运行产物const path require(path); const webpack require(webpack); const APP_NAME YOUR_PROJECT_NAME; // TODO: replace me! module.exports { entry: { server: ./server.ts }, resolve: { extensions: [.js, .ts] }, mode: development, target: node, externals: [ /* Firebase has some troubles being webpacked when in in the Node environment, lets skip it. Note: you may need to exclude other dependencies depending on your project. */ /^firebase/ ], output: { // Export a UMD of the webpacked server.ts deps, for // rendering in Cloud Functions path: path.join(__dirname, dist/${APP_NAME}-webpack), library: app, libraryTarget: umd, filename: [name].js }, module: { rules: [ { test: /\.ts$/, loader: ts-loader } ] }, plugins: [ new webpack.ContextReplacementPlugin( /(.)?angular(\\|\/)core(.)?/, path.join(__dirname, src), // location of your src {} // a map of your routes ), new webpack.ContextReplacementPlugin( /(.)?express(\\|\/)(.)?/, path.join(__dirname, src), {} ) ] }配置要点target: node产物面向 Node 运行环境externals: [/^firebase/]Firebase SDK 在 Node 环境下直接 require 原生模块往往比打进 bundle 更稳定因此跳过打包。若你的项目还依赖其他在 Node 下有原生实现的库可仿照此正则追加排除项UMD 输出是关键设计libraryTarget: umd与library: app使产物同时暴露为dist/APP_NAME-webpack/server.js这正是 Cloud Functions 中require(.../server).app能够取到 Express 实例的前提ContextReplacementPlugin分别处理 Angular core 与 Express 的动态上下文避免打包时出现歧义模块解析。配置构建脚本更新package.json把YOUR_PROJECT_NAME替换为真实项目名scripts: { // ... omitted build: ng build npm run build:ssr, build:ssr: ng run YOUR_PROJECT_NAME:server npm run webpack:ssr, webpack:ssr: webpack --config webpack.server.config.js, serve:ssr: node dist/YOUR_PROJECT_NAME-webpack/server.js },脚本链路说明ng build构建客户端产物到dist/APP_NAME/ng run YOUR_PROJECT_NAME:server通过 Angular CLI 的servertarget 生成服务端模块工厂AppServerModuleNgFactory到dist/APP_NAME-server/mainwebpack --config webpack.server.config.js将server.ts打包为dist/APP_NAME-webpack/server.jsnode dist/YOUR_PROJECT_NAME-webpack/server.js直接以 Node 启动渲染服务器。完成配置后本地验证npm run build npm run serve:ssr启动成功后访问http://localhost:4000页面 HTML 应包含服务端渲染出的完整内容可通过浏览器查看源代码验证。结合仓库源码的现代演进参考当前仓库的 sample 示例项目sample/展示了 Angular 21 AngularFire 21 下 SSR 的最新实践可作为对比参考服务端入口sample/src/server.ts使用angular/ssr/node的AngularNodeAppEngine取代旧式ngExpressEngine并将express.static的静态资源maxAge设为1y通过cookieParser解析__sessionCookie 后注入请求上下文服务端应用配置sample/src/app/app.config.server.ts通过provideServerRendering(withRoutes(serverRoutes))启用 SSR 路由并调用initializeServerApp(environment.firebase, { authIdToken })将请求携带的认证令牌透传给 Firebase Admin SDK实现携带用户身份的 SSR——这是传统方案中需要自行处理的鉴权关键点客户端应用配置sample/src/app/app.config.ts配合provideClientHydration(withIncrementalHydration())实现客户端水合同时支持在 Emulator 端口可用时自动连接 Auth 模拟器保证本地开发与云端行为一致。对比可见旧版流程本文主体胜在完全透明的自定义能力而现代流程则由框架接管渲染管线、减少样板代码。两者共通的底层诉求一致——让 HTML 在请求期生成、让 Firebase 在 Node 环境可用。下一步预渲染与云端部署SSR 之外AngularFire 还支持**预渲染Prerendering**与Cloud Functions 部署两条进阶路径官方配套文档分别为site/src/universal/prerendering.md通过static.paths.js列出待渲染路由借助renderModuleFactory在构建期一次性生成静态 HTML 到public/目录适合高频访问页面的性能与成本优化site/src/universal/cloud-functions.md通过firebase init配置functionshosting在firebase.json的hosting.rewrites中写入{ source: **, function: universal }将全部请求代理到 Cloud Functions 中的 Express 实例实现按需渲染与自动扩缩容。两篇文档均以本文的server.ts与 Webpack 配置为前置基础阅读顺序建议为Getting Started本文→ Prerendering → Cloud Functions。小结本文完整复现了 AngularFire 官方 SSR 接入流程前置版本要求、Universal 模块生成、Express 服务器编写含 Firebase 的 Node polyfill、懒加载模块映射与 Cloud Functions 兼容分支、Webpack 打包含 UMD 导出与 firebase externals以及一键构建脚本。配合仓库中的 sample 现代实现对照你可以根据项目对自定义控制权与开发效率的权衡选择适合自己的 SSR 落地路径。赞分享后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载相关推荐KeyDB 内置的 C StatsD 客户端cpp-statsd-client头文件式埋点、批处理与采样机制全解析KeyDB 内置的 C StatsD 客户端cpp statsd client头文件式埋点、批处理与采样机制全解析 导读 本文以 KeyDB 仓库 d后端AngularFire 实战在 Firebase Cloud Functions 上部署 Angular UniversalSSR应用AngularFire 实战在 Firebase Cloud Functions 上部署 Angular UniversalSSR应用 Angular U后端gpui-kit NumberInput 数值输入组件完全指南增减步进、范围约束与数字格式化gpui kit NumberInput 数值输入组件完全指南增减步进、范围约束与数字格式化 NumberInput 是 gpui kit 中面向数值输入场景后端上一篇antlr4ts高级技巧使用Listener和Visitor模式处理复杂语法树下一篇PollyJS 适配器Adapter完全指南pollyjs/adapter 基础类的生命周期、Hook 体系与 API 演进史创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考