Load resources in JavaScript using code that works in all universes environments, using
import.meta.resolve(…)
and friends.
.js
).css
).json
).png
, .jpeg
, .webp
, …)Worker
, ServiceWorker
, SharedWorker
).wasm
)import.meta.resolve(…)
// JS
const libPath = import.meta.resolve("./lib/dynamic.js");
const lib = await import(libPath);
// JSON
const dataPath = import.meta.resolve("./data.json");
const data = await (await fetch(dataPath)).json();
console.log(data);
// CSS
const cssPath = import.meta.resolve("./themes/solarized.css");
const link = document.body.appendChild(document.createElement("link"));
link.rel = "stylesheet";
link.href = cssPath;
// Image
const imagePath = import.meta.resolve("./icons/errorsaurus.svg");
document.body.appendChild(document.createElement("img")).src = imagePath;
// Web worker
const workerPath = import.meta.resolve("./client/worker.js");
const worker = new Worker(workerPath, { type: "module" });
worker.postMessage("hi");
// WASM
const wasmPath = import.meta.resolve("./code.wasm");
const wasmModule = WebAssembly.compileStreaming(fetch(wasmPath), /* imports */);
console.log(wasmModule.exports.foo());
// Arbitrary resources
const resourcePath = import.meta.resolve("./resource");
const response = await fetch(resourcePath);
// binary
console.log(await response.arrayBuffer());
// text
console.log(await response.text());
// JSON
const dataPath = import.meta.resolve("./data.json");
const data = await import(dataPath, { assert: { type: "json" } });
console.log(data);
// CSS
const cssPath = import.meta.resolve("./themes/solarized.css");
const cssModule = await import(cssPath, { assert: { type: "css" } });
document.adoptedStyleSheets = [cssModule.default];
import.meta.resolve(…)
calls that use relative paths (i.e. strings that begin with ./
or ../
), and update such
calls to any new relative path.
import.meta.url(…)
is not implemented in all environments yet, and is not
technically
specified as part of JavaScript.
URL
constructor, with
import.meta.url
as the second parameter:
const workerPath = new URL("./client/worker.js", import.meta.url).href;
const worker = new Worker(workerPath, { type: "module" });
import.meta.resolve(…)
, when bundlers process JavaScript code and other resources in a way
that can
move them into different folders than originally, they should look for
new URL(…, import.meta.url)
calls that use relative paths for the first argument (i.e. strings that begin with ./
or
../
), and update such
calls to any new relative path.
import.meta.resolve(…)
to
new URL(…, import.meta.url).href
when outputting code to
environments that may not support the former, particularly if the code may
be used by other bundlers that do not support it yet. However, the ecosystem will reach a reliable
equilibrium once all major tools preserve import.meta.resolve(…)
by default.
import
declaration:
import { name } from "./lib/dynamic.js";
fetch
-based backwards-compatible code requires top-level await
, which can be challenging for
bundlers to handle correctly.
import.meta.resolve(…)
and new URL(…, import.meta.url)
for code that can handle all
resource paths, today and
into the future.
import.meta.resolve(…)
new URL(…, import.meta.url)
Environment | Uses | JavaScript | JSON | Image | Web worker | WASM |
Browsers | ||||||
Chromium 111 |
V8 | ✅ ✅ | ✅ ✅ | ✅ ✅ | ✅ ✅ | ✅ ✅ |
Firefox 114 |
Spider |
✅ ✅ | ✅ ✅ | ✅ ✅ | ✅ ✅ | ✅ ✅ |
Safari 16.4 |
JavaScript |
✅ ✅ | ✅ ✅ | ✅ ✅ | ✅ ✅ | ✅ ✅ |
Runtimes | ||||||
node 20.6.0 |
V8 | ✅ ✅ | ✅ ✅ | — | ✅ ✅ | ✅ ✅ |
deno 1.27.2 |
V8 | ✅ ✅ | ✅ ✅ | — | ✅ ✅ | ✅ ✅ |
bun 0.5.7 |
JavaScript |
✅ ✅ | ✅ ✅ | — | ✅ ✅ | ✅ ✅ |
Bundlers | ||||||
esbuild 0.5.7 |
❌ ❌ | ❌ ❌ | ❌ ❌ | ❌ ❌ | ❌ ❌ | |
Rollup 3.20.2 |
❌ ❌ | ❌ ❌ | ❌ ❌ | ❌ ❌ | ❌ ❌ | |
Webpack 5.76.3 |
❌ ❌ | ❌ ✅ | ❌ ✅ | ❌ ❌ | ❌ ❌ | |
swcpack 0.1.62 |
❌ ❌ | ❌ ❌ | ❌ ❌ | ❌ ❌ | ❌ ❌ | |
Parcel2 2.8.3 |
swc |
❌ ❌ | ❌ ❌ | ❌ ✅ | ❌ ✅ | ❌ ❌ |
Vite2 4.2.1 |
Rollup andesbuild
|
❌ ❌ | ❌ ✅ | ❌ ✅ | ❌ ❌ | ❌ ❌ |