Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No apparent way to use --bundle-dependencies=all successfully since 1.5.0 #8616

Closed
SteveSandersonMS opened this issue Nov 23, 2017 · 44 comments
Assignees
Labels
area: devkit/build-angular freq1: low Only reported by a handful of users who observe it rarely P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful severity5: regression
Milestone

Comments

@SteveSandersonMS
Copy link

Prior to the 1.5.0 release, it was possible to pass --bundle-dependencies=all --prod to get an AoT compiled self-contained bundle that worked for server-side rendering (SSR) under Node.js. Since 1.5.0, these flags produce a bundle that, as far as I can tell, can never work because they now rely on the existence of browser DOM APIs that don't exist in Node.

If there is any way to use --bundle-dependencies=all successfully in --prod build with 1.5.0+, I'd love to know about it.

Versions

Angular CLI: 1.5.4
Node: 6.11.0
OS: win32 x64
Angular: 5.0.2
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router

@angular/cli: 1.5.4
@angular-devkit/build-optimizer: 0.0.33
@angular-devkit/core: 0.0.21
@angular-devkit/schematics: 0.0.37
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.8.4
@schematics/angular: 0.1.7
typescript: 2.4.2
webpack: 3.8.1

Repro steps

  • Clone the example repo at https://github.com/SteveSandersonMS/angular-bundledependencies-repro. This is the same as the universal-starter repo, except for one commit that gets as close as I can to a scenario where --bundle-dependencies=all could work (but still doesn't).
  • Run npm install
  • Observe that it works fine in a non-prod build by running npm run build:ssr then npm run serve:ssr. If you visit http://localhost:4000, you'll get both server and client rendering.
  • Observe that if you build in prod mode (run npm run build:ssr:prod then npm run serve:ssr), then it does not work - you'll get this error:
TypeError: StaticInjectorError[InjectionToken DocumentToken]: 
  StaticInjectorError[InjectionToken DocumentToken]: 
    Right-hand side of 'instanceof' is not an object
    at ke (C:\path\angular-bundledependencies-repro\dist\server.js:4106:724114)
    at xe (C:\path\angular-bundledependencies-repro\dist\server.js:4106:723991)
    at lr (C:\path\angular-bundledependencies-repro\dist\server.js:4106:746752)
    at _n.insertToken (C:\path\angular-bundledependencies-repro\dist\server.js:4106:767718)
    at C:\path\angular-bundledependencies-repro\dist\server.js:4106:726646
    at Fe (C:\path\angular-bundledependencies-repro\dist\server.js:4106:726661)
    at I (C:\path\angular-bundledependencies-repro\dist\server.js:4106:721959)
    at Object.parse (C:\path\angular-bundledependencies-repro\dist\server.js:4106:766648)
    at Object.t.createDocument (C:\path\angular-bundledependencies-repro\dist\server.js:4106:1194422)
    at Object.t.createWindow (C:\path\angular-bundledependencies-repro\dist\server.js:4106:1194526)

