angular-cli: angular universal server.ts fails

Versions

    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 6.0.0
Node: 8.10.0
OS: linux x64
Angular: 5.2.9
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.6.0
@angular-devkit/build-angular     0.6.0
@angular-devkit/build-optimizer   0.6.0
@angular-devkit/core              0.0.29
@angular-devkit/schematics        0.6.0
@angular/cli                      6.0.0
@angular/platform-server          6.0.0
@ngtools/webpack                  6.0.0
@schematics/angular               0.6.0
@schematics/update                0.6.0
rxjs                              5.5.7
typescript                        2.4.2
webpack                           4.6.0
-----------------------------------------------------------------------------
Distributor ID:	Debian
Description:	Debian GNU/Linux 9.4 (stretch)
Release:	9.4
Codename:	stretch

Repro steps

Observed behavior

project builds and the server runs, but when entering to localhost:4000 an error is throw

Node server listening on http://localhost:4000
ERROR { TypeError: StaticInjectorError[function (){} -> InjectionToken DocumentToken]:
  StaticInjectorError(Platform: core)[function (){} -> InjectionToken DocumentToken]:
    Right-hand side of 'instanceof' is not an object
    at bt (/home/username/Desktop/projectname/dist/server.js:1239:87385)
    at yt (/home/username/Desktop/projectname/dist/server.js:1239:87260)
    at ir (/home/username/Desktop/projectname/dist/server.js:1239:110031)
    at He.insertToken (/home/username/Desktop/projectname/dist/server.js:1239:86646)
    at /home/username/Desktop/projectname/dist/server.js:1239:89924
    at Mt (/home/username/Desktop/projectname/dist/server.js:1239:89939)
    at Ke (/home/username/Desktop/projectname/dist/server.js:1239:84920)
    at Object.parse (/home/username/Desktop/projectname/dist/server.js:1239:83906)
    at Object.t.createDocument (/home/username/Desktop/projectname/dist/server.js:3180:76668)
    at Object.t.createWindow (/home/username/Desktop/projectname/dist/server.js:3180:76772)
  ngTempTokenPath: null,
  ngTokenPath:
   [ 'function (){}',
     e { _desc: 'DocumentToken', ngMetadataName: 'InjectionToken' } ] }
Unhandled Promise rejection: StaticInjectorError[function (){} -> InjectionToken DocumentToken]:
  StaticInjectorError(Platform: core)[function (){} -> InjectionToken DocumentToken]:
    Right-hand side of 'instanceof' is not an object ; Zone: <root> ; Task: Promise.then ; Value: { TypeError: StaticInjectorError[function (){} -> InjectionToken DocumentToken]:
  StaticInjectorError(Platform: core)[function (){} -> InjectionToken DocumentToken]:
    Right-hand side of 'instanceof' is not an object
    at bt (/home/username/Desktop/projectname/dist/server.js:1239:87385)
    at yt (/home/username/Desktop/projectname/dist/server.js:1239:87260)
    at ir (/home/username/Desktop/projectname/dist/server.js:1239:110031)
    at He.insertToken (/home/username/Desktop/projectname/dist/server.js:1239:86646)
    at /home/username/Desktop/projectname/dist/server.js:1239:89924
    at Mt (/home/username/Desktop/projectname/dist/server.js:1239:89939)
    at Ke (/home/username/Desktop/projectname/dist/server.js:1239:84920)
    at Object.parse (/home/username/Desktop/projectname/dist/server.js:1239:83906)
    at Object.t.createDocument (/home/username/Desktop/projectname/dist/server.js:3180:76668)
    at Object.t.createWindow (/home/username/Desktop/projectname/dist/server.js:3180:76772)
  ngTempTokenPath: null,
  ngTokenPath:
   [ 'function (){}',
     e { _desc: 'DocumentToken', ngMetadataName: 'InjectionToken' } ] } TypeError: StaticInjectorError[function (){} -> InjectionToken DocumentToken]:
  StaticInjectorError(Platform: core)[function (){} -> InjectionToken DocumentToken]:
    Right-hand side of 'instanceof' is not an object
    at bt (/home/username/Desktop/projectname/dist/server.js:1239:87385)
    at yt (/home/username/Desktop/projectname/dist/server.js:1239:87260)
    at ir (/home/username/Desktop/projectname/dist/server.js:1239:110031)
    at He.insertToken (/home/username/Desktop/projectname/dist/server.js:1239:86646)
    at /home/username/Desktop/projectname/dist/server.js:1239:89924
    at Mt (/home/username/Desktop/projectname/dist/server.js:1239:89939)
    at Ke (/home/username/Desktop/projectname/dist/server.js:1239:84920)
    at Object.parse (/home/username/Desktop/projectname/dist/server.js:1239:83906)
    at Object.t.createDocument (/home/username/Desktop/projectname/dist/server.js:3180:76668)
    at Object.t.createWindow (/home/username/Desktop/projectname/dist/server.js:3180:76772)

Desired behavior

