I mentioned this in passing in my Weak imports proposal, but a couple days ago I was reminded of how useful this could be in regular imports too, when unpkg was down and suddenly several of my Vue apps were not working.
Import specifier stacks would be a comma-separated list of import specifiers. If the first specifier fails to resolve for whatever reason, the second one will be attempted and so on.
Example:
import * as Vue from "https://unpkg.com/vue@3/dist/vue.esm-browser.js",
"https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.js";
One could even combine bare specifiers and URLs:
import * as Vue from "vue", "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
This would load Vue from a CDN if there is no import map that makes a bare vue
resolve to something useful (in a browser) or if it's not installed locally (in a build environment).
Another pattern:
import * as Vue from "./vue.js", "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
This would load Vue from a CDN if there is no vue.js
file adjacent to the current file.
Note that comma-separating multiple import specifiers is currently a syntax error, so this should not introduce any web compat issues.
There are several ways to introduce this functionality to dynamic imports.
We cannot allow import()
to take multiple specifiers, as the second argument is currrently reserved for metadata. Another option could be to allow the first parameter to be an array of specifiers, but this is not backwards compatible. Introducing a fallbacks
property in the second argument seems to be backwards compatible with current implementations and would just load the first URL if the runtime doesn't support specifier stacks:
let Vue = await import("https://unpkg.com/vue@3/dist/vue.esm-browser.js", {
fallbacks: ["https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.js"]
});