首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular-universal获取错误:必须传入NgModule或NgModuleFactory才能启动

Angular-universal获取错误:必须传入NgModule或NgModuleFactory才能启动
EN

Stack Overflow用户
提问于 2018-04-16 13:41:02
回答 5查看 6.9K关注 0票数 27

通过遵循this guide,我将现有的angular-cli应用程序转换为angular-universal。

你可以看看我完整的源代码here

我可以构建浏览器和客户端项目,但在浏览器中查看应用程序时出现以下错误:

错误:必须传入NgModule或NgModuleFactory才能在View.engine中引导(D:\ng-ssr-demo\dist\server.js:359545:23)

问题出在我的server.ts文件中,其中的AppServerModuleNgFactory是未定义的,并且由于此工厂用于在express后端引导应用程序,因此引导失败。

Server./server.ts:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
{
  "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:

代码语言:javascript
复制
export { AppServerModule } from './app/app.server.module';

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

代码语言:javascript
复制
@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:

代码语言:javascript
复制
@NgModule({
  imports: [
    AppModule,
    ServerModule,
    ModuleMapLoaderModule
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule {}
EN

回答 5

Stack Overflow用户

发布于 2019-06-17 21:21:48

ANGULAR 8更新(v8.0.1 -截至2019年6月)

对我来说,我使用Angular CLI运行了通用设置,但它不能直接工作。在阅读了几个小时后,我发现这些包是不匹配的。我让Angular 8运行这个项目,但是我的package.json中的nguniversal包是在v7中指定的。

我建议您将这些更新到与您安装的angular相同的版本。默认情况下,CLI确实应该这样做,但我猜不是(还没有?)

对于Angular 8,在撰写本文时(2019年6月),它是@next@8.0.0-rc.1版本,因此运行以下命令进行更新:

代码语言:javascript
复制
npm i --save @nguniversal/express-engine@next @nguniversal/module-map-ngfactory-loader@next

在我更新了这篇文章后,我仍然收到错误,并设法确定了另一个问题。我还必须关闭服务器端应用程序的Ivy编译器。为此,我将以下行添加到tsconfig.server.json

代码语言:javascript
复制
{
    "extends": "./tsconfig.app.json",
    ...
    "angularCompilerOptions": {
        ...
        "enableIvy": false
    }
    ...
}

在Angular 8中,Ivy在默认情况下是关闭的,但是因为我的tsconfig.server.json扩展了tsconfig.app.json,并且应用程序配置打开了Ivy,所以我不得不在服务器配置中显式地关闭它。

经过这一切,服务器对内容的请求实际上开始对我起作用了。

如果这对您没有帮助,我建议您下载angular文档中提到的通用示例项目:

下载:https://angular.io/generated/zips/universal/universal.zip文档:https://angular.io/guide/universal

下载后,比较所有相关文件,以确保您拥有相同的文件。如果你仍然在你自己的项目中得到错误,但是示例工作正常,那么,试着在示例项目中逐个移动你的设置文件、模块和组件等,看看是什么破坏了它。这就是我如何能够确定是我的tsconfig.server.json文件破坏了它。

票数 12
EN

Stack Overflow用户

发布于 2018-04-19 16:31:59

我查看了您的存储库,并且能够在浏览器中查看dist,而不会出现该错误。也许您在运行build时忘记添加标志-prod?请试试这个

代码语言:javascript
复制
ng build --prod

您还可以完全删除dist和/或删除node_modules,执行npm cache clean,在尝试重新构建之前运行npm install

如果您正在使用npm脚本,我注意到您的/server构建缺少--prod标志。请试试这个

代码语言:javascript
复制
"build:server": "ng build --prod --app 1 --output-hashing=false",
票数 8
EN

Stack Overflow用户

发布于 2018-12-06 07:08:24

代码语言:javascript
复制
    const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');

您可以检查一下您的main.bundle中是否存在'AppServerModuleNgFactory‘吗?它可能使用其他名称,所以只需检查"ModuleNgFactory“找出哪个NgFactory正在导出您的应用程序,只需将其替换为工厂名称即可。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49850267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档