2

I am developing a SPA which contains multiple dashboards. Each dashboard is a set of Web Components respecting a layout. These components are not known statically. They are determined at run-time.

What I want to achieve is the following scenario:

  1. Application starts.
  2. The application performs XHR to fetch dashboards representations from a REST service.
  3. User sees dashboards listed by name.
  4. User clicks on a dashboard item. (say dashboard 1)
  5. The application determines the necessary components needed to load dashboard 1 (web components)
  6. Load web components and their dependencies.

I am pretty aware of loading web components dynamically which was answered here

My actual problem is

how to load a web component with their dependencies at run-time without having to load duplicate dependencies?

Are there any module formats or practices to follow when packaging the web components?

Hasitha Jayawardana
  • 2,326
  • 4
  • 18
  • 36
Anis Tissaoui
  • 834
  • 1
  • 7
  • 26
  • There's [dynamic import](https://stackoverflow.com/questions/35914712/es6-conditional-dynamic-import-statements) proposal, [already implemented in some browsers](https://caniuse.com/#feat=es6-module-dynamic-import), which seems to fit your use case – artem Jul 10 '19 at 20:58
  • IIRC webpack supports multiple entry points, and multiple component bundles, and figures out duplicate-free dependencies for you. – Bergi Jul 11 '19 at 16:57

1 Answers1

1

If you have a mapping from dashboard to the module that implements it, then you can just dynamic import() the necessary module. The JS module system will take care of not loading modules that have already been loaded, so common dependencies like lit-element will only be loaded once.

This deduplication works based on URL, so you have to make sure that you have one copy of a dependency installed via npm. npm dedupe will attempt to deduplicate your node_modules/ folder, and npm ls will let you see the dependency tree.

All current browsers support dynamic import(), and most bundlers do too - as long as the argument is a string constant. This means that you can't compute the module URL based on the dashboard if you want to use a bundler. You need something like:

const dashboardLoaders = {
  'dash-1': () => import('./dashboards/dash-1.js'),
  'dash-2': () => import('./dashboards/dash-2.js'),
  // etc...
};
Justin Fagnani
  • 10,483
  • 2
  • 27
  • 37