v155 · text modules

Against fetch()

Both get you a string, so the comparison is not about which is faster. It is about when a missing file becomes your problem, what a second use costs, and whether a build tool can see the dependency at all.

Run both

The second-load button is the interesting one. A module is instantiated once per graph and cached by the module map; a fetch() goes back through HTTP caching every time, which is a different mechanism with different rules.

Measured on this machine
approachfirst loadsecond loadcharactersidentical?
Not run yet.
Press the button.

When a missing file becomes your problem

Point both at a file that does not exist and watch where the failure surfaces.

Failure behaviour
approachwhat happenedhad to be checked?
Not run yet.

fetch() resolves for a 404 — the request succeeded, the server said no. Forgetting response.ok is one of the most common bugs in code that loads text this way, and it turns a missing file into a template that renders "Not Found".

What the calling code looks like

As a text module

import schema from "./schema.sql"
  with { type: "text" };

db.exec(schema);

With fetch()

async function loadSchema() {
  const res = await fetch("./schema.sql");
  if (!res.ok) {
    throw new Error(`schema: ${res.status}`);
  }
  return res.text();
}

db.exec(await loadSchema());
// ...and everything that calls this is
// now async, all the way up.

see also