When you talk about speculative fetches, are you suggesting that engines would guess at which modules were going to be imperatively imported before actually running the code? That doesn't seem like a general solution, or even a particularly desirable one, but I'm interested to learn what you're referring to.
Yes, that is indeed what I am referring to, as engines already do for HTML.
Speculative fetching is possible in HTML because <link> and <img> and <script> tags etc are declarative. Similarly, modules can be fetched without the code executing because `import` is declarative. How can a browser prefetch modules when it encounters an imperative statement like `x = await import(computedModuleId())` without actually running the code?
See above for a response to your point here.
I'm familiar with the concept, but I didn't think that it was standard practice or heading that way for JS. I also have the impression that it comes with serious overhead of its own, making the "await considered harmful" performance claims valid even in that case.
I don't mean that as an argument: if speculative fetches handle this issue I don't understand how, and I'd really like to know.
In the context being discussed here, it means that `await import('./foo.js')` could kick off a speculative fetch for foo.js and all of its dependencies during the tokenization stage---exactly the same as is done for declarative `import './foo.js'`. (Per spec, the fetch for `import './foo.js'` doesn't happen until parsing, which is generally too late to give a good user experience---i.e., this is something engines will already be doing.) You could even imagine extending this to `await fetch('./foo.json')`, although I imagine that will be more of a stretch.
Of course that doesn't help for dynamic cases like `` await import(`./language-packs/${navigator.language}.js`) ``. But that's exactly as you'd expect: if your application truly depends on runtime-determined resources before it can proceed, then of course it needs to avoid continuing to evaluate code that depends on those resources. Top-level await just gives you a way to express that dependency without wrapping the rest of your app in async functions.
Interesting, and kind of makes sense.
However:
> Of course that doesn't help for dynamic cases like `` await import(`./language-packs/${navigator.language}.js`) ``.
Isn't that the main, possibly only advantage of `await import(...)` though?
For static import names, why write `const x = await import('x');` if you can simply write `import x from 'x';`?