If you trace this into the server.js bundle code, what's happening is that it's testing whether someValue instanceof HTMLElement (though it's not obvious at first glance because everything is minified and renamed). That code would be OK in a browser, but it's an error in Node, because HTMLElement is undefined. So the generated bundle isn't going to work for SSR under Node.

  • If you want, verify that removing --bundle-dependencies=all from lines 22 and 23 in package.json is enough to make it work in both dev and prod builds. So the problem is the combination of --prod with --bundle-dependencies=all - you can use either on their own, but not both together.

Observed behavior

Fails with the Right-hand side of 'instanceof' is not an object error shown above.

Desired behavior

SSR works as it did in the non-prod build.

Mention any other details that might be useful (optional)

The equivalent did work pre-1.5.0 (which was also Angular 4.x).

The reason I'm asking about this is because I'm building new Angular CLI-based ASP.NET templates that will be included in the .NET Core SDK and Visual Studio. We want the template to use --bundle-dependencies=all by default because then developers don't have to publish their node_modules to production, and attempting to publish 20,000+ files from node_modules is extremely time-consuming (and not always reliable) from VS. Plus it tends to hit Windows path-length limitations depending on the deployment target.

@naveedahmed1
Copy link

@filipesilva any thoughts on this?

@filipesilva filipesilva added the needs: investigation Requires some digging to determine if action is needed label Nov 24, 2017
@filipesilva
Copy link
Contributor

@Brocco can you take a look please?

@naveedahmed1
Copy link

@Brocco did you get a chance to look into this?

@asadsahi
Copy link

asadsahi commented Dec 8, 2017

Really love to have this nailed down. Thanks guys.

@naveedahmed1
Copy link

@hansl is it due to the issue reported here #8900 ?

@naveedahmed1
Copy link

naveedahmed1 commented Jan 5, 2018

Ok I think the issue is with the uglifyjs plugin. It seems that angular cli is using --mangle and --compress option with this plugin for server bundles and its causing the issue.

To confirm this, I first build bundle using below command:

ng build --app=ssr --output-hashing=media --aot --bundle-dependencies=all

Then I used uglifyjs using below command

uglifyjs main.bundle.js --output output.js

(main.bundle.js is the server bundle generated in 1st command)

the bundle generated after above command worked perfectly.

Then I tried generating a bundle with --compress and --mangle

uglifyjs main.bundle.js --output output.js --compress --mangle

when I used this bundle it threw the error @SteveSandersonMS mentioned above.

An unhandled exception has occurred: StaticInjectorError[InjectionToken Application Initializer -> InjectionToken DocumentToken]: 
  StaticInjectorError(Platform: core)[InjectionToken Application Initializer -> InjectionToken DocumentToken]: 
    Right-hand side of 'instanceof' is not an object
      TypeError: StaticInjectorError[InjectionToken Application Initializer -> InjectionToken DocumentToken]: 
 

@naveedahmed1
Copy link

@filipesilva can you please share if there is any update on this?

@naveedahmed1
Copy link

@hansl should we expect this and #8900 to be solved in V6?
If this could be fixed, it would really help developers using Angular and SSR with Windows technologies (.net core) or hosting Angular apps on Windows servers/IIS/Kestrel.

@asadsahi
Copy link

asadsahi commented Feb 10, 2018

Personally I would love to have this feature available as soon as possible, but for now I have stopped wasting time and effort on making angular apps universal.
Right now the stability of angular universal is good for demo purposes but as soon as you start expanding application to a good scale you start realising the amount of energy required to maintain those features is quite large. I hope in coming days DX will improve to implement SSR in angular apps and it will be easier like angular cli has done good job developing/building angular apps.

@filipesilva filipesilva added comp: cli/build freq1: low Only reported by a handful of users who observe it rarely severity5: regression and removed needs: investigation Requires some digging to determine if action is needed labels Feb 14, 2018
@speige
Copy link

speige commented Feb 22, 2018

+1

@lankaapura
Copy link

lankaapura commented Mar 15, 2018

seems still not working with the latest release. Does anyone have an alternative for this? My CI/CD pipeline is taking 30+ minutes to complete due to this issue and #6795.

@speige
Copy link

speige commented Mar 15, 2018

@SteveSandersonMS
I cloned your repo at https://github.com/SteveSandersonMS/angular-bundledependencies-repro and found a workaround.

If you change this line in package.json

"build:client-and-server-bundles:prod": "ng build --prod && ng build --prod --app 1 --output-hashing=false --bundle-dependencies=all",

with this

"build:client-and-server-bundles:prod": "ng build --prod && ng build --build-optimizer --aot --environment prod --app 1 --output-hashing=false --bundle-dependencies=all",

everything works.

I'm not sure what's different between "--prod" and "--build-optimizer --aot --environment prod", but I think they're almost the same. Also, it's only necessary for the server-side version of the code so if some random optimization is missing it might be okay.

@naveedahmed1
Copy link

@filipesilva @hansl @Brocco can you please share if there is any update on this?

@naveedahmed1
Copy link

@speige can you please compare the size of the bundles with --prod and --build-optimizer --aot --environment prod ?

@speige
Copy link

speige commented Apr 9, 2018

Results of "ng build --prod --app 1 --output-hashing=false --bundle-dependencies=all" & "webpack --config webpack.server.config.js --progress --colors"
image

Results of "ng build --build-optimizer --aot --environment prod --app 1 --output-hashing=false --bundle-dependencies=all" & "webpack --config webpack.server.config.js --progress --colors"
image

It appears that the --prod bundle is much smaller, but it's also the broken one. Maybe treeshaking was overzealous? Since this is the server build, the larger size shouldn't be an issue. Also, if it's removing the need to copy the entire node_modules folder (or run npm install on my server), I'd happily take the larger size.

Note: There is a separate issue logged about the yellow warning, but I've found in my app that everything still works, so I just ignore the warning.

@naveedahmed1
Copy link

Thanks for sharing this, I believe the size of the bundle should have an effect on the memory consumption on server as well for heavy traffic websites. For developers using .net technologies, this requires immediate attention from Angular CLI team, its already been ~5 months.

@speige
Copy link

speige commented Apr 9, 2018

Fyi, I've also tried this on Angular 6 RC & the same issue still exists. The format of angular-cli.json has changed, but the issue & workaround are still the same.

broken:

	"ssr": {
      "root": "",
      "projectType": "application",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist/ssr",
            "main": "src/main.server.ts",
            "tsConfig": "src/tsconfig.server.json"
          },
          "configurations": {
            "production": {
              "optimization": true,
              "outputHashing": "none",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
			"bundleDependencies": "all"
            }
          }
        }
      }
    }

