Skip to content

replace importmap with import rewrite#101

Merged
mbostock merged 3 commits intomainfrom
mbostock/rewrite-import-map
Nov 6, 2023
Merged

replace importmap with import rewrite#101
mbostock merged 3 commits intomainfrom
mbostock/rewrite-import-map

Conversation

@mbostock
Copy link
Member

@mbostock mbostock commented Nov 4, 2023

Fixes #14. Instead of relying on an import map, we now rewrite npm:foo import specifiers to the corresponding URL. Since public/client.js is served statically without rewriting, we replace a handful of npm: import specifiers with the corresponding URL to match.

Screen.Recording.2023-11-04.at.7.11.55.AM.mov

@mbostock mbostock requested a review from cinxmo November 4, 2023 14:14
}

export function resolveImport(specifier: string): string {
return !specifier.startsWith("npm:")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we define

const CDN_IMPORT_SPECIFIER = "npm:"

I think it makes the code a little easier to read:

return !specifier.startsWith(CDN_IMPORT_SPECIFIER)
? specifier
: specifier === `${CDN_IMPORT_SPECIFIER}@observable/runtime`
? "/_observablehq/runtime.js"
:  `https://cdn.jsdelivr.net/npm/${specifier.slice(CDN_IMPORT_SPECIFIER.length)}/+esm`

Copy link
Member Author

@mbostock mbostock Nov 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but I think it would just make it less obvious what the code is doing, since you would have to then lookup what the value of CDN_IMPORT_SPECIFIER is. And this isn’t the sort of thing that would change — it’s a contract with users, who will use the npm: “protocol” to indicate a package that is published to npm (in the same way that Node.js developers use the node: protocol to indicate built-in packages that Node provides as opposed to ones installed into node_modules).

https://2ality.com/2021/12/node-protocol-imports.html

If anything, I would pull out the code that maps an npm module specifier to a URL (currently using jsDelivr’s +esm service), as that is an implementation detail and not something that a user would typically care about. We could make that a constant too, but a function is better because it’s not a fixed prefix on other CDNs (e.g., esm.sh). But that could consolidate a bit if desired.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would look like this:

export function resolveImport(specifier: string): string {
  return !specifier.startsWith("npm:") ? specifier : resolveNpmImport(specifier.slice(4));
}

export function resolveNpmImport(specifier: string): string {
  return specifier === "@observablehq/runtime"
    ? "/_observablehq/runtime.js"
    : `https://cdn.jsdelivr.net/npm/${specifier}/+esm`;
}

I’d rather keep things as-is, though, since resolveImport is already nicely encapsulated; I don’t see a need to expose a separate method for resolving a specifier that is specific to npm.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewritten as "npm:".length instead of 4 for clarity.

@mbostock mbostock force-pushed the mbostock/rewrite-import-map branch from b45e36f to 73e57bf Compare November 6, 2023 22:10
@mbostock mbostock enabled auto-merge (squash) November 6, 2023 22:10
@mbostock mbostock merged commit d635bcb into main Nov 6, 2023
@mbostock mbostock deleted the mbostock/rewrite-import-map branch November 6, 2023 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detect when a library should be added to the import map during live preview

3 participants