Skip to content

Generate import maps #26316

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

Closed
anhallbe opened this issue Nov 10, 2023 · 3 comments
Closed

Generate import maps #26316

anhallbe opened this issue Nov 10, 2023 · 3 comments

Comments

@anhallbe
Copy link

anhallbe commented Nov 10, 2023

Command

build, serve

Description

Our application has a plugin system where it needs to load external modules that are not known at build-time. These external modules are often (but not always) Angular components, and they share dependencies with the application. Think:

// Application
const { PluginComponent } = await import("https://cdn/plugin.js"); // NOTE: The URL is not known at build-time


// https://cdn/plugin.js
import { Component } from "@angular/core";
@Component(/* ... */)
export PluginComponent {}

The above does not work, since there is no way for plugin.js to resolve the "@angular/core" import.

We have solved this by making sure the plugins are SystemJS modules rather than ES Modules, and they are imported with System.import() with some custom resolvers (see below).

However, we would really like to drop SystemJS and use ES modules instead. But this is not possible today.

Describe the solution you'd like

In order to load external modules that depend on bare specifiers, I think the cleanest solution would be to use Import Maps. A possible solution would be for Angular CLI to generate import maps for some chosen dependencies. Like:

angular.json

{
  "builder": "@angular-devkit/build-angular:application",
  "options": {
    "generateImportMaps": [
      "@angular/core",
      "@angular/common",
      "rxjs",
      "some-other-dependency"
    ],
  },
}

index.html

<script type="importmap">
{
  "imports": {
    "@angular/core": "/chunk-foo123.js",
    "@angular/common": "/chunk-bar456.js"
  }
}
</script>

Alternatively, there could be a way to write & use plugins for esbuild (or vite?) that does this, if it is possible to get the generated chunk name in there.

Describe alternatives you've considered

We are currently forcing the plugins to be built as SystemJS modules, and they are imported with System.import. Like:

// Application
/* Custom SystemJS resolve & instantiate with import("@angular/core") and lots of hacks */
const { PluginComponent } = await System.import("https://cdn/plugin.js");


// https://cdn/plugin.js
System.register(["@angular/core"], function (_export, _context) {
  let angularCore;
  return {
	  setters: [
		  angularCoreDep => angularCore = angularCoreDep,
	  ],
	  execute: function () {
		  _export({
			  PluginComponent: /* uses angularCore.Component and more */,
		  });
	  }
  };
});
@alan-agius4
Copy link
Collaborator

Support for imports map are something that we are looking at as part of #17556

One way to achieve this to, would be to mark these packages as external using the externalDependencies and build the import map yourself.

@dgp1130
Copy link
Collaborator

dgp1130 commented Nov 10, 2023

+1 to externalDependencies and adding your own import maps, that seems like a reasonable solution to that specific problem.

However externalizing @angular/core and using it from a dynamically loaded plugin sounds a lot like #17556 as Alan referenced. Micro-frontends are a lot more complicated than just externalizing dependencies I don't think this is a good solution on its own, we'd need something a lot more comprehensive to cover that use case.

Since import maps are possible to do manually and micro-frontends are tracked separately, I'll close this as a dupe since there's nothing actionable here specifically.

Duplicate of #17556

@dgp1130 dgp1130 closed this as not planned Won't fix, can't repro, duplicate, stale Nov 10, 2023
@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 Dec 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants