import.prefetch and import.preload

It would be a nice feature to have to prefetch and preload dynamic imports.
When creating a SPA it's a common thing to lazy load components with using dynamic imports.
Unfortunately, there is no good way to prefetch or preload them when needed.
For example, when user visits page with list of items, you may want to prefetch a component which displays item details, as it's likely that it will be needed soon.

Currently, you would have as a link element to the document to prefetch/preload module.
This is not the optimal way, as it won't work inside workers.
Also, code bundlers often change the file name of module we want to load and it's impossible to know what file to prefetch/preload.

I propose adding two "functions": import.prefetch and import.preload, which should be used just like import "function", for example:

import.prefetch('./item-details.mjs');
async function goToDetails() {
  const itemDetails = await import('./item-details.mjs');
  // display itemDetails
}

This would create a standardized way to prefetch/preload module which could be utilized by bundlers like webpack.

import.prefetch and import.preload should work as a hint to the browsers, similar as link element. They should not return anything or block the thread.

We should be able do detect whether the feature is available so we could use it without breaking compatibility:

if (import.prefetch) {
  import.prefetch('...');
}

There’s not a concept of “fetching” in the language; that’s a web-specific thing.

I believe there’s already the link rel preload tag for this; you could write your own function that takes these specifiers and preloads them in the browser, for example.

Maybe we should introduce that concept to the language?
It's not just a browser specific thing. Other runtimes could also benefit from this feature. For example, Node could do I/O in the background.

Or maybe, lets think of a way to add metadata to es modules? Similar how html documents have link elements, something similar could be added es module... Perhaps, in this case more declarative way should be considered instead of import.prefetch/preload functions.
I know we can add links using HTTP headers, but it's not the best solutions: change in application would require a change in server configuration and it won't work well with bundlers.

This idea reminds me of https://github.com/sebmarkbage/ecmascript-asset-references. It effectively specifies a declarative prefetch hint to browsers and runtimes, and you pass that to import and other loader utilities to load it the rest of the way.

I/O might be slow, but it's not that slow when it's just local I/O. Node's require performance issues aren't from the I/O, but from 1. doing it all synchronously on one thread, 2. the large number of C++ round trips from all the I/O and other privileged stuff, and 3. the fact all the data structures are in JS and not C++ and thus there's occasionally some language overhead. (If it were implemented in pure C++ with stuff like require._cache/Module._cache implemented as host objects masquerading as object literals, it'd easily be at least 2-3x as fast.) ES modules let it resolve everything using multiple cores and allow for less waiting on slow hard drives by better leveraging Libuv, but Node doesn't have the network overhead to double that time cost if not more that browsers have when loading assets (compression + encryption on server, decompression + decryption on client, network latency, protocol overhead from TCP/IP + HTTP + Ethernet/Wi-Fi/etc., possible encryption/decryption for Wi-Fi, among other things) and it doesn't need to track assets as dependencies like bundlers like Webpack and Prepack do.

Also, embedded runtimes like Moddable's SDK (using a home-rolled engine) have literally no use for prefetching and preloading as most are single-threaded and for the few that can do anything in parallel at all (like the Tessel 2, which runs a heavily customized Node.js), they just don't have the memory and compute power to make use of it.