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

时间:2019-10-18 09:04:13

标签: angular firebase google-cloud-functions angular-universal

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

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

interface SmallOrder {
  common: string,
  prop1: string
}

interface MediumOrder {
  common: string,
  prop2: string
}

interface LargeOrder {
  common: string,
  prop3: string
}

interface XLargeOrder {
  prop4: number
}

type Order = SmallOrder | MediumOrder | LargeOrder | XLargeOrder;

type Res = Order[]

type Country = 'US' | 'International'

type OrderExt = Order & { country: Country }

const myOrders: Order[] = [
  { common: 'one', prop1: "small" },
  { common: 'two', prop2: "medium" },
  { common: 'three', prop3: "large" },
  { common: 'four', prop1: "smaller" }
]

const myExtOrders: OrderExt[] = myOrders.map(o => ({
  ...o,
  country: 'US'
}))

myExtOrders.map(o => {
  if (o.common) {
    o.common.trim()
  }
})

ng add @nguniversal/express-engine --clientProject PROJECT_NAME 可在PROJECT_NAME部分下方的angular.json文件中找到。

有人可以帮我吗?

3 个答案:

答案 0 :(得分:6)

重要提示:此解决方案摘自Udemy(here)Angular课程的“问答”部分。我尝试了一下,并进行了一些修改使其得以正常工作。


因此,首先通过运行npm run build:ssrnpm run serve:ssr确保SSR确实有效。

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

  • 如果您之前尚未安装Firebase命令行工具,请运行npm install -g firebase-tools
  • 运行firebase login,如果需要,提供您的Firebase凭据(电子邮件/密码)。
  • 运行firebase init

回答一些问题...

  • “您准备好继续吗?”

    键入y,然后按Enter。

  • “您要设置哪些Firebase CLI功能?”

    选择...

    (*) Functions
    
    (*) Hosting
    

    ...,同时使用SPACE键选择它们,然后按Enter。

  • “为此目录选择默认的Firebase项目吗?”

    使用箭头键选择一个,然后按Enter。

  • “您想使用哪种语言编写Cloud Functions?”

    使用箭头键选择TypeScript,然后按Enter。

  • “您要使用TSLint吗?”

    键入y,然后按Enter。

  • “您是否要立即使用npm安装依赖项?”

    键入y,然后按Enter。

  • “您要将什么用作公用目录?”

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

  • “要配置为单页应用吗?”

    键入y,然后按Enter。

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

    键入n(重要!),然后按Enter。

修改一些文件...

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

    ({ssr指向此export const ssr = 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: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/
    ],

这将修复一个错误:

  

找不到模块'require(“ ./ server / main”)'

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

  • 通过运行npm run build:ssr重建应用。

  • 使用终端移至功能文件夹: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 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文件,因此除非您首先重建应用程序(通过运行{{ 1}}->这将重新创建npm run serve:ssr文件)。

  • functions / package.json 中(不在项目的package.json中!)更改构建条目,如下所示:

npm run build:ssr

  • functions / src / index.ts 中,用以下内容替换内容:
index.html
  • 在终端中,确保您位于 functions 目录中,然后运行"build": "node copy-angular-app && tsc", import * as functions from 'firebase-functions'; const universal = require(`${process.cwd()}/dist/server`).app; export const ssr = functions.https.onRequest(universal); 文件夹复制到npm run build文件夹中。 / li>

附加说明: 为了简化Firebase的构建,您可以在主项目的dist文件中创建脚本:

functions

此脚本将首先构建您的Angular SSR应用程序(package.json),然后将在您的 functions 文件夹中运行 "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", (这样它将复制项目的{{ 1}}文件夹到您的功能 npm run build:ssr文件夹中,将删除项目的npm run build文件)。

部署您的应用...

  • 您可以在部署之前通过运行dist(如果需要)在 localhost:5000 上为本地应用提供服务。

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

  • 然后,您可以通过运行dist来部署应用程序,并通过终端中显示的URL对其进行访问。

通过这种方式,我设法在Firebase上部署了Angular SSR应用。

希望这对您有帮助...

答案 1 :(得分:2)

@miselking的基本解答,我只是想补充一下,Angular现在(Angular 9及更高版本)使用CLI构建器来构建和提供SSR应用程序,因此webpack.server.config.js是从Angular 8升级后,它甚至根本无法使用。问题#16348解释了如何在需要添加外部依赖项的情况下进行管理。现在,您可以在angular.json中添加externalDependencies,这就是webpackexternals / nodeExternals相关的自定义配置的替代方式。

除此之外,@ miselking的答案仍是最新的。

答案 2 :(得分:1)

Angular Firebase刚发布了new simple way,可以通过 ng deploy 进行部署!我认为他们仍然在解决错误……