working:

	"ssr": {
      "root": "",
      "projectType": "application",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist/ssr",
            "main": "src/main.server.ts",
            "tsConfig": "src/tsconfig.server.json"
          },
          "configurations": {
            "production": {
              "optimization": false,
              "outputHashing": "none",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
			"bundleDependencies": "all"
            }
          }
        }
      }
    }

Only difference is optimization: true/false. Without bundleDependencies, both true/false work, with bundleDepencencies: all only optimization: false works.

Also, same error during ng serve (Right-hand side of 'instanceof' is not an object) & same yellow circular dependency warning occur [which I'm ignoring, since it still works]. Although if I remember correctly the yellow warning was about the express/view.js file instead of core.umd.js but that may be because I was on a completely different repo, not Steve's angular-bundledependencies-repro

@naveedahmed1
Copy link

@hansl @filipesilva what if we update the Uglify settings to preserve the class names for server builds? I believe this would be a better solution than to turn mangle off. What do you think?

@naveedahmed1
Copy link

@filipesilva @hansl did you get a chance to check my last comment of Jun 10?

@hansl hansl assigned hansl and vikerman and unassigned hansl Sep 28, 2018
@hansl hansl added the needs: discussion On the agenda for team meeting to determine next steps label Jan 10, 2019
@ngbot ngbot bot added this to the needsTriage milestone Jan 10, 2019
@dominikfoldi
Copy link

This is a huge issue because lots of people wants to use Angular Universal with ASP.NET Core backend. Could you please prioritize this to the top?

@stefankip
Copy link

I've tried every suggestion in this thread, but still run into this issue:

Error: No NgModule metadata found for '[object Object]'. at NgModuleResolver.resolve (C:\project\node_modules\@angular\compiler\bundles\compiler.umd.js:20020:27) at CompileMetadataResolver.getNgModuleMetadata (C:\project\node_modules\@angular\compiler\bundles\compiler.umd.js:18662:47) at JitCompiler._loadModules (C:\project\node_modules\@angular\compiler\bundles\compiler.umd.js:26085:55) at JitCompiler._compileModuleAndComponents (C:\project\node_modules\@angular\compiler\bundles\compiler.umd.js:26066:40) at JitCompiler.compileModuleAsync (C:\project\node_modules\@angular\compiler\bundles\compiler.umd.js:26026:41) at CompilerImpl.compileModuleAsync (C:\project\node_modules\@angular\platform-browser-dynamic\bundles\platform-browser-dynamic.umd.js:202:35) at C:\project\node_modules\@nguniversal\express-engine\bundles\express-engine.umd.js:110:29 at new ZoneAwarePromise (C:\project\node_modules\zone.js\dist\zone-node.js:910:29) at getFactory (C:\project\node_modules\@nguniversal\express-engine\bundles\express-engine.umd.js:96:16) at C:\project\node_modules\@nguniversal\express-engine\bundles\express-engine.umd.js:75:17

@vikerman
Copy link
Contributor

vikerman commented May 24, 2019

We have a fix to the ng add schematics for 8.0 for this.(PR above)

But to manually fix your existing project - Move all Angular related imports in server.ts as re-exports in main.server.ts and then you can use --bundleDependencies all. Would also need to change the top-level webpackconfig to main.ts external to server.ts builds.

Shown in example repo here -
vikerman/v8-lazy@515239b

With this you should need to deploy only dist/server.js and dist/server/main.js and not node_modules.

@vikerman
Copy link
Contributor

@dominikfoldi @stefankip - can you try the suggestion above?

@dominikfoldi
Copy link

@vikerman our Angular project is not ejected so I cannot modify the webpack.config. I can wait until Angular 8. Glad to hear that you have a fix!

@vikerman
Copy link
Contributor

@dominikfoldi - Not sure what your setup is. But essentially the fix would be to move all references to @angular and @nguniversal to the main.server.ts and bundle it once there and use only re-exports from the express(or whichever) entry point. Otherwise you would end up with two copies of Angular and things will start to fail randomly.

@ErazerBrecht
Copy link

@vikerman
I can confirm the 'fix' works ;)
The only problem is that I now have the original error:

