just-jeb/angular-builders

splitChunks scripts not added in html

Closed this issue · 11 comments

Describe the Bug

When optimisation/splitChunks settings applied the scripts files get split properly but the scripts tags don't get added in index.html file.


optimization: {
    minimize: true,
    removeEmptyChunks: false,
    mergeDuplicateChunks: false,
    splitChunks: {
      minSize: 0,
      maxSize: 4500000,
      minChunks: 1,
      automaticNameDelimiter: '-',
      hidePathInfo: true
    }
  }

Minimal Reproduction

You will find the script fiels are generated in output folder but the index.html missing the required <script> tags.

Expected Behavior

As the script files get split into multiple, the files should be referenced in html file

Screenshots

If applicable, add screenshots to help explain your problem.

Environment


Libs
- @angular/core version: 9.0.0
- @angular-devkit/build-angular version: >=0.900.0 < 0.1000.0
- @angular-builders/{the name of the builder} version: 9.1.0

For Tooling issues:
- Node version: 12.16.2
- Platform:  Windows


That's interesting. At first I thought it's related to the usage of HtmlWebpackPlugin because the script tags are included in footer.html, but when I remove it the result is still the same. Besides, when I run ng serve they are added. With ng build they are not.

image

Need to dig into Angular CLI code see why it happens. Can you confirm ng serve works for you?

I'm going to need a clear reproduction. Would you mind creating a brand new app with minimal splitChunks config?

I've used full-cycle-app and cloned into https://github.com/ranaictiu/splitchunk-mininal-config. Looks like the minimal option you need to reproduce is the maxSize as below:


  optimization: {
    splitChunks: {
      maxSize: 4500000,
    }
  }

Full cycle app has a lot of noice. A clean reproduction with ng new would be really helpful.

My bad. This time used an angular boilerplate template - https://github.com/ranaictiu/angular-boilerplate-splitchunks

Does anyone got a solution for this? I am facing the same problem

Can you provide minimal reproduction?

Can you provide minimal reproduction?

@just-jeb
https://github.com/songzhj/split-chunk-demo
Same problem, here is a reproduction.
You can run npm run start(correct inject in html) and npm run build:prod(wrong in html) reproduce it.
Looking forward to some solution. :)

Just wanted to check if there is any update on this. I am facing the same problem on using '@angular-builders/custom-webpack@9.2.0' with angular 9.

I am trying to chunk 'vendor.[hash].js' using the below config

splitChunks: {
            cacheGroups: {
                vendor: {
                    minSize: 1000000,
                    maxSize: 1000000
                }
            }
        }

Even though the chunks do get generated, the script tag entries for these are not updated in 'index.html'.

Following approach working for me:
I am chunking vendor.js for my build & including back in index.html

My Custom Webpack Configutation entry for chunking vendor.js

. . .
        splitChunks: {
            automaticNameDelimiter:'-',
            cacheGroups: {
                vendor: {
                    minSize: 1000000,
                    maxSize: 1000000
                }
            }
        }
. . .

Custom Builder has an additional proerty called indexTransform, which can used to transform index.html entries

Ref: https://github.com/just-jeb/angular-builders/blob/9.x.x/packages/custom-webpack/README.md#index-transform

Updated angular.json

architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "./wm-custom-webpack.config.js"
            },
            "indexTransform":"./index-html-transform.js",
       . . .

code of index-html-transform.js


const fs = require('fs');
const node_path = require('path');

const addScript = (path)=>{
    return `<script src="${path}"></script>`
}
module.exports = (targetOptions, indexHtml) =>{
    const vendor_path = node_path.resolve(__dirname+`/dist`);
    let vendorScripts = ``;
    fs.readdirSync(vendor_path).forEach((file)=>{
        if(file.indexOf('vendor-')===0){
                vendorScripts+=addScript(file);
        }
    });

    const mainScriptStr = `<script src="ng-bundle/main`;
    const mainIndex = indexHtml.indexOf(mainScriptStr);
    
    return `${indexHtml.slice(0,mainIndex)}
            ${vendorScripts}
            ${indexHtml.slice(mainIndex)}`;
}

Hopefully this should help.

Regards,
Subodh Kumar

Thanks Subodh,
Slight modification of the vendor_path worked for me with Angular 10.x as the build adds a dir with the project name in the dist folder
const vendor_path = node_path.resolve(__dirname+/dist/${targetOptions.project});

Steve Farwell