Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include import.meta.resolve(…) arguments in the source graph for bun build #2906

Open
Tracked by #294
lgarron opened this issue May 16, 2023 · 3 comments
Open
Tracked by #294
Labels
bundler Something to do with the bundler enhancement New feature or request

Comments

@lgarron
Copy link
Contributor

lgarron commented May 16, 2023

I was super excited to see https://bun.sh/blog/bun-v0.6.0 this morning — I was able to use it on the first try with a codebase containing over 300 TypeScript source files! 😻

What is the problem this feature would solve?

I'd like to advocate for bun build to become a go-to tool for authoring interoperable code that works in browsers as well as runtimes, by preserving import.meta.resolve(…) resolution. This is necessary for writing code that can instantiate web workers and load WASM across environments:

// 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());

Although bun doesn't support web workers or WASM yet, import.meta.resolve(…) is implemented already1. I would love to see bun build include import.meta.resolve(…) arguments in the source graph, particularly for relative imports of files for the two web-native languages:

  • .ts/.js: Treat the argument as an entry file: bundle as normal and rewrite the argument to the relative bundled entry point.
  • .wasm: Copy the file to the bundled output, rewriting the relative path if necessary.

I think it would be great to support this for more resources as well, but these two are table-stakes for writing performant JavaScript apps.

What is the feature you are proposing to solve the problem?

I would love to get bun to implement enough features to pass the tests I have at the following:

git clone https://github.com/lgarron/loadeverything.net && cd loadeverything.net
make test-bun-build

I could use help identifying what is needed, and if there's anything I could do to contribute.

What alternatives have you considered?

No response

Footnotes

  1. It differs from all other environments (https://github.com/parcel-bundler/parcel/issues/8924) but that is not a concern for this issue.

@lgarron lgarron added the enhancement New feature or request label May 16, 2023
@Jarred-Sumner
Copy link
Collaborator

yeah this is very reasonable

We should specifically detect new Worker and create bundles for it.

@lgarron lgarron changed the title Interoperable resource bundling using import.meta.resolve. Include import.meta.resolve arguments in the source graph for bun build May 16, 2023
@lgarron lgarron changed the title Include import.meta.resolve arguments in the source graph for bun build Include import.meta.resolve(…) arguments in the source graph for bun build May 16, 2023
@lgarron
Copy link
Contributor Author

lgarron commented May 16, 2023

yeah this is very reasonable

Glad to hear it! 😻

We should specifically detect new Worker and create bundles for it.

I think this is good in general, but I'd like to ask for an important consideration when it comes to detecting new Worker(…): the following code does not work for libraries hosted on a CDN:

// Source code at https://cdn.cubing.net/foo.js

// fails in browsers if the source file origin does not match the top-level page origin.
new Worker(import.meta.resolve("./worker.js"), { type: "module" });

Instead (or in addition), libraries have to implement trampoline fallback:

// Source code at https://cdn.cubing.net/foo.js

const workerURL = import.meta.resolve("./worker.js");
const blob = new Blob([`import ${JSON.stringify(workerURL)}`], { type: "text/javascript" });
new Worker(URL.createObjectURL(blob), { type: "module" });

In a few years we may be able to avoid this using either blank workers or module expressions, but the solution above is the only interoperable fallback that works as of today.1

If possible, I'd like to ask that the semantics of the trampoline version of the code are also preserved by bun build. 🙏

Footnotes

  1. Technically node requires additional workarounds (https://github.com/nodejs/node/issues/43583) but for the purposes of this issue the only difference is that Worker would be an imported constructor rather than globalThis.Worker.

@Electroid Electroid added the bundler Something to do with the bundler label May 18, 2023
lgarron added a commit to lgarron/bun that referenced this issue May 28, 2023
@lgarron
Copy link
Contributor Author

lgarron commented May 28, 2023

I've started trying to tackle this at main...lgarron:bun:lgarron/import.meta.resolve

There's a lot more code to update, but I might appreciate some pointers if I'm not on the right track.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bundler Something to do with the bundler enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants