angularwebpackgoogle-chrome-extensionfirefox-addon

When is index.html generated in Angular build?


I am trying to figure out when in the build phase Angular generates the index.html file so that I can move it to another directory afterwards. I noticed that when I am trying to copy the files using WebpackShellPlugin, index.html is not in the dist/projectToMove directory during both onBuildEnd and onBuildExit phases.

The Webpack config is as follows:

const WebpackShellPlugin = require('webpack-shell-plugin');

module.exports = {
  plugins: [
    new WebpackShellPlugin({
      onBuildEnd: [
        'echo "Files at end of compilation: "',
        'ls ./dist/apps/curemedit/'
      ],
      onBuildExit: [
        'echo "Copying Popup App contents..."',
        'ls ./dist/apps/curemedit/',
        'cp -rvf ./dist/apps/curemedit/* ./dist/apps/'
      ],
      safe: true
    })
  ]
};

Output of ls for both cases:

favicon.ico
main.js
main.js.map
manifest.json
polyfills.js
polyfills.js.map
runtime.js
runtime.js.map
styles.js
styles.js.map
vendor.js
vendor.js.map

I have a multi-application Angular workspace for a browser extension. projectToMove is the one that will be used for the popup display of this extension. I am trying to move the contents of its corresponding folder in dist one level up so that it is together with the manifest file in the extension's root directory.

My guess was that this delay in generating the index.html file is due to ES5 bundle generation for differential loading. I have set Chrome >= 61 in my browserslist file for this project but it turns out that this does not make a difference.

What would be the correct way to grab the index.html file? Should I be watching the folder for longer with a node script or is there a more elegant solution?

Additional info about my use case:

I am building a browser extension. Before when it was a single project angular workspace, live reload worked using webpack-extension-reloader as explained here. Now that I have two separate angular projects for the popup display and the options page, both of those two project's corresponding index.html pages expect the js and css files in the extension root folder. So now I have an ugly hack using CopyPlugin, WebpackShellPlugin and some sad sed.

Here are the added build config files:

ext.config.js:

const CopyPlugin = require('copy-webpack-plugin');
const WebpackShellPlugin = require('webpack-shell-plugin');

module.exports = {
  entry: {
    background: './src/chrome/background.ts'
  },
  plugins: [
    new CopyPlugin([
      {
        from: './src/chrome/manifest.json',
        to: '../manifest.json'
      }
    ]),
    new WebpackShellPlugin({
      onBuildExit: [
        // Rename sourcemaps, js and css files -> undo chunks' renamings -> move them to extension root
        'echo "Moving Options App Contents..."',
        'for f in ./dist/apps/proj1/*.js.map; do mv "$f"  "${f%.js.map}.proj1.js.map"; done ',
        'for f in ./dist/apps/proj1/*.js; do mv "$f"  "${f%.js}.proj1.js"; done ',
        'mv ./dist/apps/proj1/styles.css ./dist/apps/proj1/styles.proj1.css',
        'for f in ./dist/apps/proj1/[0-9].proj1.js; do mv "$f" "${f%.proj1.js}.js"; done ',
        'for f in ./dist/apps/proj1/workspace*.proj1.js; do mv "$f" "${f%.proj1.js}.js"; done ',
        'for f in ./dist/apps/proj1/workspace*.proj1.js.map; do mv "$f" "${f%.proj1.js.map}.js.map"; done ',
        'mv -v ./dist/apps/proj1/* ./dist/apps/'
      ],
      safe: true
    })
  ]
};

ext.popup.js:

const WebpackShellPlugin = require('webpack-shell-plugin');

module.exports = {
  plugins: [
    new WebpackShellPlugin({
      onBuildExit: [
        'echo "Moving Popup App Contents..."',
        'for f in ./dist/apps/proj2/*.js.map; do mv "$f"  "${f%.js.map}.proj2.js.map"; done ',
        'for f in ./dist/apps/proj2/*.js; do mv "$f"  "${f%.js}.proj2.js"; done ',
        'mv ./dist/apps/proj2/styles.css ./dist/apps/proj2/styles.proj2.css',
        'mv -v ./dist/apps/proj2/* ./dist/apps/'
      ],
      safe: true
    })
  ]
};

sed.sh:

#!/bin/sh

sed -i 's/.js/.proj1.js/g' ./dist/apps/proj1/index.html
sed -i 's/styles.css/styles.proj1.css/g' ./dist/apps/proj1/index.html
sed -i 's/.js/.proj2.js/g' ./dist/apps/proj2/index.html
sed -i 's/styles.css/styles.proj2.css/g' ./dist/apps/proj2/index.html

package.json:

"build": "rm -rf ./dist/ && ng build proj1 && ng build proj2 && ./sed.sh",
"buildprod": "rm -rf ./dist/ && ng build proj1 --prod && ng build proj2 --prod && ./sed.sh"

Solution

  • I don't fully understand your use case but hopefully this helps.

    The Angular CLI allows to configure the index property. By default this is only a path which specifies where the index.html file is in your src directory. The output path will then be the same as the input path. But the CLI also accepts an object which specifies the input path and the output path.

    The property is deeply nested in the angular.json file. In a newly generated application it's located at projects > project-name > architect > build > index.

    "index": {
        "input": "src/index.html",
        "output": "../index.html"
    }
    

    This will place the index.html file one level above the other files. Unfortunately this will not alter the references to the other files inside the index.html file. This still needs to be done outside. I think this is a bug and therefore created a bug report.