single-spa / single-spa-angular

Helpers for building single-spa applications which use Angular
Apache License 2.0
198 stars 78 forks source link

Custom webpack splitChunks #105

Closed quocnt closed 4 years ago

quocnt commented 4 years ago

Hi, I just added this custom webpack script on extra-webpack.config.js for caching common framework and angular library.

const singleSpaAngularWebpack = require('single-spa-angular/lib/webpack').default

module.exports = (angularWebpackConfig, options) => {
  let singleSpaWebpackConfig = singleSpaAngularWebpack(angularWebpackConfig, options);

  // optimize libs
  singleSpaWebpackConfig.optimization.splitChunks = {
    cacheGroups: {
      framework: {
        name: 'framework',
        chunks: 'initial',
        test: /[\\/]angular\d?-framework[\\/]/,
        priority: 5,
      },
      angular: {
        name: 'angular',
        chunks: 'initial',
        test: /[\\/]@angular[\\/]/,
        priority: 5,
      }
    }
  };

  // Feel free to modify this webpack config however you'd like to
  return singleSpaWebpackConfig;
}

seem like it's error. If I remove it. It will work. So can we do that or anyway ? thanks

image

joeldenning commented 4 years ago

Webpack has two ways of doing code splits: 1) dynamic import and entry points, 2) optimizations block in webpack config. Only option 1 works with single-spa. This does not mean that your bundle is un-optimized. It’s just different approaches to bundling.

The reason that single spa requires option 1 is that single spa applications do not own their own html file, but rather share it with all the other applications. The webpack optimizations config creates js bundles that afaik can only be included via a script tag in the html file, and are not lazy loaded or dynamically loaded when you load the main bundle.

Closing this because I think I’ve answered the question, but feel free to comment further or reopen with more discussion.

quocnt commented 4 years ago

Hi @joeldenning , thanks for your explanation. image

In my projects, shared as framework, app1 and app2 are using shared common modules so I just though split chunks then replace script html tag from app1, app2 to the same url might cache it.

In my case, is there any way if we must to use option 1 to avoid duplicated code ( packages like @angular/core{common, form, ...} and shared module ) and reload when we switch between apps ?

p/s : Sorry for my english

joeldenning commented 4 years ago

Interesting, thanks for the diagram and explanation. I would not recommend using commons chunks plugin to share between different bundles. Instead I would use in-browser ES modules in your import map.

In other words, make all of the shared things (like @angular/core) be in your import map. Then make them webpack externals in each angular application.

friendly-tech commented 4 years ago

@joeldenning - How do you share these via import map, there is plenty of info around making your micro front ends use externals, but no info on how to actually share those modules/externals from the host app..

Do we use a public CDN or is there a way to bundle these into host app and expose them to be comsumed by the micro front ends?

What do you actually put into you import-map to make them available to micro front ends?

joeldenning commented 4 years ago

One thing to note is that Ivy Compiler strictly disallows and discourages sharing of the core libraries. So if you're using Angular 9 + Ivy, you won't be able to do it. More info at https://twitter.com/Joelbdenning/status/1253781652486017024.

Here are some resources and examples of how to share dependencies with import maps:

There's no officially supported Angular example of it yet, although there hopefully will be soon. The examples linked to above show how to do it with Vue.