oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
73.95k stars 2.75k forks source link

`bun build --compile`: include non-statically analyzable dynamic imports with a flag #11732

Open terrablue opened 4 months ago

terrablue commented 4 months ago

What is the problem this feature would solve?

It's currently impossible to include non-statically analyzable dynamic imports in a single-file executable.

await import("./icon.png", { with { type: "file" } });

works and generates an internal file path, but

const file = "icon";
await import(`./${file}.png`, { with { type: "file" } });

doesn't. This is similar to a Deno restriction. They solved it by offering an --include <path> flag.

This is also generally useful if your application has unified paths for Node/Deno/Bun but you want to compile it specifically using Bun.

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

Add an --include <path> flag to bun build --compile.

What alternatives have you considered?

Not using Bun to compile my app.

ralyodio commented 4 months ago

Can we add this flag soon?

Jarred-Sumner commented 4 months ago

Temporary workaround

If you pass --minify, to bun build --compile --minify, static analysis gets smarter.

This code works:

const file = "icon";
const { default: icon } = await import(`./${file}.png`, { with: { type: "file" } });
terrablue commented 4 months ago

Thank you. This helps short term. Long term, it would still be useful to specify those assets -- some of them aren't even loaded via import but through normal FS reads, explicitly.

Perhaps you could consider introducing a manifest file in which assets for inclusion (and perhaps other exe build options) would be specified?

azu commented 3 weeks ago

Dynamic Imports support would be very useful. For example, “bun build --compile” does not support tools with a plugin system that uses Dynamic Import to load packages, such as ESLint and textlint.

With deno compile, tools with plugin systems can be compiled with the plugin included by importing the plugin in advance.

import “eslint-plugin-foo”; // prefetch and bundle it into binary

.... CLI code ....

Bun and Deno with the following simple code give different results

// preload
import "rambda";

const loadModule = async (moduleName) => {
  await import(modName); 
  // Bun's binary throw an Error
  // Deno's binary can import it
}

await loadModule("rambda"); 

Example repo: