Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Bun Releases Native Bundler and Introduces Macros

Bun Releases Native Bundler and Introduces Macros

Bun has recently launched its fast native JavaScript bundler, bringing enhanced bundling capabilities to the Bun ecosystem. The new bundler, now in beta, offers a comprehensive set of features and tools to simplify and accelerate the process of building frontend applications. In addition, Bun introduces JavaScript macros that allow JavaScript functions to be executed at bundle-time and their results to be directly inlined into the bundle.

Bun is an all-in-one toolkit for JavaScript and TypeScript apps that aims to replace Node.js. It includes a fast JavaScript runtime, the Bun runtime, which offers improved startup times and memory usage. The toolkit ships as a single executable called "bun​" and provides various functionalities such as a test runner, script runner, and package manager.

The native Bun bundler attempts to simplify the challenges of complex JavaScript and TypeScript bundling, such as running TypeScript files, building and bundling code for production, handling dependencies, and enabling features like sourcemaps, which often leading to time-consuming tasks hampering development speed and efficiency.

The bundler offers several key features. First, it provides fast plugin execution through a lightweight Bun process, resulting in quicker bundling times. Moreover, the bundler generates pre-transpiled files optimized for Bun's runtime, eliminating redundant transpilation steps and improving overall execution performance. The unified plugin API allows plugins to extend the bundler and the runtime capabilities of Bun, enhancing flexibility and code reuse. Additionally, integrating the bundler and the runtime enables the seamless passing of BuildArtifact objects, which can be directly used in HTTP APIs like new Response(). The bundler also introduces standalone executable generation, allowing the creation of self-contained executables that include a copy of the Bun runtime.

Performance is an essential focus of the Bun bundler. Benchmarks comparing Bun to popular bundlers such as esbuild, Parcel 2, Rollup + Terser, and Webpack demonstrate Bun's exceptional speed. Bun outperforms these bundlers, with impressive speed improvements ranging from 1.75x to 220x faster, depending on the benchmark.

Developers can utilize the function or the Bun build CLI command to build frontend applications with ease. The API supports essential options such as entrypoints, output directory, target (browser, Bun, or node), format (esm), minification, sourcemap configuration, and more. In addition, the bundler supports tree-shaking to remove dead code. With a stable plugin system and loader configurations, developers can customize their bundling process according to their specific requirements.

In addition to the bundler, Bun introduced Bun Macros, which allows JavaScript functions to execute at bundle-time. Developers can import functions as macros using special import attribute syntax, inlining their results directly into the bundle. Macros run synchronously during the transpiler phase of the bundling process and are parallelized across multiple JavaScript workers, ensuring efficient execution. Macros facilitate operations such as making fetch requests at bundle-time or enhancing developer flexibility.

For security considerations, Bun Macros must be explicitly imported with the { type: 'macro' } attribute to ensure intentional execution and mitigate potential security risks. Disabling macros using the --no-macros flag adds an extra layer of security by preventing their execution altogether. Additionally, to safeguard against malicious packages, macros cannot be invoked from the node_modules directory. This limitation ensures that macros are run exclusively within the application code. Attempts to invoke macros from node_modules will trigger a specific error message.

While Bun Macros offer enhanced code execution capabilities, they have a few limitations. The result of a macro must be serializable to allow seamless inlining into the abstract syntax tree (AST). JSON-compatible data structures are fully supported, but functions and instances of most classes are not serializable. Macros can accept inputs only if the value is statically known at bundle-time. Dynamic values or those dependent on runtime conditions are not permitted as macro inputs.

Bun Macros have gathered mixed opinions within the developer community. A user, explaininjs, commented on Hacker News,

"Very nice. This should get rid of a lot of clunky webpack/esbuild/etc junk I have lying around to inline various constants or otherwise one-time configure the runtime."

Another user, skybrian, expressed support, stating,

"I like that it's not allowed in npm modules. Module authors can do whatever compile-time codegen they want as part of their own builds."

However, contributors such as goranmoomin expressed a different perspective, saying,

"Macros should be able to apply syntactic transformation on the code. Lisp is famous for allowing that by representing code as lists. Rust has a compiler-level API to give tokens and run arbitrary code, then spit new tokens out."

Jarred Sumner, CEO of Oven, the company behind Bun, acknowledged the feedback, mentioning plans to revisit the macro design.

About the Author

Rate this Article