Is expected to render the application

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 15
  • Comments: 24 (1 by maintainers)

Most upvoted comments

Setting mode: 'none' in webpack config solved this issue for me. But the bundle sized increased from 1.6Mb to 4.8Mb

Webpack in mode: "production" optimizes the output with certain defaults (If you don’t set a mode, it is “production” by default). One optimization is including UglifyJsPlugin which will mangle class and functions names and break injection. You can (and should) keep production mode for all other optimizations. All of the following edits are made to your webpack.server.config.js file.

module.exports = {
  mode: "production",
  ...
}

and just disable UglifyJs

module.exports = {
  mode: "production",
  ...
  optimization: {
    minimize: false
  },
  ...
}

This does NOT affect the client side js bundles sent to the browser, just your server.js file running in node. However, if you really want the server.js to be minimized as well (I doubt that will have any impact on the performance at all) you can manually add UglifyJsPlugin back and enable keep_classnames and keep_fnames options.

module.exports = {
  mode: "production",
  ...
  optimization: {
    minimize: false
  },
  plugins: [
    new UglifyJsPlugin({
      parallel: true,
      uglifyOptions: {
        keep_classnames: true,
        keep_fnames: true
      }
    }),
    ...
  ]
  ...
}

Here my configuration for universal:

"server": {
  "builder": "@angular-devkit/build-angular:server",
  "options": {
    "outputPath": "dist/server",
    "main": "src/main.server.ts",
    "tsConfig": "src/tsconfig.server.json",
     "fileReplacements": [
       {
         "replace": "src/environments/environment.ts",
         "with": "src/environments/environment.prod.ts"
       }
     ],
     "optimization": true,
     "sourceMap": false
  }
}

Like this we have an optimization for the build & the good environment.

yes, just confirming this seems to be a fix. bundle size isn’t that great (BIG project pumping out 8.4mb) but I suppose it doesn’t matter seeing that it’s running on the server. I guess file size isn’t as big an issue because the client isn’t downloading it. but still, if uglifying and compiling server code is going to improve server performance production compiling should be an option.

In addition, this are the scripts I’m using (most of them are boilerplate code posted on https://github.com/angular/angular-cli/wiki/stories-universal-rendering)

angular.json architect->server section

    "server": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist/server",
            "main": "src/main.server.ts",
            "tsConfig": "src/tsconfig.server.json"
          }
        },

package.json relevant scripts

    "build:client-and-server-bundles": "ng build --prod && ng run projectname:server",
    "build:prerender": "npm run build:client-and-server-bundles && npm run webpack:server && npm run generate:prerender",
    "build:ssr": "npm run build:client-and-server-bundles && npm run webpack:server",
    "generate:prerender": "cd dist && node prerender",
    "webpack:server": "webpack --config webpack.server.config.js --progress --colors",
    "serve:prerender": "cd dist/browser && http-server",
    "serve:ssr": "node dist/server"

using npm run build:ssr && npm run serve:ssr to build and run

main.server.ts

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

app.server.module.ts

import {NgModule} from '@angular/core';
import {ServerModule} from '@angular/platform-server';
import {ModuleMapLoaderModule} from '@nguniversal/module-map-ngfactory-loader';

import {AppModule} from './app.module';
import { RootComponent } from '../root/root.component';

@NgModule({
  imports: [
    // The AppServerModule should import your AppModule followed
    // by the ServerModule from @angular/platform-server.
    AppModule,
    ServerModule,
    ModuleMapLoaderModule // <-- *Important* to have lazy-loaded routes work
  ],
  // Since the bootstrapped component is not inherited from your
  // imported AppModule, it needs to be repeated here.
  bootstrap: [RootComponent], // small change over here since this is the name of my bootstrap component
})
export class AppServerModule {}

tsconfig.server.json

{
    "extends": "../tsconfig.json",
    "compilerOptions": {
      "outDir": "../out-tsc/app",
      "baseUrl": "./",
      "module": "commonjs",
      "types": []
    },
    "exclude": [
      "test.ts",
      "**/*.spec.ts"
    ],
    "angularCompilerOptions": {
      "entryModule": "app/app.server.module#AppServerModule"
    }
  }

webpack.server.config.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {  server: './server.ts' },
  resolve: { extensions: ['.js', '.ts'] },
  target: 'node',
  // this makes sure we include node_modules and other 3rd party libraries
  externals: [/(node_modules|main\..*\.js)/],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      { test: /\.ts$/, loader: 'ts-loader' }
    ]
  },
  plugins: [
    // Temporary Fix for issue: https://github.com/angular/angular/issues/11580
    // for "WARNING Critical dependency: the request of a dependency is an expression"
    new webpack.ContextReplacementPlugin(
      /(.+)?angular(\\|\/)core(.+)?/,
      path.join(__dirname, 'src'), // location of your src
      {} // a map of your routes
    ),
    new webpack.ContextReplacementPlugin(
      /(.+)?express(\\|\/)(.+)?/,
      path.join(__dirname, 'src'),
      {}
    )
  ]
}