webentwicklung-frage-antwort-db.com.de

Angular-universal-Abruffehler: Sie müssen ein NgModule oder eine NgModuleFactory übergeben, um gestartet zu werden

Ich habe meine bestehende Winkel-Cli-Anwendung auf Winkel-Universal umgestellt, indem ich diesem Leitfaden folgte.

Sie können meinen vollständigen Quellcode hier ansehen.

Ich kann Browser- und Client-Projekte erstellen, erhalte jedoch folgende Fehlermeldung, wenn ich die App im Browser sehe:

Fehler: Sie müssen ein NgModule oder eine NgModuleFactory übergeben, um .__ zu sein. bootstrapped at View.engine (D:\ng-ssr-demo\dist\server.js: 359545: 23)

Das Problem ist in meiner Datei server.ts enthalten, in der AppServerModuleNgFactory nicht definiert ist. Da diese Factory für das Bootstraping der App im Express-Backend verwendet wird, schlägt das Bootstrapping fehl.

./server.ts:

const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();

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

// Express server
const app = express();

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

// Fix for window error:
const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.resolve('./', 'dist', 'browser/', 'index.html')).toString();
const win = domino.createWindow(template);

// workaround for leaflet
global['window'] = win;
global['document'] = win.document;

// workaround for nex-charts
win.screen = { deviceXDPI: 0, logicalXDPI: 0 };
global['MouseEvent'] = win.MouseEvent;
global['navigator'] = mock.getNavigator();


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

// AppServerModuleNgFactory is undefined
console.log('AppServerModuleNgFactory', AppServerModuleNgFactory);

// This is injected
console.log('LAZY_MODULE_MAP', LAZY_MODULE_MAP);

// 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)
  ]
}));

./webpack.server.config.js:

module.exports = {
  entry: {
    // This is our Express server for Dynamic universal
    server: './server.ts',
    // This is an example of Static prerendering (generative)
    prerender: './prerender.ts'
  },
  target: 'node',
  resolve: { extensions: ['.ts', '.js'] },
  // Make sure we include all node_modules etc
  externals: [/node_modules/],
  output: { path: path.join(__dirname, 'dist'), filename: '[name].js' },
  module: { rules: [{ test: /\.ts$/, loader: 'ts-loader'}] },
  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'), {}
    )
  ]
}

./src/tsconfig.server.json:

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "module": "commonjs",
    "baseUrl": "./",
    "types": ["node"],
    "typeRoots": ["../node_modules/@types"],
    "paths": {
      "@angular/*": [
        "../node_modules/@angular/*"
      ],
      "@nebular/*": [
        "../node_modules/@nebular/*"
      ]
    }
  },
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ],
  "angularCompilerOptions": {
    "entryModule": "app/app.server.module#AppServerModule",
    "platform": 1
  }
}

./src/main.server.ts:

export { AppServerModule } from './app/app.server.module';

./src/app/app.module.ts:

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule.withServerTransition({appId: 'my-app'}),
    BrowserAnimationsModule,
    HttpModule,
    AppRoutingModule,

    NgbModule.forRoot(),
    ThemeModule.forRoot(),
    CoreModule.forRoot(),
    environment.production ? ServiceWorkerModule.register('./ngsw-worker.js') : [],
  ],
  bootstrap: [AppComponent],
  providers: [
    { provide: APP_BASE_HREF, useValue: '/' }, WebWorkerService,
  ],
})
export class AppModule {
}

./src/app/app.server.module.ts:

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    ModuleMapLoaderModule
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule {}
18

Ich habe Ihr Repo ausgecheckt und konnte die Dist-Fine ohne diesen Fehler im Browser anzeigen. Vielleicht haben Sie vergessen, das Flag -prod hinzuzufügen, wenn Sie build ausführen. Bitte versuchen Sie das

ng build --prod

Sie können auch den dist vollständig entfernen und/oder node_modules entfernen, npm cache clean ausführen, npm install ausführen, bevor Sie versuchen, erneut zu erstellen.

Wenn Sie npm-Skripts verwenden, stelle ich fest, dass in Ihrem/server-Build das --prod-Flag fehlt. Bitte versuchen Sie das

"build:server": "ng build --prod --app 1 --output-hashing=false",
8
Arielle Nguyen

ANGULAR 8 UPDATE (v8.0.1 - Stand Juni 2019)

Für mich führte ich das universelle Setup mit der Angular CLI aus und es funktionierte nicht sofort. Nach stundenlangem Durchlesen stellte ich fest, dass die Pakete nicht übereinstimmten Angular 8 das Projekt ausführen, aber Nguniversal-Pakete in meinem package.json wurden bei v7 angegeben.

Ich würde empfehlen, diese auf die gleiche Version von angular, die Sie installiert haben) zu aktualisieren. Die CLI sollte dies eigentlich standardmäßig tun, aber ich denke nicht (noch?).

Für Angular 8, zum Zeitpunkt des Schreibens (Juni 2019) ist dies die Version @next Oder @8.0.0-rc.1. Führen Sie daher zum Aktualisieren den folgenden Befehl aus:

npm i --save @nguniversal/[email protected] @nguniversal/[email protected]

Nachdem ich dies aktualisiert hatte, wurde immer noch der Fehler angezeigt und es gelang mir, ein anderes Problem zu identifizieren. Ich musste auch den Ivy-Compiler für die serverseitige Anwendung ausschalten. Dazu habe ich dem tsconfig.server.json Folgende Zeile hinzugefügt:

{
    "extends": "./tsconfig.app.json",
    ...
    "angularCompilerOptions": {
        ...
        "enableIvy": false
    }
    ...
}

Ivy ist in Angular 8 standardmäßig deaktiviert, aber da mein tsconfig.server.jsontsconfig.app.json Erweitert und in der App-Konfiguration Ivy aktiviert war, musste ich ihn explizit aktivieren off für die Serverkonfiguration.

Nach all dem begannen Server-Anfragen nach Inhalten für mich zu funktionieren.

Wenn dies nicht hilft, würde ich empfehlen, das universelle Beispielprojekt herunterzuladen, das in den angular docs erwähnt wird:

Download: https://angular.io/generated/zips/universal/universal.Zip Dokumentation: https://angular.io/guide/universal

Vergleichen Sie nach dem Herunterladen alle relevanten Dateien, um sicherzustellen, dass Sie dieselben haben. Wenn in Ihrem eigenen Projekt weiterhin Fehler auftreten, das Beispiel jedoch funktioniert, verschieben Sie die Einstellungsdateien, Module und Komponenten usw. nacheinander in das Beispielprojekt, und überprüfen Sie, welche Fehler auftreten. Auf diese Weise konnte ich feststellen, dass es meine tsconfig.server.json - Datei war, die sie beschädigt hat.

4
DoubleA

verwenden Sie mode: 'development', für webpack.config.js

0
gorniv
    const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');

können Sie bitte überprüfen, ob 'AppServerModuleNgFactory' in Ihrem main.bundle vorhanden ist. Es kann sich auch um andere Namen handeln. Überprüfen Sie also mit "ModuleNgFactory", welche NgFactory Ihre App exportiert. Ersetzen Sie einfach den Fabriknamen.

0
sheravanan