TypeError: StaticInjectorError[InjectionToken DocumentToken]: 
  StaticInjectorError[InjectionToken DocumentToken]: 
    Right-hand side of 'instanceof' is not an object

Like already said in this issue disabling optimization fixes this.
I'll do this for now until this issue is completely fixed

Again thx for your effort & the example repo

@stefankip
Copy link

@vikerman awesome, works perfectly! Thank you very much!

@filipesilva filipesilva removed the needs: discussion On the agenda for team meeting to determine next steps label Jun 27, 2019
@vikerman
Copy link
Contributor

Closing this as we have some reports that this works.

@naveedahmed1
Copy link

@vikerman I think the issue still exists "bundleDependencies": "all", works only when "optimization": false, but when "optimization": true, it throws below error

NodeInvocationException: StaticInjectorError(AppServerModule)[InjectionToken Application Initializer -> InjectionToken DocumentToken]: 
StaticInjectorError(Platform: core)[InjectionToken Application Initializer -> InjectionToken DocumentToken]: 
Right-hand side of 'instanceof' is not an object
TypeError: StaticInjectorError(AppServerModule)[InjectionToken Application Initializer -> InjectionToken DocumentToken]: 
StaticInjectorError(Platform: core)[InjectionToken Application Initializer -> InjectionToken DocumentToken]: 
Right-hand side of 'instanceof' is not an object

@naveedahmed1
Copy link

@vikerman how about this #8616 (comment) ?

@naveedahmed1
Copy link

Ok I have found one solution.

  1. Disable optimizations i.e. "optimization": false, in angular.json file.
  2. Enable bundle dependencies "bundleDependencies": "all", in angular.json file.
  3. Build your bundle (in my case npm run build:ssr). This will generate a large bundle., in my case the size of the bundle is 9.89Mb with IVY Enabled.
  4. Install terser plugin npm install terser -g
  5. Run terser to minify bundle terser dist-server/main.js -o dist-server/main.js -c -m --keep-fnames. The compressed build in my case is of 3.9mb i.e. ~60% reduction.

Please do share feedback and suggestions for further improvements.

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Oct 1, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: devkit/build-angular freq1: low Only reported by a handful of users who observe it rarely P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful severity5: regression
Projects
None yet
Development

No branches or pull requests