如何让 Angular Universal 为 Firebase Cloud Functions 编译 Typescript

Posted

技术标签:

【中文标题】如何让 Angular Universal 为 Firebase Cloud Functions 编译 Typescript【英文标题】:How can I get Angular Universal to Compile Typescript for Firebase Cloud Functions 【发布时间】:2018-12-03 14:30:21 【问题描述】:

我正在尝试将 Angular Universal 添加到我的 Angular Firebase 应用程序中。我一直在关注这个video。但需要进行一些更改才能使其与云功能一起使用。

我在 angular-cli.config 中的“apps”数组中添加了一个额外的配置块

// .angular-cli.config.json - "apps" [

      "platform": "server",
      "root": "src",
      "outDir": "dist/server",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main.server.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.server.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "serviceWorker": false,
      "styles": [
        "styles/styles.scss"
      ],
      "scripts": [],
      "environmentSource": "environments/environment.ts",
      "environments": 
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      

接下来我还添加了一个名为 tsconfig.server.json 的附加文件


  "extends": "../tsconfig.json",
  "compilerOptions": 
    "outDir": "../out-tsc/app",
    "baseUrl": "./",
    "module": "commonjs",
    "types": []
  ,
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ],
  "angularCompilerOptions": 
    "entryModule": "app/app.server.module#AppServerModule"
  

然后我创建了一个额外的 app.server.module.ts

import  NgModule  from '@angular/core';
import  AppModule  from './app.module';
import  ServerModule, ServerTransferStateModule  from '@angular/platform-server';
import  ModuleMapLoaderModule  from '@nguniversal/module-map-ngfactory-loader';

@NgModule(
  imports: [
    AppModule,
    ServerModule,
    ServerTransferStateModule, //  <-- needed for state transfer
    ModuleMapLoaderModule // <-- needed for lazy-loaded routes,
  ],
  declarations: []
)
export class AppServerModule 

与上面的视频一样,代码被转换为浏览器应用程序和服务器应用程序的 dist 文件夹。虽然我已经决定避免使用 webpack 来创建 server.js 文件,而是决定将它作为 typescript 直接添加到我的云函数中。

ng build --prod && ng build --prod --app 1 --output-hashing=false

创造..

  dist/browser
  dist/server

我已将代码移至 cloud functions.js,而不是 server.js。但是,从 dist/server/main.bundle.js 导入我的服务器包会导致 firebase 部署过程出错。

// cloud functions code above...

// Causes Error: -> const  AppServerModuleNgFactory, LAZY_MODULE_MAP  = require('./../../dist/server/main.bundle');

// more cloud functions code below..

我收到的错误是:

i  functions: preparing functions directory for uploading...

Error: Error occurred while parsing your function triggers.
project_root/node_modules/angular2-markdown/markdown/markdown.component.js:1
(function (exports, require, module, __filename, __dirname)  import  Component, ElementRef, Input  from '@angular/core';
我相信我的云功能只使用节点 6。

dist/server/main.bundle.js 需要使用 es6 导入语法的 node_module。

dist/server/main.bundle.js -> require("angular2-markdown.. -> markdown.component.js:1 -> import

我已经尝试过要求函数 tsconfig.json 将输出带到 es5,但我认为它不能将 node_module .js 依赖项操作为较低的 js。 (node_modules比functions文件夹中的node_modules高1个文件夹-(dist文件夹也比functions文件夹高1级)

函数/tsconfig.json


  "compileOnSave": false,
  "compilerOptions": 
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5", // <--- Trying to es5 the output
    "typeRoots": [
      "node_modules/@types",
      "src/types-overwrite"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  

是否可以获取 firebase 云功能来升级节点版本以使用类似 Node 10.5 的导入语法? 如果没有,我可以编辑我的 tsconfig 以将所有内容转换为 es5 吗?

更新:

我创建了一个示例 github 项目来下载和测试功能部署。

链接:https://github.com/Jonathan002/firebase-cloud-functions-node-6-import-statement-broken/blob/master/README.md

我还尝试将所有内容捆绑为 webpack_require 以将 node_modules 转译为与捆绑包内联,而不是使用 webpack 要求,但得到了错误:

TypeError: o.initStandalone 不是函数

我相信它来自被依赖的 firebase node_module,但我无法确认这一点。 (此错误仅出现在我正在处理的我自己的项目中,并且很难确定在示例项目中确切包含什么 node_module 以使用 webpack 获得相同的错误结果)。

下面显示的是我在函数中使用的 webpack 配置:

var path = require('path');

module.exports = 
  entry: './src/index.ts',
  target: 'node',
  output: 
    filename: 'index.js',
    path: path.resolve(__dirname, 'lib')
  ,
  mode: 'none',
  devtool: 'source-map',
  plugins: [],
  resolve: 
    extensions: ['.ts', '.tsx', '.js', '.json']
  ,
  module: 
    rules: [
       test: /\.tsx?$/, loader: 'ts-loader' ,
    ]
  ,
;

在函数文件夹中,您可以使用以下方式生成捆绑代码:

webpack --config webpack.config.js --colors --progress

并在 firebase.json 中使用 firebase 的 typescript 函数删除预部署代码:


  "functions": 
    "predeploy": [
      // remove this..
      // -> "npm --prefix \"$RESOURCE_DIR\" run lint",
      // -> "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  

【问题讨论】:

【参考方案1】:

使用 firbase 工具时,您可以在初始化期间创建函数/索引文件的 ts 版本。

$ npm install -g firebase-tools

$ firebase init

在设置选项中,为函数目录选择 ts 选项而不是 js。

【讨论】:

以上是关于如何让 Angular Universal 为 Firebase Cloud Functions 编译 Typescript的主要内容,如果未能解决你的问题,请参考以下文章

Angular Universal - 部署到 AWS Elastic Beanstalk

如何在 Angular 4 Universal 中发出 http post 请求?

Angular 2 Universal - 使用手写笔和 pug 模板的服务器端渲染

当网站上的文档过时时如何安装 Angular2 Universal?

将 Angular 2/3/4/5/6 项目转换为 Angular Universal

如何正确启动 Angular Universal 到实时服务器