Releases: oven-sh/bun
Bun v0.0.36
bun create
bun create
is a new subcommand that lets you quickly create a project from a template.
To create a new React project (based on Create React App)
bun create react ./app
11x faster than yarn create react app
on my Macbook Pro (both installing dependencies via yarn)
To create a new Next.js project (based on Create Next App)
bun create next ./app
To create from a GitHub repository:
bun create jarred-sumner/calculator calc
To see a list of templates:
bun create
Right now, there are only two "official" templates (and they're mostly empty) – but you can add more. bun create
fetches from packages published in the examples
folder of Bun's GitHub repo. PRs are very welcome!
Local templates
Many developers have boilerplate code copied for new projects.
That's why bun create
also searches $HOME/.bun-create
for local templates.
Add a folder with a package.json in $HOME/.bun-create/my-local-template
and then you can run:
bun create my-local-template ./foo
This copies the contents of my-local-template
, initializes a git repository, runs any preinstall steps, installs dependencies (if any exist), runs any postinstall steps and rewrites the name
field in package.json
to foo
.
It uses the fastest system calls available for copying files. bun create
copies files faster than cp
. Here is a stupid microbenchmark
Performance
The slowest part is running your NPM client to install node_modules
. The second slowest part is downloading the tarball from GitHub (or NPM if it's from Bun's examples folder). Third is git.
Other stuff
fetch
now supports gzip- https support in
fetch
was completely rewritten to be more reliable. TLS is now powered by s2n-tls fetch
now supportsTransfer-Encoding: chunked
. It didn't before, which was embarrassing.- Set
self
toglobalThis
in Bun.js. This improves compatibility with some npm packages - There are two new test binaries in
misctools/
,tgz
andfetch
.tgz
is likegunzip
except harder to use andfetch
is sort of likecurl
? These are really just to help me test some things in isolation from the rest of Bun
Bun v0.0.34
Features
Slightly better tsconfig.json
handling:
jsxImportSource
support – if you setjsxImportSource
to"@emotion/react"
, JSX will auto-import from"@emotion/react/jsx-dev-runtime"
instead of"react/jsx-dev-runtime"
jsxFragmentFactory
support – this lets you override what<>
transforms into. By default it's"Fragment"
, since<>
becomesReact.Fragment
normally.jsxFactory
support – if you setjsxFactory
to"h"
, when using the classic JSX runtime, it will runh
instead ofcreateElement
This makes it easier to use @emotion/react
, preact
, and other JSX runtimes with Bun.
Bug fixes
- [fetch] Fix bug with HTTP request bodies for http (not https) requests
- Fix JSX transform edgecase with static children to match Babel's behavior (static ===
children.length > 1
) - Fix node_module resolver edgecase when resolving from the dev server (not
bun bun
) that happened when resolving workspace packages above the project root that expect dependencies from the project. This applied to pnpm
Other:
- Add a small end-to-end test for emotion JSX
- Add a small end-to-end test for React Context.Provider & Context.Consumer
- Add analytics
Bun v0.0.32
Bug fixes
- [Linux] Fix Bun failing to start when the system-installed version of ICU didn't match the dynamically linked version. The fix here is to statically link ICU. This unfortunately doubles the binary size of Bun on Linux
- Fix running
bun bun
on a networked filesystem. This is particularly relevant to WSL. The normal posix C function for moving files doesn't work if the source file is on a different mounted filesystem than the target. This fix detects the error and attempts to use sendfile() so that it copies the file faster than it would by reading the memory manually.
Bun v0.0.29
Bun v0.0.28
Bun on Linux x64
Bun is now available for Linux x64. That includes a filesystem watcher leveraging inotify
, Linux's API for watching files as well as macros and SSR/SSG.
When bundling 20 copies of Three.js on Linux x64, Bun performed:
- 1.6x faster than esbuild
- 13.5x faster than Parcel 2
- 19.5x faster than Webpack (without
babel-loader
)
I have done very little work on optimizing Bun for Linux. I'm not satisfied with these numbers, but it's a start.
Bun uses the GOMAXPROCS
to control concurrency despite not being written in Go because I didn't want to think about what to name the variable
The runs with GOMAXPROCS=1
are single-threaded runs.
Bun single-threaded performed 2.2x faster than esbuild single-threaded. The relative gap between single-threaded and concurrent performance implies there's room for improvement in Bun's concurrency code. This machine has 6 cores (nproc
returns 12
) and 64 GB of memory.
Other
- Bun's installed binary is now about 28% smaller
Bun v0.0.27
Features
Relay GraphQL client
You can now use Facebook's Relay GraphQL framework with Bun via bun-macro-relay
.
bun-macro-relay
implements the Bun equivalent of babel-plugin-relay
.
Input:
const query = graphql`
query Bacon {
}
`;
Output:
import Bacon from '__generated__/Bacon.graphql';
const query = Bacon;
This macro is implemented entirely in TypeScript - not in native code. For install instructions, head over to bun-macro-relay
.
Automatically remap macros
// Instead of having to change every import like this:
import { css } from "@emotion/react";
// To this:
import { css } from "macro:bun-macro-emotion-react";
// Now you don't have to change your code
import { css } from "@emotion/react";
note: @emotion/react is not implemented yet!
To use this, add this to your package.json (and remove the comments):
"bun": {
"macros": {
// "react-relay" is the import path to rewrite
"react-relay": {
// rewrite the "graphql" import to instead point to "bun-macro-relay/bun-macro-relay.tsx"
"graphql": "bun-macro-relay/bun-macro-relay.tsx"
}
}
},
Remapping this way only applies to macros. To rewrite imports otherwise, Bun will read paths
from tsconfig.json
or jsconfig.json
.
Bug fixes
- Fix edgecase with cjs -> esm interop runtime code when the ESM export was marked as not extensible
- Fix potential infinite loop on calling macros
- Fix incorrect jsxDEV transform when
source
feature flag is off and a runtime error occurs in a component being rendered - Fix dead-code elimination edgecase with call expressions
- Fix edgecase with parsing .env containing very short strings
More macro features
<import>
lets you inject an import statement into a module. It acceptsdefault
, which is the default import alias and you can pass anamespace
object where the object maps the import names to their names in the current file<id>
lets you reference an import (and eventually, other symbols too)<inject>
will insert each child element to the module scope. This currently only works with<import>
, but it will work with other statements eventually.
Here's an example:
const importStmt = (
<import default="MyImportName" path="foo/bar" />
);
return (
<>
<inject>{importStmt}</inject>
<id to={importStmt.namespace.MyImportName} />
</>
);
Bun v0.0.26
Features
Bun Macro
Bun Macros are a simple way to move code snippets from runtime to build-time.
Use them for:
- Zero runtime CSS-in-JS (or a little runtime, up to you)
- GraphQL parsing
- Static data fetching without a library (similar to Next.js'
getStaticProps
but from any file instead of just pages) - you can come up with more use cases
This API (and implementation) is very new and I want to hear feedback on what to change.
How to use macros:
- Any import that starts with
macro:
is imported as a macro. Macros can be npm packages, local files, or anything else resolvable. These imports are always removed from the final output. - Imports must be a named import, and are matched against call expressions (function calls) and template literals. JSX props may be added in a future release
Here's a quick example of using a macro:
// This import won't exist at runtime!
import { matchInFile } from "macro:./matchInFile";
export const IPAddresses = () => (
<div>
<h2>recent ip addresses</h2>
<div className="Lines">
{/* matchInFile gets inlined into an array at compile time */}
{matchInFile("access.log", /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}/).map(
(ipAddress, index) => (
<div className="Line" key={index}>
{ipAddress}
</div>
)
)}
</div>
</div>
);
The transpiled output looks something like this:
export const IPAddresses = () => jsx("div", {
children: [
jsx("h2", {
children: ["recent ip addresses"]
}, undefined, true, {}, this),
jsx("div", {
className: "Lines",
children: [[
"98.210.28.6",
"192.99.4.168",
// ... rest of the array
].map((ipAddress, index) => jsx("div", {
className: "Line",
children: [ipAddress]
}, index, true, {}, this))]
}, undefined, true, {}, this)
// ...rest of code
]
});
There are a few examples of how to write macros in https://github.com/Jarred-Sumner/bun/tree/main/examples/macros, but I will write more docs once I'm a little more confident that the API isn't going to change. Once I write macros for Relay and Emotion, I'll have a better sense for if this API is good enough or if there are changes to make.
I might change the import prefix from macro:
to bun:
because it's shorter and slightly faster to check (one u32 instead of a u32 and then a u16)
Credits
Bun Macros are inspired by babel-plugin-macros, which was Sunil Pai's idea. They're also sort of similar to Zig's comptime
feature.
Bun.js
Bun.readFileAsBytes
andBun.readFile
now accept an array of paths to join. Both of these are valid:
Option A:
Bun.readFile(Bun.cwd + "file.txt");
Option B:
Bun.readFile([Bun.cwd, "./text/", "file.txt"]);
Unlike Node.js' path.join
, it's an explicit array instead of arguments because someday, we might want to add extra options to this function.
Bug fixes
- Thanks @alexkuz for adding a check to the Makefile that necessary dependencies are installed prior to compiling Bun.
- Fixed an occasional UTF-8 decoding bug in
Response.text()
(fromfetch
) - Fixed an edgecase in the URL parser where it would sometimes erroneously report the pathname as
/
- Fixed a typo in the error thrown when you pass a blank string to
fetch
fetch
now includes aUser-Agent
header by default. This is overridable, but it defaults toBun.js v0.0.version-number
Bun v0.0.24
Bug fixes
- Fix crash when both JSX automatic and JSX classic imports are automatically imported and unbundled
- Fix lexing bug with the
\f
form feed character (used in Emotion & Styled Components) - Fix bug with resolving
"browser"
field in package.json. In some cases, it was resolving from the parent directory of the result instead of the browser scope.
Stability
- Add integration test that checks styled-components renders successfully and no incorrect unicode characters are present in the
style
tag
Bun v0.0.23
Fix bug with JSX transform when using a key
prop, a {...spread}
prop and a callback function as a prop in the same element. Thank you @alexkuz for the repro
Bun v0.0.22
Features
- Support resolving
"exports"
field in package.json. Webpack's guide does a great job explaining the"exports"
field. - Add parsed lines of code counter to
bun bun
- Support importing files above the project root. HTTP Requests above the project root are allowlisted to specific file extensions to prevent common webserver security vulnerabilities like reading
/etc/passwd
. Absolute file path imports always start withabs:
. The security questions aren't as relevant for localhost development, but still worth thinking about. - Support bundling symlinked workspace packages via
bun bun
. To use this, set"bun": { "alwaysBundle": ["packageName"] }
in the project'spackage.json
. - When bundling JSON, print the output as
JSON.parse(jsonString)
when the JSON is ASCII.JSON.parse
is much faster for JavaScript engines to parse.
Bun.js
- Implement
console.time
,console.timeEnd
- Implement
Bun.readFileBytes()
to get a Uint8Array of the file's contents without copying.
Bug fixes
- Fix handling when file metadata store exceeds statically allocated count (at time of writing, 16k)
- Always log errors when generating
node_modules.server.bun
- Fix how error lines with strings are highlighted
- Fix parsing/printing JavaScript unicode identifiers
- Slightly improve .env loader string detection
- More correct
export default
transform for bundled code - Fix a JavaScript simplification bug involving ternaries
- Fix a JavaScript parsing bug with arrays in function arguments that have default values
- Fix edgecase with bare imports inside .bun
- Fix edgecase with whether to wrap arrow expressions in parentheses when printing
- Fix edgecase when a bundled module with multiple-levels of nested exports have a boolean value for the
default
export - Globally define
require()
so that UMD modules which check for the existence ofrequire()
to determine if it's CommonJS use the CommonJS code path instead of the globalThis code path. This is not great. - Embed regeneratorRuntime so that modules which expect it to be a global work
- Fix crash when loading JS fails really quickly
Misc
- Begin adding integration tests with snapshots that run with HMR disabled & HMR enabled
- Add comment explaining failed package.json parsing optimization
- Elaborate on
bun bun
in the readme - Switch to UTF-8 for prefilled strings, remove eagerly loading identifier_name
- Symlinks work but the readme wasn't updated
- Add skeleton code for macros but do not execute them yet