web icon indicating copy to clipboard operation
web copied to clipboard

A modern alternative to the `--node-resolve` flag

Open FluorescentHallucinogen opened this issue 2 years ago • 5 comments

With the --node-resolve option, bare module imports e.g.:

import moment from "moment";

will be rewritten on-the-fly to:

import moment from "/node_modules/moment/src/moment.js";

What about generating import maps on-the-fly instead of rewriting bare module imports and keep all bare module imports untouched "as is"? I.e. injecting on-the-fly the following to the index.html code:

<html>
  <head>
+   <script type="importmap">
+     {
+       "imports": {
+         "moment": "/node_modules/moment/src/moment.js"
+       }
+     }
+   </script>
  </head>
  <body>
    <script type="module">
      import moment from "moment";
    </script>
  </body>
</html>

Modern browsers now support import maps natively.

This might even have a positive impact on performance and caching (no need to rewrite on-the-fly a bunch of files).

Moreover, for small apps it can be fine to just ship unminified / unbundled sources. So this approach could be applied not only for serving, but also for "building" projects.

FluorescentHallucinogen avatar Nov 21 '23 05:11 FluorescentHallucinogen

I like this idea in general, mainly because it should improve the debugging experience even further.

But the potential caveat is: how do we know in advance what to include in the importmap?

  • shall we analyze the entire dependencies tree of all entry point modules before serving the html?
  • shall we cache all node_modules importmap and use that instead?
  • how do we make this performant as compared to current behavior?

I think dynamic importmaps are not implemented / under discussion now, so it's not really possible to one-by-one inject newly identified bare modules over Web Sockets or smth, but even if it was possible, that would be even more perf cost as compared to current behavior, so I'd rather not go there.

Happy to discuss the details.

bashmish avatar Nov 21 '23 14:11 bashmish

There are some interesting community plugins which might help to explore this idea https://github.com/WICG/import-maps#community-polyfills-and-tooling

bashmish avatar Nov 21 '23 15:11 bashmish

JSPM CLI (jspm link index.html -p nodemodules -o index.html) does exactly what I mean (can use an HTML file as an entry point, generates only required import maps, then injecting the import map output back into the HTML file). The only inconvenience is that this command has to be run manually every time.

Can we use @jspm/generator in @web/dev-server?

This is the low-level core library for working with import map generation that's used under the hood in the JSPM CLI.

FluorescentHallucinogen avatar Nov 21 '23 17:11 FluorescentHallucinogen

I'm tinkering with this over at https://github.com/patternfly/patternfly-elements/pull/2655. I think this will need some chin-scratching in order to work with typescript via esbuildPlugin.

My current error is

JspmError: Module not found: file:///home/bennyp/Developer/patternfly/node_modules/@patternfly/elements/pf-button/pf-button.js 

I believe this requires more hooks into JSPM generator, since I have not yet seen a way to tell generator to parse typescript files.

Either I'm holding it wrong (likely), or JSPM generator needs a patch or two in order to support the workflow

Additionally, I'm unaware of reliable tools to resolve local monorepo (workspaces) directories, so i'll have to hack one together on my own with glob

bennypowers avatar Dec 28 '23 06:12 bennypowers

+1 on this feature, we ran into some weird edge cases using --node-resolve. I think that Web Test Runner should opt purely into generating an import map, and use as little transpilation as possible, relying on web tech instead.

jonkoops avatar Feb 06 '24 22:02 jonkoops