Universal: You must pass in a NgModule or NgModuleFactory to be bootstrapped

Created on 14 Sep 2017  Â·  11Comments  Â·  Source: angular/universal

I have just tried Angular Universal using angular universal starter.
I did customize it a bit by doing the following changes:

server.js

  var isOldIE = isIE(req.headers['user-agent']) && isIE(req.headers['user-agent']) !== 11 ? true : false
  if(isOldIE) {
      // Static
      res.render('index.html', {
          req: req,
          res: res
      });
  }
  else {
      // SPA
      res.sendFile('index.html', {root: __dirname});
  }

app.module.ts

@NgModule({
  imports: [
    CommonModule,
    HttpModule,
    RouterModule.forRoot([
  {
    path: '', redirectTo: '/comp', pathMatch: 'full'
  },
  {
    path: 'comp',
    loadChildren: 'app/comp/comp.module#CompModule'
  },
])
  ],
  declarations: [ AppComponent, ...],
  exports: [ AppComponent ]
})
export class AppModule {}

My comp module is basicaly a seed with only a main component display "foo"

If I try running it with a recent browser, I get the site working well (and I get the non-static version of the source).

Now If I do masquerade as IE10 by instance (changing my user-agent). I get the following error :

GET: /comp: 8.912ms
Error: You must pass in a NgModule or NgModuleFactory to be bootstrapped
    at View.engine (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\@nguniversal\express-engine\src\main.js:34:23)
    at View.render (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\view.js:127:8)
    at tryRender (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\application.js:640:10)
    at EventEmitter.render (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\application.js:592:3)
    at ServerResponse.render (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\response.js:971:7)
    at app.get (C:\dev\workspace\neo\foyer-redbutton-front\ui\dist\server.js:50:11)
    at Layer.handle [as handle_request] (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\layer.js:95:5)
GET: /: 0.489ms
Error: You must pass in a NgModule or NgModuleFactory to be bootstrapped
    at View.engine (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\@nguniversal\express-engine\src\main.js:34:23)
    at View.render (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\view.js:127:8)
    at tryRender (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\application.js:640:10)
    at EventEmitter.render (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\application.js:592:3)
    at ServerResponse.render (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\response.js:971:7)
    at app.get (C:\dev\workspace\neo\foyer-redbutton-front\ui\dist\server.js:50:11)
    at Layer.handle [as handle_request] (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\dev\workspace\neo\foyer-redbutton-front\ui\node_modules\express\lib\router\layer.js:95:5)

I used the following command :
ng build && ng build --app 1 --output-hashing=false && cpy ./server.js ./dist && cd dist && node server

Any idea what am I doing wrong ?

Most helpful comment

The problem is solved. The guide creates a main.server.ts file and does nothing with it :-|
Also in the guide's example there's no main.server.ts at all and that confused me.
But the problem is solved by putting export { AppServerModule } from './app/app.server.module'; in main.server.ts. Thanks...

All 11 comments

Were you to fix this problem?

you've left out the --prod flag on the ng build. --prod includes aot mode which generates the ModuleNgFactory files for the ts modules. Correct me if i'm wrong

Yes you need prod for both those apps

But I have the --prod flag and I still get the same error. I've used the recommended commands in the Angular Universal guide.
"build:universal": "npm run build:client-and-server-bundles && npm run webpack:server", "serve:universal": "node dist/server.js", "build:client-and-server-bundles": "ng build --prod && ng build --prod --app 1 --output-hashing=false", "webpack:server": "webpack --config webpack.server.config.js --progress --colors"
first I build the project and it's fine. But when it comes to opening a tab in the browser I get the same error.

things I would check:

  1. Is angular/cli up to date (right now it's at 1.7.3)

  2. is angular/compiler up to date.

  3. is your angular-cli.json in the correct format/order (the --app 1 options is the selection of the app in the angular-cli.json

  4. in the dist folder do you see browser & server folders?

somewhere along the line, the compiler may not be producing the ngModule files OR they may not be being imported in the correct files e.g.

prerender.ts --->

```
// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

import { renderModuleFactory } from '@angular/platform-server';

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

```
here it looks like the main.bundle file is the important one: so check that it is present in the dist/server folder.

I noticed that there is a main.server.ts file that is empty. Why is that? There's nothing mentioned about it in the guide. It just creates the file and leaves it empty and mentions that it's an entry point for the server.
https://angular.io/guide/universal
Also everything you mentioned above is OK, but the problem is still around.

The problem is solved. The guide creates a main.server.ts file and does nothing with it :-|
Also in the guide's example there's no main.server.ts at all and that confused me.
But the problem is solved by putting export { AppServerModule } from './app/app.server.module'; in main.server.ts. Thanks...

Following other recomendations, I have put the aot option to false so I dont get the "Property ‘x’ is private and only accessible within class ‘MyComponent’ " error. From this, I understand that its necessary that aot must be true.
Should I change all my private properties and object types so aot dosen't complain?
I am using Angular-Starter and there AoT complains/errors let me continue, it dosen't stop the compilation. How can I do the same? I notice that those scripts from Angular-Starter dosen't use ng but I don't know how to reproduce it.

I have made the changes and now aot does not have any error. But I get the same error when I enter on the page. Could I have an error on webpack/tsconfig configuration and not poitting something right? I have checked it multiple times but maybe I am doing something wrong.

If your trying to access a private property in a template then it's going to break.

You can only access public properties in the component templates when compiling for aot or production.

Post your tsconfig.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings