在 Firebase 上部署 Angular 8 Universal (s-s-r) 应用程序
Posted
技术标签:
【中文标题】在 Firebase 上部署 Angular 8 Universal (s-s-r) 应用程序【英文标题】:Deploy Angular 8 Universal (s-s-r) application on Firebase 【发布时间】:2020-02-15 06:00:44 【问题描述】:我最近将 Angular 8 应用程序升级为通用应用程序 (s-s-r)。在它成为 s-s-r 应用程序之前,我已将它部署到 Firebase,但后来我发现使用常规 Firebase 托管无法在 Firebase 上部署 s-s-r 应用程序。我做了一些研究,发现我必须使用Firebase Cloud Functions。
我使用以下方法创建了一个 s-s-r 应用程序:
ng add @nguniversal/express-engine --clientProject PROJECT_NAME
PROJECT_NAME
可以在angular.json
文件下面的"projects"
部分中找到。
谁能帮我解决这个问题?
【问题讨论】:
【参考方案1】:重要提示:此解决方案取自 Udemy (here) 的 Angular 课程的问答部分。我试了一下,做了一些修改才成功。
因此,首先通过运行 npm run build:s-s-r
和 npm run serve:s-s-r
确保 s-s-r 确实有效。
然后安装 Firebase Tools 并初始化项目:
如果您之前没有安装 Firebase 命令行工具,请运行npm install -g firebase-tools
运行firebase login
,根据要求提供您的 Firebase 凭据(电子邮件/密码)。
运行firebase init
回答一些问题...
“你准备好继续了吗?”
输入y
并按回车键。
“您要设置哪些 firebase CLI 功能?”
选择...
(*) Functions
(*) Hosting
... ,使用 SPACE 键选择两者,然后按 ENTER。
“为此目录选择一个默认的 Firebase 项目?”
用箭头键选择一个,然后按 ENTER。
“您想使用哪种语言来编写 Cloud Functions?”
用箭头键选择TypeScript
,然后按回车键。
“你想使用 TSLint 吗?”
输入y
并按回车键。
“你想现在用 npm 安装依赖吗?”
输入y
并按回车键。
“你想用什么作为你的公共目录?”
输入 dist/browser
并按 ENTER 键(请注意:这与在没有 Universal 的情况下部署应用不同!)。
“配置为单页应用?”
输入y
并按回车键。
文件 index.html 已经存在。覆盖?
输入n
(重要!)并按回车键。
修改一些文件...
在 firebase.json 中将 "destination": "/index.html"
替换为 "function": "s-s-r"
(s-s-r
指向这个export const s-s-r = functions.https.onRequest(universal);
变量,你会在下面找到它)。
在 server.ts 中将 export
添加到 app
初始化:export const app = express();
而不是 const app = express();
在 server.ts 中注释掉最后三行 (app.listen(...)
) 或将它们替换为:
// If we're not in the Cloud Functions environment, spin up a Node server
if (!process.env.FUNCTION_NAME)
// Start up the Node server
app.listen(PORT, () =>
console.log(`Node Express server listening on http://localhost:$PORT`);
);
您可以在部署到 Firebase 时删除它们,但在运行 npm run serve:s-s-r
时需要它们才能在 localhost
上托管您的应用。
output
如下:
output:
// Puts the output at the root of the dist folder
path: path.join(__dirname, 'dist'),
// Export a UMD of the webpacked server.ts & dependencies for rendering in Cloud Functions
library: 'app',
libraryTarget: 'umd',
filename: '[name].js',
,
并像这样修改externals
:
externals: [
// Firebase has some troubles being webpacked when it's in the Node environment, so we will skip it.
/^firebase/
],
这将修复一个错误:
找不到模块'require("./server/main")'
在运行 npm run serve:s-s-r
或 firebase serve
命令时。
通过运行 npm run build:s-s-r
重新构建您的应用程序。
使用终端移动到functions文件夹:cd functions
安装用于文件系统访问的 npm 包:npm i fs-extra
在 functions 文件夹中创建一个名为 copy-angular-app.js 的新文件,其内容如下:
const fs = require('fs-extra');
fs.copy('../dist', './dist').then(() =>
// We should remove the original "index.html" since Firebase will use it when s-s-r is enabled (instead of calling s-s-r functions),
// and because of that, s-s-r won't work for the initial page.
fs.remove('../dist/browser/index.html').catch(e => console.error('REMOVE ERROR: ', e));
).catch(err =>
console.error('COPY ERROR: ', err)
);
此修复初始页面未作为 s-s-r 加载(而不是显示初始页面的内容,它仍显示 <app-root></app-root>
)。
注意:由于我们删除了index.html
文件,运行npm run serve:s-s-r
将无法工作,除非您首先重建您的应用程序(通过运行npm run build:s-s-r
-> 这个将重新创建index.html
文件)。
"build": "node copy-angular-app && tsc",
import * as functions from 'firebase-functions';
const universal = require(`$process.cwd()/dist/server`).app;
export const s-s-r = functions.https.onRequest(universal);
在终端确保你在functions目录下,运行npm run build
将dist
文件夹复制到functions
文件夹中。
附加说明:为了更轻松地构建 Firebase,您可以在主项目的 package.json
文件中创建一个脚本:
"build:s-s-r": "npm run build:client-and-server-bundles && npm run compile:server", // this one should already exist
"build:s-s-r-firebase": "npm run build:s-s-r && npm --prefix functions/ run build",
此脚本将首先构建您的 Angular s-s-r 应用程序 (npm run build:s-s-r
),然后它将在您的 functions 文件夹中运行 npm run build
(这样它会将项目的 dist
文件夹复制到您的functions dist
文件夹,并将删除项目的 index.html
文件)。
部署您的应用...
您可以在部署之前在本地为您的应用提供服务,在 localhost:5000 上运行 firebase serve
(如果需要)。
停止服务器(Ctrl + C)。
然后你可以通过运行firebase deploy
来部署应用程序,并通过终端显示的url访问它。
通过这种方式,我设法在 Firebase 上部署了我的 Angular s-s-r 应用。
希望这会有所帮助...
【讨论】:
冒险真是太有趣了。谢谢!! Firebase 部署完成后。动态生成的元标记和备用链接不会反映在 firebase 链接上。但它在 firebase 服务中工作 这会覆盖/删除我现有的 firebase 函数吗? 这只会在部署后为您的特定项目创建/更新名为 s-s-r 的函数。它不会触及您在其他项目中定义的功能。 Max 的精彩课程,@miselking 我们已经完成了同样的自学 :)【参考方案2】:@miselking 的回答基本上很棒,我只想补充一点,Angular
现在是(Angular 9
及更高版本)使用 CLI Builders 构建和服务 s-s-r 应用程序,因此在我的如果从Angular 8
升级后它甚至根本不起作用。问题#16348 解释了现在如何管理外部依赖项(如果需要添加)。在angular.json
现在您可以添加externalDependencies
,这是webpack
与externals
/nodeExternals
相关的自定义配置的替代品。
除此之外,@miselking 的答案仍然是最新的。
【讨论】:
【参考方案3】:Angular Firebase 刚刚发布了 new simple way 以使用 ng deploy 进行部署!我认为他们仍在解决这些错误......
【讨论】:
以上是关于在 Firebase 上部署 Angular 8 Universal (s-s-r) 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
Angular 8,Firebase 推送通知:无法在推送通知上获取调试器或自定义逻辑
在 Firebase 上重新加载 Angular 页面时找不到页面