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

Interest in implementing in a bundler & dev server (subresource loading) #705

Open
Jarred-Sumner opened this issue Dec 11, 2021 · 1 comment

Comments

@Jarred-Sumner
Copy link

I’d be interested in potentially implementing support for outputting Web Bundles in a new bundler & transpiler called Bun.

The specific motivation for Bun’s usecase today is to improve page load time in development for large apps while keeping hot module reloading incredibly fast.

Currently, there’s an unfortunate tradeoff for hot module reloading <> bundling. Bundling improves page load time, but means the browser must reload lots of code for small changes. There are various workarounds, but a better solution is if browsers exposed an interface for remapping import paths to byte ranges within a bundled file (like with web bundles!)

From there, the initial request could be bundled and the bundler-specific implementation of hot module reloading would be able to use consistent import paths in transpiled code. Consistent import paths help prevent reloading code unnecessarily. The alternative is implementing a custom module loader on top of either ESM or <script> tags, which adds runtime & build-time performance overhead.

Incase it's helpful, here's a little about the metadata Bun's current bundling format stores.

For apps with ~15 MB of JavaScript dependencies (3,185 modules & 295 npm packages), the metadata loads in ~0.15ms on my laptop

image

The file starts with #!/usr/bin/env bun\n, followed by a byte offset to the start of the metadata, then the bundled code for each file, and at the end, the metadata.

// This is the top-level type loaded from disk
message JavascriptBundleContainer {
  uint32 bundle_format_version = 1;

  // These fields are specific to Bun and probably not other bundlers
  LoadedRouteConfig routes = 3;
  LoadedFramework framework = 2;

  JavascriptBundle bundle = 4;

  // Don't technically need to store this, but it may be helpful as a sanity check
  uint32 code_length = 5;
}

struct StringPointer {
  uint32 offset;
  uint32 length;
}

struct JavascriptBundledModule {
  // package-relative path including file extension
  StringPointer path;

  // Source code
  StringPointer code;

  // index into JavascriptBundle.packages
  uint32 package_id;

  // The ESM export is this id ("$" + number.toString(16))
  uint32 id;

  // This lets us efficiently compare strings ignoring the extension
  byte path_extname_length;
}

struct JavascriptBundledPackage {
  StringPointer name;
  StringPointer version;
  uint32 hash;

  uint32 modules_offset;
  uint32 modules_length;
}

struct JavascriptBundle {
  // These are sorted alphabetically so you can do binary search
  JavascriptBundledModule[] modules;
  JavascriptBundledPackage[] packages;
  
  byte[] etag;

  uint32 generated_at;
  
  // generated by hashing all ${name}@${version} in sorted order
  byte[] app_package_json_dependencies_hash;

  byte[] import_from_name;

  // This is what StringPointer refers to 
  byte[] manifest_string;
}

Eventually, this will include exports & imports of each module.

Is the recommended way to try out web bundles in a browser today using the <link> based api & an origin trial with Chromium?

@hayatoito
Copy link
Collaborator

Thanks for filing an issue!

How Web Bundles can help hot module reloading seems an interesting topic.
We've never thought how a browser-native bundle format, Web Bundles, can help HMR.

We don't have any plan nor ideas as of now, and I am not fully aware how a browser can help to support HMR nicely.
If you have any specific requests, that would be welcomed!

Is the recommended way to try out web bundles in a browser today using the based api & an origin trial with Chromium?

You can try the feature locally by enabling the flag.
This guide might be helpful:

https://chromium.googlesource.com/chromium/src/+/refs/heads/main/content/browser/web_package/subresource_loading_origin_trial.md#how-to-try-this-feature-locally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants