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

Why does prerendering create NamedChunks? #17021

Closed
2 of 6 tasks
scurk1415 opened this issue Feb 14, 2020 · 26 comments · Fixed by #17515
Closed
2 of 6 tasks

Why does prerendering create NamedChunks? #17021

scurk1415 opened this issue Feb 14, 2020 · 26 comments · Fixed by #17515

Comments

@scurk1415
Copy link

🐞 Bug report

What modules are related to this issue?

  • aspnetcore-engine
  • builders
  • common
  • express-engine
  • hapi-engine
  • module-map-ngfactory-loader

Is this a regression?

I don't know cause i was not using the previous version

Description

Prerendering always creates named chunks. If i run ng run app:build:production everything builds correctly https://prnt.sc/r2dytb , but if i run it with ng run app:prerender:production the lazy loaded modules are still named based on the module name https://prnt.sc/r2dzp1

🔬 Minimal Reproduction

  1. Create angular app (v9)
  2. ng add @nguniversal/express-engine
  3. create a module to lazy load
  4. run ng run app:prerender:production

🌍 Your Environment


Angular CLI: 9.0.2
Node: 12.14.1
OS: win32 x64

Angular: 9.0.1
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.2
@angular-devkit/build-angular     0.900.2
@angular-devkit/build-optimizer   0.900.2
@angular-devkit/build-webpack     0.900.2
@angular-devkit/core              9.0.2
@angular-devkit/schematics        9.0.2
@angular/cli                      9.0.2
@ngtools/webpack                  9.0.2
@nguniversal/builders             9.0.0
@nguniversal/common               9.0.0
@nguniversal/express-engine       9.0.0
@schematics/angular               9.0.2
@schematics/update                0.900.2
rxjs                              6.5.4
typescript                        3.7.5
webpack                           4.41.2


@wagnermaciel
Copy link
Contributor

@alan-agius4 This is interesting because the browser target we are passing to the prerender builder is app:build:production. See add/index.ts. Do you have any idea why this happens?

@alan-agius4
Copy link
Collaborator

Will need some debugging, I am also noticing that in one of screenshots sources are emitted while in the other screenshots they are not.

@alan-agius4
Copy link
Collaborator

@scurk1415
Copy link
Author

scurk1415 commented Feb 15, 2020

I also noticed that the file sizes are not the same (which they probably should be) so i am guessing that it runs the serverTarget instead of browserTarget.

This is the output for the files if i run it with the serverTarget configuration (https://prnt.sc/r2mwif). Which is close to being the same as on my second screenshot when i ran app:prerender:production https://prnt.sc/r2dzp1 (based on file size)

@alan-agius4 alan-agius4 self-assigned this Feb 18, 2020
@alan-agius4
Copy link
Collaborator

I looked at this briefly and it seems that this is a bug related to Angular Devkit architect.

Did a small test to confirm

I did a custom builder that calls the browser target;

const { createBuilder, targetFromTargetString } = require("@angular-devkit/architect");

async function execute(options, context) {
  const browserTarget = targetFromTargetString(options.browserTarget);
  console.log(
    'getTargetOptions', await context.getTargetOptions(browserTarget)
  );

  const browserTargetRun = await context.scheduleTarget(browserTarget);
  await browserTargetRun.result;
  await browserTargetRun.stop();

  return { success: true };
}

exports.default = createBuilder(execute);

Executing the above will return the below (Note: while sourceMaps is false, they are still generated)

getTargetOptions {
  outputPath: 'dist/uni-pre/browser',
  index: 'src/index.html',
  main: 'src/main.ts',
  polyfills: 'src/polyfills.ts',
  tsConfig: 'tsconfig.app.json',
  aot: true,
  assets: [ 'src/favicon.ico', 'src/assets' ],
  styles: [ 'src/styles.css' ],
  scripts: [],
  fileReplacements: [
    {
      replace: 'src/environments/environment.ts',
      with: 'src/environments/environment.prod.ts'
    }
  ],
  optimization: true,
  outputHashing: 'all',
  sourceMap: false,
  extractCss: true,
  namedChunks: false,
  extractLicenses: true,
  vendorChunk: false,
  buildOptimizer: true,
  budgets: [
    { type: 'initial', maximumWarning: '2mb', maximumError: '5mb' },
    {
      type: 'anyComponentStyle',
      maximumWarning: '6kb',
      maximumError: '10kb'
    }
  ]
}
Generating ES5 bundles for differential loading...
ES5 bundle generation complete.

chunk {3} polyfills-es5.041738d66a3982520e90.js, polyfills-es5.041738d66a3982520e90.js.map (polyfills-es5) 127 kB [initial] [rendered]
chunk {2} polyfills-es2015.db39b23daa8851ccf344.js, polyfills-es2015.db39b23daa8851ccf344.js.map (polyfills) 35.7 kB [initial] [rendered]
chunk {0} runtime-es2015.0811dcefd377500b5b1a.js, runtime-es2015.0811dcefd377500b5b1a.js.map (runtime) 1.51 kB [entry] [rendered]
chunk {0} runtime-es5.0811dcefd377500b5b1a.js, runtime-es5.0811dcefd377500b5b1a.js.map (runtime) 1.51 kB [entry] [rendered]
chunk {1} main-es2015.4da5b65032ea1b50beac.js, main-es2015.4da5b65032ea1b50beac.js.map (main) 27.1 kB [initial] [rendered]
chunk {1} main-es5.4da5b65032ea1b50beac.js, main-es5.4da5b65032ea1b50beac.js.map (main) 27.3 kB [initial] [rendered]
chunk {5} vendor-es2015.126aaec3f9743611b6ec.js, vendor-es2015.126aaec3f9743611b6ec.js.map (vendor) 215 kB [initial] [rendered]
chunk {5} vendor-es5.126aaec3f9743611b6ec.js, vendor-es5.126aaec3f9743611b6ec.js.map (vendor) 260 kB [initial] [rendered]
chunk {4} styles.8547d00c5fcaf5c47c33.css, styles.8547d00c5fcaf5c47c33.css.map (styles) 0 bytes [initial] [rendered]
Date: 2020-02-19T08:46:11.724Z - Hash: a4caaf1c847b94bf8394 - Time: 24565ms

The interesting part is that if we omit calling context.getTargetOptions prior to context.scheduleTarget the result is different,.

Let update our builder to;

const { createBuilder, targetFromTargetString } = require("@angular-devkit/architect");

async function execute(options, context) {
  const browserTarget = targetFromTargetString(options.browserTarget);
  // console.log(
  //   'getTargetOptions', await context.getTargetOptions(browserTarget)
  // );

  const browserTargetRun = await context.scheduleTarget(browserTarget);
  await browserTargetRun.result;
  await browserTargetRun.stop();

  return { success: true };
}

exports.default = createBuilder(execute);

Here's the result;

Generating ES5 bundles for differential loading...
ES5 bundle generation complete.

chunk {2} polyfills-es2015.ca64e4516afbb1b890d5.js (polyfills) 35.6 kB [initial] [rendered]
chunk {3} polyfills-es5.277e2e1d6fb2daf91a5c.js (polyfills-es5) 127 kB [initial] [rendered]
chunk {0} runtime-es2015.0811dcefd377500b5b1a.js (runtime) 1.45 kB [entry] [rendered]
chunk {0} runtime-es5.0811dcefd377500b5b1a.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main-es2015.be16c3d420978605e6ed.js (main) 216 kB [initial] [rendered]
chunk {1} main-es5.be16c3d420978605e6ed.js (main) 258 kB [initial] [rendered]
chunk {4} styles.3ff695c00d717f2d2a11.css (styles) 0 bytes [initial] [rendered]
Date: 2020-02-19T08:49:18.308Z - Hash: e6d6b1251cfe649fbfa7 - Time: 20023ms

@alan-agius4
Copy link
Collaborator

Transferring to the CLI repo and chiming in @clydin

@Mr-Plutus
Copy link

Now in prerender there is only dev assembly, and it is needed only for production

@scurk1415
Copy link
Author

So any update on this?

@s2young
Copy link

s2young commented Mar 3, 2020

Same issue. Also ngsw-worker.js isn't getting built during prerender, where it is within ng build.

@Exocomp
Copy link

Exocomp commented Mar 6, 2020

Running into the same issue, appears it is generating a dev build for some reason. My work around, although very ugly is to build for prerender then build for prod and copy over the prerender html files over to the prod build. Then update the bundle paths in the html files for prod. Very ugly but only work around I could think of for right now just to have a solution.

@skyquartam
Copy link

Whatching on this beacuse this makes impossible to use ng service worker with prerender (So bad) @Exocomp please can you post some snippets on how to do your workaround?

@Exocomp
Copy link

Exocomp commented Mar 19, 2020

@skyquartam

It's pretty ugly (I stress it again) but here is the general idea, however, I recommend just waiting for an actual fix:

  • Build for prerender
    • Afterwards rename the dist folder to something else (ex. dist_prerender)
  • Build for prod
    • Afterwards copy the .html files from dist_prerender over to dist
    • For each .html file modify the previous bundle paths to the prod bundle paths

Since you're working with a service worker you probably will have to update the service worker json file (ngsw.json) with the new file hashes (sha-1) or I think it will break how sw works.

@trympet
Copy link

trympet commented Mar 31, 2020

Quick and dirty workaround if your dev workflow doesn't depend on named chunks:

  1. Open "node_modules/@angular-devkit/build-angular/src/angular-cli-files/plugins/named-chunks-plugin.js"
  2. Comment out "dependency.block.chunkName = Template.toPath(dependency.request);" (line 26)

This will prevent the named chunks plugin from renaming dependencies.

This was referenced Apr 27, 2020
@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 May 23, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.