Angular Universal 不适用于 Angular Google 地图

Posted

技术标签:

【中文标题】Angular Universal 不适用于 Angular Google 地图【英文标题】:Angular Universal does not work with Angular Google Maps 【发布时间】:2019-08-26 07:35:28 【问题描述】:

技术:Angular Cli、Angular 7、Angular Google Maps、Firebase Functions。

问题:我正在尝试为我的 Angular 通用应用程序提供服务,但在构建时遇到 Angular 谷歌地图错误。

错误我得到:

/Users/test/Public/Leisure/leisure-app/functions/node_modules/@agm/core/services/managers/info-window-manager.js:1
(function (exports, require, module, __filename, __dirname)  import 
Observable  from 'rxjs';
                                                              ^^^^^^

SyntaxError: Unexpected token import
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)

似乎 Angular Universal 不喜欢第三方库。

我关注的资源: https://hackernoon.com/deploying-angular-universal-v6-with-firebase-c86381ddd445

我的应用模块:

import  AgmCoreModule  from '@agm/core';
import  AngularFireAuthModule  from '@angular/fire/auth';
import  AngularFireDatabase  from '@angular/fire/database';
import  AngularFireModule  from '@angular/fire';
import  ServiceWorkerModule  from '@angular/service-worker';
import  AngularFireStorageModule  from '@angular/fire/storage';
import  AngularFirestoreModule  from '@angular/fire/firestore';
import  BrowserModule  from '@angular/platform-browser';
import  CommonModule  from '@angular/common';
import  GooglePlaceModule  from 'ngx-google-places-autocomplete';
import  HTTP_INTERCEPTORS, HttpClientModule  from '@angular/common/http';
import  NgModule, NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA  from '@angular/core';
import  NgxErrorsModule  from '@hackages/ngxerrors';
import  ReactiveFormsModule, FormsModule  from '@angular/forms';
import  RouterModule  from '@angular/router';
import  TruncateModule  from 'ng2-truncate';
import  MetaModule  from '@ngx-meta/core';
import  PreventDoubleSubmitModule  from 'ngx-prevent-double-submission';

// Core App
import  AppComponent  from './app.component';
import  CoreInterceptor  from './interceptor';
import  environment  from '../environments/environment';

// Modules
import  SharedModule  from './shared/shared.module';
import  CoreModule  from './services/core.module';
import  LayoutModule  from './layouts/layout.module';

// Sections
import  COMPONENTS  from './components/index';
import  ROUTES  from './app.routes';

// Guards
import  AuthGuard  from './guards/auth.guard';
import  CreditGuard  from './guards/credit.guard';

@NgModule(
  declarations: [
    AppComponent,
    COMPONENTS
  ],
  imports: [
    CommonModule,
    FormsModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireAuthModule,
    AngularFirestoreModule,
    AngularFireStorageModule,

    // This is the Angular google maps module causing issue on build
    AgmCoreModule.forRoot(
      apiKey: environment.googleApiKey,
      libraries: ['places']
    ),

    GooglePlaceModule,
    LayoutModule,
    BrowserModule.withServerTransition( appId: 'test123' ),
    PreventDoubleSubmitModule.forRoot(),
    TruncateModule,
    MetaModule.forRoot(),
    HttpClientModule,
    NgxErrorsModule,
    ReactiveFormsModule,
    RouterModule.forRoot(ROUTES),
    CoreModule,
    SharedModule,
    ServiceWorkerModule.register('/ngsw-worker.js',  enabled: environment.production )
  ],
  providers: [
     provide: HTTP_INTERCEPTORS, useClass: CoreInterceptor, multi: true ,
    AuthGuard,
    CreditGuard,
    AngularFireDatabase
  ],
  exports: [ RouterModule ],
  schemas: [ NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA ],
  bootstrap: [ AppComponent ]
)
export class AppModule  

我运行的命令:serve:npm run build && firebase serve --only 函数

最新错误(对于 npm run serve:s-s-r):

来自 serve:s-s-r: 的错误代码:

e.Lb=function(a,b,c)a=this.ka.J[String(a)];if(!a)return!0;a=a.concat();for(var d=!0,f=0;f<a.length;++f)var g=a[f];if(g&&!g.Sa&&g.capture==b)var k=g.listener,p=g.Ob||g.src;g.Eb&&this.Le(g);d=!1!==k.call(p,c)&&d;return d&&0!=c.Be;e.jb=function(a,b,c,d)return this.ka.jb(String(a),b,c,d);var ub=h.JSON.stringify;function vb(a,b)this.Sf=100;this.ef=a;this.ug=b;this.Zb=0;this.Pb=null;vb.prototype.get=function()if(0<this.Zb)this.Zb--;var a=this.Pb;this.Pb=a.next;a.next=null;else a=this.ef();return a;vb.prototype.put=function(a)this.ug(a);this.Zb<this.Sf&&(this.Zb++, a.next=this.Pb, this.Pb=a);;function I()this.lc=this.Va=null;var xb=new vb(function()return new wb,function(a)a.reset(););I.prototype.add=function(a,b)var c=this.Af();c.set(a,b);this.lc?this.lc.next=c:this.Va=c;this.lc=c;;I.prototype.remove=function()var a=null;this.Va&&(a=this.Va, this.Va=this.Va.next, this.Va||(this.lc=null), a.next=null);return a;I.prototype.wg=function(a)xb.put(a);;I.prototype.Af=function()return xb.get();function wb()this.next=this.scope=this.Gc=null;
wb.prototype.set=function(a,b)this.Gc=a;this.scope=b;this.next=null;;wb.prototype.reset=function()this.next=this.scope=this.Gc=null;;function yb(a)h.setTimeout(function()throw a;,0);var zb;

【问题讨论】:

我在某些地方读到,您可以使用 webpack 配置文件将第三方库列入白名单。但不知道该怎么做。 this issue 中的 cmets 可能会给您一些提示。 One comment 建议使用 import-export 或禁用 AoT 编译作为解决方法。 Another comment 建议将--bundle-dependencies=all 添加到ng build 命令或"bundleDependencies": "all"configurations in angular.json @ConnorsFan 这些链接似乎不适用于 Angular 版本 7 应用程序 @AngularM 在你说它在 v7 中不起作用之前看看这里,不知道你是否尝试过 ng:***.com/questions/39996655/… 【参考方案1】:

TL;DR:

Source codeDEMO


这里的问题是@agm/core 包是用 es2015 模块编译的。结果在js代码中包含importexport

要解决这个问题,您有两个主要选择:

1。将@agm/core 包编译成commonjs 格式。

您可以使用 babel 或 typescript 来编译该包。然后你需要确保你在你的函数依赖中提供了编译版本

functions/package.json

"dependencies": 
  ...
  "@agm/core": "file:./@agm/core"
,

这里我使用本地依赖,但你也可以使用自己发布的版本。

另一种方法是直接在 node_modules 中编译并发布整个 node_modules(我会避免这个):

firebase.json


  "functions": 
    "ignore": []
  

如何编译?

通天塔

在根目录下安装依赖。

npm i -D @babel/cli @babel/core @babel/preset-env

使用以下脚本编译:

package.json

"postbuild": "babel node_modules/@agm/core -d functions/@agm/core --presets @babel/preset-env && node ./copy-package-json.js"

在哪里

copy-package-json.js

const fs = require('fs-extra');
const  join  = require('path');

(async() => 
  await fs.copy(join(process.cwd(), 'node_modules/@agm/core/package.json'),
                join(process.cwd(), 'functions/@agm/core/package.json'));
)();

打字稿

tsconfig.agm.json


  "extends": "./tsconfig.json",
  "compilerOptions": 
    "outDir": "./functions/@agm/core",
    "types": [],
    "module": "commonjs"
  ,
  "include": [
    "node_modules/@agm/core"
  ]

package.json

"postbuild": "tsc -p tsconfig.agm.json --allowJs && node ./copy-package-json.js"

2。生成服务器包

这是 Angular 通用 tutorial 使用的,所以我更喜欢这个解决方案

也关注这个quide

简单的步骤:


1.安装全局依赖项

我已经安装了:

@angular/cli@7.3.8 firebase-tools@6.5.2

2。创建一个新的 Angular 项目

ng new angular-agm

3.添加 Angular 通用

ng add @nguniversal/express-engine --clientProject angular-agm

4.更新 server.ts

导出 express 应用,然后移除调用监听并将索引更改为 index2。

import 'zone.js/dist/zone-node';
import enableProdMode from '@angular/core';
// Express Engine
import ngExpressEngine from '@nguniversal/express-engine';
// Import module map for lazy loading
import provideModuleMap from '@nguniversal/module-map-ngfactory-loader';

import * as express from 'express';
import join from 'path';
import * as path from 'path';

// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();

// Express server
export const app = express();

// const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');

const index = require('fs')
  .readFileSync(path.resolve(DIST_FOLDER, 'index2.html'), 'utf8')
  .toString();

const domino = require('domino');
const win = domino.createWindow(index);
global['window'] = win;
global['document'] = win.document;

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const AppServerModuleNgFactory, LAZY_MODULE_MAP = require('./dist/server/main');

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine(
  bootstrap: AppServerModuleNgFactory,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP)
  ]
));

app.set('view engine', 'html');
app.set('views', DIST_FOLDER);

// Example Express Rest API endpoints
// app.get('/api/**', (req, res) =>  );
// Serve static files from /browser
app.get('*.*', express.static(DIST_FOLDER, 
  maxAge: '1y'
));

// All regular routes use the Universal engine
app.get('*', (req, res) => 
  res.render('index2',  req );
);

// Start up the Node server
/*app.listen(PORT, () => 
  console.log(`Node Express server listening on http://localhost:$PORT`);
);*/

5.构建

npm run build:s-s-r

在哪里构建:s-s-r

"build:s-s-r": "npm run build:client-and-server-bundles && npm run compile:server && node ./tools/copy-artifacts.js",

copy-artifacts.js

const fs = require('fs-extra');
const  join  = require('path');

(async() => 
  const src = join(process.cwd(), 'dist');
  const copy = join(process.cwd(), 'functions/dist');

  await fs.rename(join(src, 'browser/index.html'), join(src, 'browser/index2.html'));
  await fs.remove(copy);
  await fs.copy(src, copy);
)();

6.更新 functions/index.js 以使用 express 应用的内置版本

const functions = require('firebase-functions');

const  app  = require('./dist/server');

exports.s-s-r = functions.https.onRequest(app);

7.配置firebase.json


  "hosting": 
    "public": "dist/browser",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      
        "source": "**",
        "function": "s-s-r"
      
    ]
  

源代码可以在Github找到

另见演示https://angular-agm.firebaseapp.com/

【讨论】:

评论不用于扩展讨论;此对话是moved to chat。 目前 html 在部署时不呈现,但在本地使用 firebase serve 工作。知道为什么吗? 您是否设法找到解决 Angular Universal 的 AngularFire 错误:“TypeError: app.auth is not a function”? 很遗憾,我没有任何可重现的例子。 你能把 angularfire 和 firebase 添加到你的 github 应用,看看你是否得到同样的错误@yurzui?

以上是关于Angular Universal 不适用于 Angular Google 地图的主要内容,如果未能解决你的问题,请参考以下文章

Angular/Rxjs 管道异步不适用于 s-s-r?

Angular Universal 错误 ReferenceError:未定义 MouseEvent

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

Angular 2 Universal 中的身份验证,nodejs

使用 JWT 对 Angular Universal 进行身份验证

(Angular 6) Angular Universal - 不等待内容 API 调用