部署 Angular 通用应用程序时找不到模块 'firebase/app'

Cannot find module 'firebase/app' while deploying Angular Universal app

我处理这个问题已经快两周了。我尝试了很多解决方法,但 none 似乎有效。我已将 angular-firefirebase 安装到其最新版本,尝试 ng add @angular/fire,配置自定义 webpack.config.ts,尝试回滚到每个建议的先前版本。 None 解决了这个问题。

实际错误:

de-10@de10-LIFEBOOK-A555:~/Desktop$ node dist/server.js 
internal/modules/cjs/loader.js:797
    throw err;
    ^

Error: Cannot find module 'firebase/app'
Require stack:
- /home/de-10/Desktop/dist/server.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:794:15)
    at Function.Module._load (internal/modules/cjs/loader.js:687:27)
    at Module.require (internal/modules/cjs/loader.js:849:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/home/de-10/Desktop/dist/server.js:125276:18)
    at __webpack_require__ (/home/de-10/Desktop/dist/server.js:20:30)
    at Module.<anonymous> (/home/de-10/Desktop/dist/server.js:125199:70)
    at __webpack_require__ (/home/de-10/Desktop/dist/server.js:20:30)
    at Module.<anonymous> (/home/de-10/Desktop/dist/server.js:124984:78)
    at __webpack_require__ (/home/de-10/Desktop/dist/server.js:20:30) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/home/de-10/Desktop/dist/server.js' ]
}

而且我无法放弃 Firebase,因为我将面临:

ERROR in ../node_modules/@angular/fire/auth/auth.d.ts:4:28 - error TS2307: Cannot find module 'firebase/app'.

4 import { User, auth } from 'firebase/app';
                             ~~~~~~~~~~~~~~
../node_modules/@angular/fire/firebase.app.module.d.ts:2:74 - error TS2307: Cannot find module 'firebase/app'.

2 import { auth, database, messaging, storage, firestore, functions } from 'firebase/app';
                                                                           ~~~~~~~~~~~~~~
../node_modules/@angular/fire/firestore/collection-group/collection-group.d.ts:2:27 - error TS2307: Cannot find module 'firebase/app'.
                            ~~~~~~~~~~~~~
.
.
.
app/services/notification.service.ts:29:38 - error TS2339: Property 'id' does not exist on type 'QueryDocumentSnapshot<unknown>'.

29                 id: snap.payload.doc.id,
                                        ~~
app/services/notification.service.ts:68:35 - error TS2339: Property 'type' does not exist on type 'DocumentChange<unknown>'.

68               return snap.payload.type
                                     ~~~~
.
.
.

package.json

{
  "name": "universal-ssr",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "npm run build:ssr",
    "staging": "npm run build:ssr-staging && npm run serve:ssr",
    "production": "npm run build:ssr && npm run serve:ssr",
    "prod": "npm run build:ssr-production && npm run serve:ssr",
    "build": "ng build --prod",
    "test": "ng test",
    "dev-start": "ng serve",
    "ng serve": "ng serve --aot",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "build:ssr": "npm run build:client-and-server-bundles && npm run webpack:server",
    "build:ssr-staging": "npm run build:client-and-server-bundles-staging && npm run webpack:server",
    "build:ssr-production": "npm run build:client-and-server-bundles-production && npm run webpack:server",
    "serve:ssr": "node dist/server.js",
    "build:client-and-server-bundles": "ng build --prod --build-optimizer && ng run universal-ssr:server --bundleDependencies all",
    "build:client-and-server-bundles-staging": "ng build --c=staging --build-optimizer=true --stats-json  && ng run universal-ssr:server",
    "build:client-and-server-bundles-production": "ng build --c=production --build-optimizer=true  && ng run universal-ssr:server --bundleDependencies all",
    "webpack:server": "webpack --config webpack.config.js --progress --colors",
    "webpack:analyzer": "webpack-bundle-analyzer dist/browser/stats.json",
    "compodoc": "npx compodoc -p src/tsconfig.app.json -o"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^8.2.14",
    "@angular/cdk": "^5.2.5",
    "@angular/common": "^8.2.14",
    "@angular/compiler": "^8.2.14",
    "@angular/core": "^8.2.14",
    "@angular/fire": "^5.4.2",
    "@angular/forms": "^8.2.14",
    "@angular/material": "^5.2.5",
    "@angular/platform-browser": "^8.2.14",
    "@angular/platform-browser-dynamic": "^8.2.14",
    "@angular/platform-server": "^8.2.14",
    "@angular/pwa": "^0.803.24",
    "@angular/router": "^8.2.14",
    "@angular/service-worker": "^8.2.14",
    "@ng-bootstrap/ng-bootstrap": "^4.0.0",
    "@nguniversal/express-engine": "^6.1.0",
    "@nguniversal/module-map-ngfactory-loader": "^6.1.0",
    "angular2-datetimepicker": "^1.1.1",
    "bootstrap": "^4.4.1",
    "city-timezones": "^1.2.0",
    "core-js": "^2.6.11",
    "cors": "^2.8.4",
    "express": "^4.17.1",
    "firebase": "^7.13.1",
    "jquery": "^3.4.1",
    "moment-timezone": "^0.5.27",
    "ng-bootstrap": "^1.6.3",
    "ng2-search-filter": "^0.5.1",
    "ngx-clipboard": "12.2.1",
    "ngx-google-places-autocomplete": "^2.0.4",
    "ngx-pagination": "^3.3.1",
    "ngx-spinner": "^2.0.0",
    "ngx-toggle-switch": "^2.0.5",
    "ngx-ui-switch": "^8.3.0",
    "rxjs": "^6.5.4",
    "rxjs-compat": "^6.0.0",
    "save": "^2.4.0",
    "ts-loader": "^4.0.0",
    "tslib": "^1.10.0",
    "uuid": "^3.4.0",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.803.23",
    "@angular/cli": "^8.3.23",
    "@angular/compiler-cli": "^8.2.14",
    "@angular/http": "^7.2.16",
    "@angular/language-service": "^8.2.14",
    "@types/jasmine": "2.8.3",
    "@types/jasminewd2": "^2.0.8",
    "@types/node": "^6.14.9",
    "codelyzer": "^5.0.1",
    "jasmine-core": "~2.8.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "^4.4.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^2.1.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "5.4.2",
    "ts-node": "~4.1.0",
    "tslint": "~5.9.1",
    "typescript": "~3.5.3",
    "webpack-cli": "^3.1.0"
  }
}

webpack.config.js:

// Work around for https://github.com/angular/angular-cli/issues/7200

const path = require('path');
const webpack = require('webpack');
// change the regex to include the packages you want to exclude
const regex = /firebase\/(app|firestore)/;


module.exports = {
  mode: 'production',
  entry: {
    // This is our Express server for Dynamic universal
    server: './server.ts'
  },
  externals: {
    './dist/server/main': 'require("./server/main")'
  },
  target: 'node',
  node: {
    __dirname: false,
    __filename: false,
  },
  resolve: { extensions: ['.ts', '.js'] },
  target: 'node',
  mode: 'none',
  // this makes sure we include node_modules and other 3rd party libraries
  externals: [/node_modules/, function (context, request, callback) {
    // exclude firebase products from being bundled, so they will be loaded using require() at runtime.
    if (regex.test(request)) {
      return callback(null, 'commonjs ' + request);
    }
    callback();
  }],
  optimization: {
    minimize: false
  },
  output: {
    // Puts the output at the root of the dist folder
    path: path.join(__dirname, 'dist'),
    filename: '[name].js'
  },
  module: {
    noParse: /polyfills-.*\.js/,
    rules: [
      { test: /\.ts$/, loader: 'ts-loader' },
      {
        // Mark files inside `@angular/core` as using SystemJS style dynamic imports.
        // Removing this will cause deprecation warnings to appear.
        test: /(\|\/)@angular(\|\/)core(\|\/).+\.js$/,
        parser: { system: true },
      },
    ]
  },
  plugins: [
    new webpack.ContextReplacementPlugin(
      // fixes WARNING Critical dependency: the request of a dependency is an expression
      /(.+)?angular(\|\/)core(.+)?/,
      path.join(__dirname, 'src'), // location of your src
      {} // a map of your routes
    ),
    new webpack.ContextReplacementPlugin(
      // fixes WARNING Critical dependency: the request of a dependency is an expression
      /(.+)?express(\|\/)(.+)?/,
      path.join(__dirname, 'src'),
      {}
    )
  ]
};

server.ts:

import 'zone.js/dist/zone-node';
import * as express from 'express';
/* const express = require('express');
const join = require('path'); */
const compression = require('compression')
import { join } from 'path';
// Express server

const app = express();
// gzip
app.use(compression())


const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(__dirname, 'browser');/* 'dist/browser' */
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap } = 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);

// 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('index', { req });
});

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

一种解决方法是在 dist 文件夹旁边安装 npm 包(firebase 和 @angular/fire),然后 运行 部署脚本。

您收到此错误是因为您用此排除了 firebase 依赖项 =>

const regex = /firebase\/(app|firestore)/;
module.exports = {
  // this makes sure we include node_modules and other 3rd party libraries
  externals: [/node_modules/, function (context, request, callback) {
    // exclude firebase products from being bundled, so they will be loaded using require() at runtime.
    if (regex.test(request)) {
      return callback(null, 'commonjs ' + request);
    }
    callback();
  }],
};

删除这个

    if (regex.test(request)) {
      return callback(null, 'commonjs ' + request);
    }

你的应用程序会很好。