angular/angular-cli

webpack-bundle-analyzer not working correctly with the latest cli 1.3.0-beta.1

Closed this issue ยท 25 comments

- [ x] bug report

Versions.

@angular/cli: 1.3.0-beta.1
node: 7.8.0
os: win32 x64
@angular/animations: 4.3.1
@angular/common: 4.3.1
@angular/compiler: 4.3.1
@angular/core: 4.3.1
@angular/forms: 4.3.1
@angular/http: 4.3.1
@angular/platform-browser: 4.3.1
@angular/platform-browser-dynamic: 4.3.1
@angular/router: 4.3.1
@angular/cli: 1.3.0-beta.1
@angular/compiler-cli: 4.3.1
@angular/language-service: 4.3.1

webpack-bundle-analyzer: "2.8.3", 
webpack: "3.1.0", 
@ngtools/webpack: "1.6.0-beta.1"

Repro steps.

ng new stats-app
cd stats-app && yarn add webpack-bundle-analyzer

modify package.json by adding a script:
"analyze": "ng build --prod --stats-json && webpack-bundle-analyzer dist/stats.json"

npm run analyze

Not showing bundles details/content:
image

Desired functionality.

Should display bundles details/content

image

Mention any other details that might be useful.

All working with angular cli 1.0.0 that I was using before

@angular/cli: 1.0.0
node: 7.8.0
os: win32 x64
@angular/common: 4.3.1
@angular/compiler: 4.3.1
@angular/core: 4.3.1
@angular/forms: 4.3.1
@angular/http: 4.3.1
@angular/platform-browser: 4.3.1
@angular/platform-browser-dynamic: 4.3.1
@angular/router: 4.3.1
@angular/cli: 1.0.0
@angular/compiler-cli: 4.3.1

webpack-bundle-analyzer: "2.8.3", 
webpack: "2.2.1",
@ngtools/webpack: "1.3.0"

I can confirm the issue. Haven't been able to track down the problem though

My guess would be an incompatibility with scope hoisting.

If the contents of the bundles is the goal, you can turn on sourcemaps and use sourcemap explorer.

Just tested with rc.0 and still an issue.

I understand this happens, but I don't think this is an issue in Angular CLI. We just pass on the stats json option into webpack, and then webpack-bundle-analyzer is used to analyse it. The CLI doesn't do anything at all with that file.

Have you tried opening an issue in https://github.com/th0r/webpack-bundle-analyzer or https://github.com/webpack/webpack instead? If it's a matter of updating our version of either I'm happy to do so.

There is an opened issue reporting for CLI 1.2.6, so probably not related to changes on 1.3.

My guess would be an incompatibility with scope hoisting.

Yes, this is very likely to be the issue with webpack-bundle-analyzer. As it happens, webpack-bundle-analyzer is not yet compatible with webpack's scope hoisting.

We're figuring out a solution for this, but for now, drilling deeper into the bundle isn't possible.

You could try to view the "stat" size, as it doesn't rely on parsing the generated bundle (where, due to scope hoisting, we've lost the details of module boundaries)

@ShadowManu I think there's something odd with the setup reported in webpack-contrib/webpack-bundle-analyzer#106, since it does mention CLI 1.2.6 but also Webpack 3.4.1, but CLI 1.2.6 is limited to webpack 2.x.

@valscion heya, thanks for chiming in! If there something we can do on Angular CLI to help please let me know.

Even using sourcemaps, using the latest cli (1.3.0.rc3), all information about the vendor libs is gone

The sourcemaps bit is a bug with the --build-optimizer flag and being tracked in #7093.

@filipesilva one possibility would be to configure the builds to not use scope hoisting when you want to analyze the bundle contents with webpack-bundle-analyzer. This way the plugin would be able to show you the sizes of each modules separately.

I'm not sure if we're able to even figure out the missing information after the scope hoisting, but I haven't yet looked into it that much.

th0r commented

Hmm, resulting stats file has very strange structure.
@filipesilva Could you provide some insides about what have been changed in webpack configuration in ng-cli 1.3.0-rc.3?

The fact is from @angular/cli@1.2.6 to @angular/cli@1.3.0-rc.3, the webpack version is upgraded from ~2.4.0 to ~3.4.0. There are breaking changes inside webpack which affect @angualr/cli.

As @valscion said, a temporary solution is to provide a flag in @angular/cli to turn off webpack.optimize.ModuleConcatenationPlugin() at here

sorry, simple comment out the plugin doesn't work. There are more things to reconfig.

Even without prod mode, like ng build --no-progress --stats-json, webpack-bundle-analyzer doesn't make it out.

th0r commented

@e-cloud I use Webpack 3.4 with ModuleConcatenationPlugin in one of my projects and analyzer works fine in my case.
I think it's something else.

@th0r, do you use @angular/cli? If not, it sounds may be cli has its own problem too.

th0r commented

@e-cloud No, I don't.

Yeah th0r knows webpack-bundle-analyzer better than me, and I'm thrilled to hear that ModuleConcatenationPlugin works. So there might be something else that the @angular/cli is doing.

th0r commented

@e-cloud The problem is in the stats.json structure. Normally it is something like this:

{
  // ...
  "chunks": [
    // chunks info WITHOUT modules
  ],
  "modules": [
    // list of ALL modules from ALL chunks
  ]
  // ...
}

But new ng-cli generates stats file with the following structure:

{
  // ...
  "chunks": [
    // chunks info WITH modules.
    // each chunk object has it's own "modules" property with all modules it contains
  ]
  // ...and no top-level "modules" field
}

So there is no top-level modules field, but all of them are spread across chunk objects.

The webpack stats output is highly configurable and its content can vary greatly depending on webpack command line options or programmatic usage. In this case, the verbose preset is used which seems to purposely not include the module list that the analyzer requires. (code ref)

To that end, is there a reason that the analyzer requires the presence of the top-level modules list? If the chunk modules are present, the analyzer seems to be doing extra work (code ref) filtering the entire modules list to find the modules used per asset. Also, since there is technically no guarantee that either of the module lists are present, it may be prudent to use chunk modules if available (more efficient), then the top-level modules if not, and finally display an error/warning if neither is found.

Regardless, I'll put together a PR that will make the Angular CLI use the same stat output options for the file that the current default --json webpack CLI option uses.

th0r commented

@clydin The thing is it's the first time I see that modules are located in chunk objects.
Do you use some plugin that modifies default stats structure or it can be achieved by just changing stats options?

A direct webpack function call is used to obtain the stats object. It supports several presets as well as a fine-grained object-based option argument. Oddly, the default includes both the modules and chunk modules lists; but verbose only includes chunk modules.
Here is the relevant code for the fine-grained options (and their defaults): https://github.com/webpack/webpack/blob/master/lib/Stats.js#L101

Big thanks to @clydin for the investigative work here.

Breaking webpack-bundle-analyzer was indeed a consequence of #6989 where we started using stats.toJson('verbose') instead of just stats.toJson() , subsequently fixed by #7259.

After some additional research, the CLI didn't actually break the functionality. Webpack 3 changed the verbose preset to not include the top level module list.

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.