在 Firebase 上部署 Angular 8 个通用 (SSR) 应用程序

Deploy Angular 8 Universal (SSR) application on Firebase

我最近将我的 Angular 8 应用程序升级为通用应用程序 (SSR)。在它成为 SSR 应用程序之前,我已将其部署到 Firebase,但后来我发现使用常规 Firebase 托管无法在 Firebase 上部署 SSR 应用程序。我做了一些研究,发现我必须使用 Firebase Cloud Functions.

我使用以下方法创建了一个 SSR 应用程序:

ng add @nguniversal/express-engine --clientProject PROJECT_NAME

PROJECT_NAME 可以在 angular.json 文件的 "projects" 部分下面找到。

谁能帮我解决这个问题?

重要说明:此解决方案摘自 Udemy (here) 的 Angular 课程的问答部分。我试了一下,经过一些修改后成功了。


所以,首先要确保 SSR 在 运行ning npm run build:ssrnpm run serve:ssr 确实有效。

然后安装Firebase Tools并初始化项目:

  • 如果您之前没有安装 Firebase 命令行工具,运行 npm install -g firebase-tools
  • 运行 firebase login,如果需要,请提供您的 Firebase 凭据 (email/password)。
  • 运行firebase init

回答一些问题...

  • "Are you ready to proceed?"

    键入 y 并按 ENTER。

  • "Which firebase CLI features do you want to setup?"

    选择...

    (*) Functions
    
    (*) Hosting
    

    ... ,使用 SPACE 键选择两者,然后按 ENTER。

  • "Select a default Firebase project for this directory?"

    Select 使用箭头键并按 ENTER。

  • "What language would you like to use to write Cloud Functions?"

    Select TypeScript 使用箭头键并按 ENTER。

  • "Do you want to use TSLint?"

    键入 y 并按 ENTER。

  • "Do you want to install dependencies with npm now?"

    键入 y 并按 ENTER。

  • "What do you want to use as your public directory?"

    键入 dist/browser 并按 ENTER(请注意:这与部署没有 Universal 的应用程序不同!)。

  • "Configure as a single page app?"

    键入 y 并按 ENTER。

  • 文件 index.html 已经存在。覆盖?

    键入 n(重要!)并按 ENTER。

修改部分文件...

  • firebase.json中将"destination": "/index.html"替换为"function": "ssr"

    (ssr指向这个export const ssr = functions.https.onRequest(universal);变量,你会在下面找到它)。

  • server.ts中添加exportapp初始化: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:ssr 时需要它们以便能够在 localhost.

上托管您的应用程序
  • webpack.server.config.js中修改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/
    ],

这将修复一个错误:

Cannot find module 'require("./server/main")'

当运行宁npm run serve:ssrfirebase serve命令时。

  • 通过 运行ning npm run build:ssr 重建您的应用程序。

  • 使用终端移动到函数文件夹:cd functions

  • 安装用于文件系统访问的 npm 包:npm i fs-extra

  • functions 文件夹中创建一个名为 copy-angular-app.js[=215 的新文件=],内容为:

    const fs = require('fs-extra');
    fs.copy('../dist', './dist').then(() => {
        // We should remove the original "index.html" since Firebase will use it when SSR is enabled (instead of calling SSR functions),
        // and because of that, SSR 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)
    });

修复了 初始页面未加载为 SSR(而不是显示初始页面的内容,它仍然显示 <app-root></app-root>)。

注:由于我们删除了index.html文件,运行宁npm run serve:ssr不会'除非您首先重建您的应用程序(通过 运行ning npm run build:ssr -> 这将重新创建 index.html 文件,否则无法正常工作。

  • functions/package.json(不在项目的package.json!)中,像这样更改构建条目:

"build": "node copy-angular-app && tsc",

  • functions/src/index.ts中将内容替换为:
    import * as functions from 'firebase-functions';

    const universal = require(`${process.cwd()}/dist/server`).app;
    export const ssr = functions.https.onRequest(universal);
  • 在终端中确保您在 functions 目录中,并且 运行 npm run builddist 文件夹复制到functions 文件夹。

附加说明: 为了更轻松地构建 Firebase,您可以在主项目的 package.json 文件中创建一个脚本:

    "build:ssr": "npm run build:client-and-server-bundles && npm run compile:server", // this one should already exist
    "build:ssr-firebase": "npm run build:ssr && npm --prefix functions/ run build",

此脚本将首先构建您的 Angular SSR 应用程序 (npm run build:ssr),然后它会 运行 npm run build 在您的 函数中 文件夹(这样它会将项目的 dist 文件夹复制到您的 functions dist 文件夹并删除项目的 index.html 文件)。

部署您的应用程序...

  • 您可以在部署前通过 运行ning firebase servelocalhost:5000 上本地提供您的应用程序(如果您想要).

  • 停止服务器(Ctrl + C)。

  • 然后就可以通过运行ning firebase deploy部署应用,通过终端显示的url访问

通过这种方式,我成功地在 Firebase 上部署了我的 Angular SSR 应用程序。

希望这对您有所帮助...

Angular Firebase 刚刚推出 new simple way 以使用 ng deploy 部署它!我认为他们仍在解决错误...

@miselking 的回答基本上很棒,我只想补充一点 Angular 现在是(Angular 9 及以上)使用 CLI Builders 来构建和提供 SSR 应用程序,因此 webpack.server.config.js 不再需要,在我的情况下,从 Angular 8 升级后它甚至根本不起作用。如果需要添加,问题 #16348 解释了现在如何管理外部依赖项的方式。在 angular.json 中,现在您可以添加 externalDependencies,这是 webpackexternals/nodeExternals.

相关的自定义配置的替代品

除此之外,@miselking 的回答仍然是up-to-date。