bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one

Downloads
4.5M
Stars
70.2K
Committers
681

Bot releases are visible (Hide)

bun - bun v0.0.71

Published by Jarred-Sumner over 2 years ago

To upgrade:

bun upgrade

# Try this
curl https://bun.sh/install | bash

Please let me know though if it doesn't work and you're on bun v0.0.69. bun v0.0.61 - v0.0.68 had issues with the HTTP client

Highlights:

  • More reliable bun install: numerous bug fixes to linking, serialization, deserialization, extracting files. It probably works in many projects now. There are still a couple bugs that need to be fixed, no node-gyp yet, and git/github dependencies don't work yet
  • "Copy as markdown" for error messages
  • Macros can now be used like regular JavaScript, with automatic conversion of primitives & objects to Bun's AST
  • bun pm hash returns a hash of the resolved all package@version in your lockfile
  • bun install --global lets you globally install npm packages with bun!
  • bug fixes to bun dev & bun run
  • TextEncoder, TextDecoder, process.exit, crypto.randomUUID, crypto.randomBytes are now available in bun.js
  • Better support for Next.js v12.1
# Install a package globally with bun install
> bun install -g typescript

# "bun i" is shorthand for bun install
> bun i -g typescript

# It symlinks into your $BUN_INSTALL/bin folder
> which tsc
/Users/jarred/.bun/bin/tsc

# print the path of the global bin
> bun pm -g bin 
/Users/jarred/.bun/bin

Lowlights:

  • Breaking changes to bun install lockfile format change means your next bun install will invalidate existing ones. The changes improve the reliability of saving and loading the lockfile

"Copy as markdown" button for error messages

Before this release, bun dev did not support displaying runtime errors. It only showed errors for build/ssr 🙈

Use macros like regular JavaScript

Now you can move code from runtime to build-time by writing ordinary javascript.

Input:

// This line is removed at build time
import {weatherIn} from 'macro:./weather'

// This function call is replaced with the value of `weatherIn(94609)` at build-time
const {current_condition: [{temp_F: degrees}]} = weatherIn(94609);

export default `It is ${degrees} in Oakland, California`

weather.js:

export async function weatherIn(call) {
    const location = call.arguments[0];
    return fetch(`https://wttr.in/${location.toString()}?format=j1`)
} 

Output:

const {
  current_condition: [{ temp_F: degrees }]
} = {
  current_condition: [
    {
      temp_F: "42"
    }
  ]
};
// once bun gets a minifier, this line would be all that remains
export default `It is ${degrees} in Oakland, California`;
{
    "current_condition": [
        {
            "FeelsLikeC": "4",
            "FeelsLikeF": "39",
            "cloudcover": "100",
            "humidity": "79",
            "localObsDateTime": "2022-02-25 03:18 AM",
            "observation_time": "11:18 AM",
            "precipInches": "0.0",
            "precipMM": "0.0",
            "pressure": "1026",
            "pressureInches": "30",
            "temp_C": "4",
            "temp_F": "40",
            "uvIndex": "1",
            "visibility": "16",
            "visibilityMiles": "9",
            "weatherCode": "122",
            "weatherDesc": [
                {
                    "value": "Overcast"
                }
            ],
            "weatherIconUrl": [
                {
                    "value": ""
                }
            ],
            "winddir16Point": "ENE",
            "winddirDegree": "70",
            "windspeedKmph": "7",
            "windspeedMiles": "4"
        }
    ],
    "nearest_area": [
        {
            "areaName": [
                {
                    "value": "Emeryville"
                }
            ],
            "country": [
                {
                    "value": "United States of America"
                }
            ],
            "latitude": "37.831",
            "longitude": "-122.284",
            "population": "0",
            "region": [
                {
                    "value": "California"
                }
            ],
            "weatherUrl": [
                {
                    "value": ""
                }
            ]
        }
    ],
    "request": [
        {
            "query": "Lat 37.83 and Lon -122.26",
            "type": "LatLon"
        }
    ],
    "weather": [
        {
            "astronomy": [
                {
                    "moon_illumination": "24",
                    "moon_phase": "Last Quarter",
                    "moonrise": "03:03 AM",
                    "moonset": "12:25 PM",
                    "sunrise": "06:46 AM",
                    "sunset": "05:59 PM"
                }
            ],
            "avgtempC": "10",
            "avgtempF": "49",
            "date": "2022-02-25",
            "hourly": [
                {
                    "DewPointC": "2",
                    "DewPointF": "36",
                    "FeelsLikeC": "5",
                    "FeelsLikeF": "42",
                    "HeatIndexC": "7",
                    "HeatIndexF": "44",
                    "WindChillC": "5",
                    "WindChillF": "42",
                    "WindGustKmph": "11",
                    "WindGustMiles": "7",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "82",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "88",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "4",
                    "humidity": "75",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1025",
                    "pressureInches": "30",
                    "tempC": "7",
                    "tempF": "44",
                    "time": "0",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "WNW",
                    "winddirDegree": "300",
                    "windspeedKmph": "6",
                    "windspeedMiles": "4"
                },
                {
                    "DewPointC": "2",
                    "DewPointF": "35",
                    "FeelsLikeC": "6",
                    "FeelsLikeF": "42",
                    "HeatIndexC": "6",
                    "HeatIndexF": "42",
                    "WindChillC": "6",
                    "WindChillF": "42",
                    "WindGustKmph": "3",
                    "WindGustMiles": "2",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "81",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "93",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "78",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "6",
                    "tempF": "42",
                    "time": "300",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "N",
                    "winddirDegree": "360",
                    "windspeedKmph": "2",
                    "windspeedMiles": "1"
                },
                {
                    "DewPointC": "1",
                    "DewPointF": "34",
                    "FeelsLikeC": "4",
                    "FeelsLikeF": "39",
                    "HeatIndexC": "5",
                    "HeatIndexF": "40",
                    "WindChillC": "4",
                    "WindChillF": "39",
                    "WindGustKmph": "9",
                    "WindGustMiles": "5",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "91",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "94",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "78",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1025",
                    "pressureInches": "30",
                    "tempC": "5",
                    "tempF": "40",
                    "time": "600",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "ENE",
                    "winddirDegree": "72",
                    "windspeedKmph": "5",
                    "windspeedMiles": "3"
                },
                {
                    "DewPointC": "-1",
                    "DewPointF": "31",
                    "FeelsLikeC": "5",
                    "FeelsLikeF": "41",
                    "HeatIndexC": "6",
                    "HeatIndexF": "42",
                    "WindChillC": "5",
                    "WindChillF": "41",
                    "WindGustKmph": "7",
                    "WindGustMiles": "4",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "89",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "87",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "64",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "6",
                    "tempF": "42",
                    "time": "900",
                    "uvIndex": "3",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "ENE",
                    "winddirDegree": "72",
                    "windspeedKmph": "5",
                    "windspeedMiles": "3"
                },
                {
                    "DewPointC": "0",
                    "DewPointF": "32",
                    "FeelsLikeC": "13",
                    "FeelsLikeF": "56",
                    "HeatIndexC": "13",
                    "HeatIndexF": "56",
                    "WindChillC": "13",
                    "WindChillF": "56",
                    "WindGustKmph": "8",
                    "WindGustMiles": "5",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "80",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "85",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "40",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "13",
                    "tempF": "56",
                    "time": "1200",
                    "uvIndex": "4",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "ENE",
                    "winddirDegree": "70",
                    "windspeedKmph": "7",
                    "windspeedMiles": "4"
                },
                {
                    "DewPointC": "1",
                    "DewPointF": "33",
                    "FeelsLikeC": "17",
                    "FeelsLikeF": "62",
                    "HeatIndexC": "17",
                    "HeatIndexF": "62",
                    "WindChillC": "17",
                    "WindChillF": "62",
                    "WindGustKmph": "8",
                    "WindGustMiles": "5",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "89",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "88",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "34",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1025",
                    "pressureInches": "30",
                    "tempC": "17",
                    "tempF": "62",
                    "time": "1500",
                    "uvIndex": "5",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "NNW",
                    "winddirDegree": "330",
                    "windspeedKmph": "7",
                    "windspeedMiles": "4"
                },
                {
                    "DewPointC": "2",
                    "DewPointF": "36",
                    "FeelsLikeC": "16",
                    "FeelsLikeF": "61",
                    "HeatIndexC": "16",
                    "HeatIndexF": "61",
                    "WindChillC": "16",
                    "WindChillF": "61",
                    "WindGustKmph": "9",
                    "WindGustMiles": "6",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "80",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "93",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "39",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1024",
                    "pressureInches": "30",
                    "tempC": "16",
                    "tempF": "61",
                    "time": "1800",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "NW",
                    "winddirDegree": "307",
                    "windspeedKmph": "8",
                    "windspeedMiles": "5"
                },
                {
                    "DewPointC": "2",
                    "DewPointF": "35",
                    "FeelsLikeC": "8",
                    "FeelsLikeF": "47",
                    "HeatIndexC": "9",
                    "HeatIndexF": "48",
                    "WindChillC": "8",
                    "WindChillF": "47",
                    "WindGustKmph": "12",
                    "WindGustMiles": "7",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "87",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "85",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "61",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1025",
                    "pressureInches": "30",
                    "tempC": "9",
                    "tempF": "48",
                    "time": "2100",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "NW",
                    "winddirDegree": "305",
                    "windspeedKmph": "6",
                    "windspeedMiles": "4"
                }
            ],
            "maxtempC": "17",
            "maxtempF": "63",
            "mintempC": "4",
            "mintempF": "39",
            "sunHour": "11.0",
            "totalSnow_cm": "0.0",
            "uvIndex": "4"
        },
        {
            "astronomy": [
                {
                    "moon_illumination": "17",
                    "moon_phase": "Waning Crescent",
                    "moonrise": "04:08 AM",
                    "moonset": "01:29 PM",
                    "sunrise": "06:44 AM",
                    "sunset": "06:00 PM"
                }
            ],
            "avgtempC": "10",
            "avgtempF": "51",
            "date": "2022-02-26",
            "hourly": [
                {
                    "DewPointC": "2",
                    "DewPointF": "35",
                    "FeelsLikeC": "7",
                    "FeelsLikeF": "45",
                    "HeatIndexC": "8",
                    "HeatIndexF": "46",
                    "WindChillC": "7",
                    "WindChillF": "45",
                    "WindGustKmph": "8",
                    "WindGustMiles": "5",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "83",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "91",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "67",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "8",
                    "tempF": "46",
                    "time": "0",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "N",
                    "winddirDegree": "353",
                    "windspeedKmph": "4",
                    "windspeedMiles": "3"
                },
                {
                    "DewPointC": "0",
                    "DewPointF": "33",
                    "FeelsLikeC": "7",
                    "FeelsLikeF": "45",
                    "HeatIndexC": "7",
                    "HeatIndexF": "45",
                    "WindChillC": "7",
                    "WindChillF": "45",
                    "WindGustKmph": "7",
                    "WindGustMiles": "4",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "91",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "94",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "12",
                    "humidity": "62",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1025",
                    "pressureInches": "30",
                    "tempC": "7",
                    "tempF": "45",
                    "time": "300",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "E",
                    "winddirDegree": "90",
                    "windspeedKmph": "4",
                    "windspeedMiles": "2"
                },
                {
                    "DewPointC": "-1",
                    "DewPointF": "31",
                    "FeelsLikeC": "6",
                    "FeelsLikeF": "42",
                    "HeatIndexC": "7",
                    "HeatIndexF": "44",
                    "WindChillC": "6",
                    "WindChillF": "42",
                    "WindGustKmph": "11",
                    "WindGustMiles": "7",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "81",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "92",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "9",
                    "humidity": "61",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "7",
                    "tempF": "44",
                    "time": "600",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "ENE",
                    "winddirDegree": "66",
                    "windspeedKmph": "6",
                    "windspeedMiles": "4"
                },
                {
                    "DewPointC": "-1",
                    "DewPointF": "31",
                    "FeelsLikeC": "6",
                    "FeelsLikeF": "43",
                    "HeatIndexC": "7",
                    "HeatIndexF": "45",
                    "WindChillC": "6",
                    "WindChillF": "43",
                    "WindGustKmph": "9",
                    "WindGustMiles": "5",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "83",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "92",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "4",
                    "humidity": "57",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1027",
                    "pressureInches": "30",
                    "tempC": "7",
                    "tempF": "45",
                    "time": "900",
                    "uvIndex": "3",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "ENE",
                    "winddirDegree": "71",
                    "windspeedKmph": "6",
                    "windspeedMiles": "4"
                },
                {
                    "DewPointC": "1",
                    "DewPointF": "33",
                    "FeelsLikeC": "14",
                    "FeelsLikeF": "57",
                    "HeatIndexC": "13",
                    "HeatIndexF": "56",
                    "WindChillC": "14",
                    "WindChillF": "57",
                    "WindGustKmph": "4",
                    "WindGustMiles": "2",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "83",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "89",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "7",
                    "humidity": "43",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1027",
                    "pressureInches": "30",
                    "tempC": "13",
                    "tempF": "56",
                    "time": "1200",
                    "uvIndex": "4",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "NE",
                    "winddirDegree": "48",
                    "windspeedKmph": "4",
                    "windspeedMiles": "2"
                },
                {
                    "DewPointC": "2",
                    "DewPointF": "35",
                    "FeelsLikeC": "15",
                    "FeelsLikeF": "60",
                    "HeatIndexC": "15",
                    "HeatIndexF": "60",
                    "WindChillC": "15",
                    "WindChillF": "60",
                    "WindGustKmph": "5",
                    "WindGustMiles": "3",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "88",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "86",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "12",
                    "humidity": "39",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "15",
                    "tempF": "60",
                    "time": "1500",
                    "uvIndex": "5",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "WNW",
                    "winddirDegree": "296",
                    "windspeedKmph": "5",
                    "windspeedMiles": "3"
                },
                {
                    "DewPointC": "1",
                    "DewPointF": "33",
                    "FeelsLikeC": "13",
                    "FeelsLikeF": "55",
                    "HeatIndexC": "13",
                    "HeatIndexF": "56",
                    "WindChillC": "13",
                    "WindChillF": "55",
                    "WindGustKmph": "12",
                    "WindGustMiles": "8",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "39",
                    "chanceofrain": "0",
                    "chanceofremdry": "91",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "80",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "49",
                    "humidity": "42",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1027",
                    "pressureInches": "30",
                    "tempC": "13",
                    "tempF": "56",
                    "time": "1800",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "116",
                    "weatherDesc": [
                        {
                            "value": "Partly cloudy"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "W",
                    "winddirDegree": "278",
                    "windspeedKmph": "9",
                    "windspeedMiles": "5"
                },
                {
                    "DewPointC": "0",
                    "DewPointF": "32",
                    "FeelsLikeC": "11",
                    "FeelsLikeF": "51",
                    "HeatIndexC": "11",
                    "HeatIndexF": "52",
                    "WindChillC": "11",
                    "WindChillF": "51",
                    "WindGustKmph": "12",
                    "WindGustMiles": "8",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "90",
                    "chanceofrain": "0",
                    "chanceofremdry": "87",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "16",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "77",
                    "humidity": "46",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1027",
                    "pressureInches": "30",
                    "tempC": "11",
                    "tempF": "52",
                    "time": "2100",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "119",
                    "weatherDesc": [
                        {
                            "value": "Cloudy"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "E",
                    "winddirDegree": "90",
                    "windspeedKmph": "7",
                    "windspeedMiles": "4"
                }
            ],
            "maxtempC": "15",
            "maxtempF": "60",
            "mintempC": "6",
            "mintempF": "42",
            "sunHour": "11.6",
            "totalSnow_cm": "0.0",
            "uvIndex": "4"
        },
        {
            "astronomy": [
                {
                    "moon_illumination": "9",
                    "moon_phase": "Waning Crescent",
                    "moonrise": "05:05 AM",
                    "moonset": "02:39 PM",
                    "sunrise": "06:43 AM",
                    "sunset": "06:01 PM"
                }
            ],
            "avgtempC": "13",
            "avgtempF": "56",
            "date": "2022-02-27",
            "hourly": [
                {
                    "DewPointC": "0",
                    "DewPointF": "32",
                    "FeelsLikeC": "11",
                    "FeelsLikeF": "51",
                    "HeatIndexC": "11",
                    "HeatIndexF": "51",
                    "WindChillC": "11",
                    "WindChillF": "51",
                    "WindGustKmph": "1",
                    "WindGustMiles": "0",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "92",
                    "chanceofrain": "0",
                    "chanceofremdry": "86",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "11",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "74",
                    "humidity": "47",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1028",
                    "pressureInches": "30",
                    "tempC": "11",
                    "tempF": "51",
                    "time": "0",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "119",
                    "weatherDesc": [
                        {
                            "value": "Cloudy"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "WNW",
                    "winddirDegree": "297",
                    "windspeedKmph": "0",
                    "windspeedMiles": "0"
                },
                {
                    "DewPointC": "0",
                    "DewPointF": "32",
                    "FeelsLikeC": "10",
                    "FeelsLikeF": "50",
                    "HeatIndexC": "10",
                    "HeatIndexF": "50",
                    "WindChillC": "10",
                    "WindChillF": "50",
                    "WindGustKmph": "7",
                    "WindGustMiles": "4",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "38",
                    "chanceofrain": "0",
                    "chanceofremdry": "85",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "86",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "29",
                    "humidity": "51",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1028",
                    "pressureInches": "30",
                    "tempC": "10",
                    "tempF": "50",
                    "time": "300",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "116",
                    "weatherDesc": [
                        {
                            "value": "Partly cloudy"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "NW",
                    "winddirDegree": "326",
                    "windspeedKmph": "4",
                    "windspeedMiles": "2"
                },
                {
                    "DewPointC": "0",
                    "DewPointF": "32",
                    "FeelsLikeC": "9",
                    "FeelsLikeF": "48",
                    "HeatIndexC": "9",
                    "HeatIndexF": "48",
                    "WindChillC": "9",
                    "WindChillF": "48",
                    "WindGustKmph": "7",
                    "WindGustMiles": "4",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "92",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "91",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "16",
                    "humidity": "54",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1029",
                    "pressureInches": "30",
                    "tempC": "9",
                    "tempF": "48",
                    "time": "600",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "N",
                    "winddirDegree": "1",
                    "windspeedKmph": "4",
                    "windspeedMiles": "2"
                },
                {
                    "DewPointC": "0",
                    "DewPointF": "32",
                    "FeelsLikeC": "10",
                    "FeelsLikeF": "51",
                    "HeatIndexC": "10",
                    "HeatIndexF": "50",
                    "WindChillC": "10",
                    "WindChillF": "51",
                    "WindGustKmph": "6",
                    "WindGustMiles": "4",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "86",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "88",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "10",
                    "humidity": "50",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1030",
                    "pressureInches": "30",
                    "tempC": "10",
                    "tempF": "50",
                    "time": "900",
                    "uvIndex": "4",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "ENE",
                    "winddirDegree": "72",
                    "windspeedKmph": "4",
                    "windspeedMiles": "2"
                },
                {
                    "DewPointC": "2",
                    "DewPointF": "35",
                    "FeelsLikeC": "17",
                    "FeelsLikeF": "62",
                    "HeatIndexC": "17",
                    "HeatIndexF": "62",
                    "WindChillC": "17",
                    "WindChillF": "62",
                    "WindGustKmph": "5",
                    "WindGustMiles": "3",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "94",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "92",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "7",
                    "humidity": "36",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1029",
                    "pressureInches": "30",
                    "tempC": "17",
                    "tempF": "62",
                    "time": "1200",
                    "uvIndex": "5",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "NNE",
                    "winddirDegree": "30",
                    "windspeedKmph": "4",
                    "windspeedMiles": "2"
                },
                {
                    "DewPointC": "3",
                    "DewPointF": "37",
                    "FeelsLikeC": "19",
                    "FeelsLikeF": "66",
                    "HeatIndexC": "19",
                    "HeatIndexF": "66",
                    "WindChillC": "19",
                    "WindChillF": "66",
                    "WindGustKmph": "9",
                    "WindGustMiles": "6",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "91",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "91",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "3",
                    "humidity": "34",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "19",
                    "tempF": "66",
                    "time": "1500",
                    "uvIndex": "5",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "WNW",
                    "winddirDegree": "299",
                    "windspeedKmph": "8",
                    "windspeedMiles": "5"
                },
                {
                    "DewPointC": "5",
                    "DewPointF": "42",
                    "FeelsLikeC": "18",
                    "FeelsLikeF": "64",
                    "HeatIndexC": "18",
                    "HeatIndexF": "64",
                    "WindChillC": "18",
                    "WindChillF": "64",
                    "WindGustKmph": "12",
                    "WindGustMiles": "7",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "83",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "90",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "0",
                    "humidity": "43",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1026",
                    "pressureInches": "30",
                    "tempC": "18",
                    "tempF": "64",
                    "time": "1800",
                    "uvIndex": "5",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Sunny"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "W",
                    "winddirDegree": "271",
                    "windspeedKmph": "10",
                    "windspeedMiles": "6"
                },
                {
                    "DewPointC": "5",
                    "DewPointF": "42",
                    "FeelsLikeC": "12",
                    "FeelsLikeF": "53",
                    "HeatIndexC": "12",
                    "HeatIndexF": "53",
                    "WindChillC": "12",
                    "WindChillF": "53",
                    "WindGustKmph": "11",
                    "WindGustMiles": "7",
                    "chanceoffog": "0",
                    "chanceoffrost": "0",
                    "chanceofhightemp": "0",
                    "chanceofovercast": "0",
                    "chanceofrain": "0",
                    "chanceofremdry": "83",
                    "chanceofsnow": "0",
                    "chanceofsunshine": "87",
                    "chanceofthunder": "0",
                    "chanceofwindy": "0",
                    "cloudcover": "16",
                    "humidity": "64",
                    "precipInches": "0.0",
                    "precipMM": "0.0",
                    "pressure": "1027",
                    "pressureInches": "30",
                    "tempC": "12",
                    "tempF": "53",
                    "time": "2100",
                    "uvIndex": "1",
                    "visibility": "10",
                    "visibilityMiles": "6",
                    "weatherCode": "113",
                    "weatherDesc": [
                        {
                            "value": "Clear"
                        }
                    ],
                    "weatherIconUrl": [
                        {
                            "value": ""
                        }
                    ],
                    "winddir16Point": "WNW",
                    "winddirDegree": "292",
                    "windspeedKmph": "6",
                    "windspeedMiles": "4"
                }
            ],
            "maxtempC": "20",
            "maxtempF": "68",
            "mintempC": "9",
            "mintempF": "47",
            "sunHour": "11.6",
            "totalSnow_cm": "0.0",
            "uvIndex": "3"
        }
    ]
}

JavaScript Parser reliability

I ported some of esbuild's tests to bun's testing library and that led to uncovering & fixing some parser bugs

// what some of the tests look like
expectParseError("-x.y() ** 2", "Unexpected **");
expectParseError("+x.y() ** 2", "Unexpected **");
expectParseError("~x.y() ** 2", "Unexpected **");
expectParseError("!x.y() ** 2", "Unexpected **");
expectParseError("void x.y() ** 2", "Unexpected **");
expectParseError("delete x.y() ** 2", "Unexpected **");
expectParseError("typeof x.y() ** 2", "Unexpected **");

New features

type inside of import clauses is now supported. This is a TypeScript feature.

// previously, this would error
import {type FooType} from 'bar';

Import assertions are now parsed by bun. Currently, they're removed from the final output

import("./foo.json", { type: "json" });
// ⬇️
import("./foo.json");

import json from "./foo.json" assert { type: "json" };
// ⬇️
import json from "./foo.json";

Fixed a number of whitespace/formatting bugs with the printer

bun install reliability

This release brings bun install much closer to something you can use daily. It's not there yet, but it is close.

Somewhat controversially, bun install uses a binary lockfile format. One thing several people asked for: a hash. So I added a hash.

> bun pm hash
1A0FF3DFFE05333A-b20fd0e1259d2de5-9E3B657EA8BD4436-9f3132e0eb95a60e

This is a SHA512/256 hash of the following string. The string is created by looping through all the resolved packages in the lockfile, sorting alphabetically, then sorting any packages with multiple duplicate versions.

> bun pm hash-string
-- BEGIN SHA512/256(`${alphabetize(name)}@${order(version)}`) --
@types/[email protected]
@types/[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
-- END HASH--

bun pm is a new subcommand for "miscellaneous package manager things"

> bun pm
bun pm - package manager related commands

  bun pm bin          print the path to bin folder
  bun pm -g bin       print the global path to bin folder
  bun pm hash         generate & print the hash of the current lockfile
  bun pm hash-string  print the string used to hash the lockfile
  bun pm hash-print   print the hash stored in the current lockfile

When using bun install -y, the hash is inserted into the saved yarn.lock:

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
# bun ./bun.lockb --hash: 3982DAEC20B10CF8-4da4f73e6f1d3ab1-77B62BB40B50C631-a7674fe7d3217550

You can now configure bun install with bunfig.toml. it will search for bunfig.toml in $XDG_CONFIG_HOME/bunfig.toml and $HOME/bunfig.toml, in addition to ./bunfig.toml

bun install bugfixes

bun run

bun bun

  • Fix race condition

bun dev

Open-in-editor is now implemented

Screen Recording 2022-02-25 at 5 15 01 AM

Bun.js

Other

try running bun wiptest in a project that uses jest

it'll probably throw a not implemented error, but it might work

bun - bun v0.0.69

Published by Jarred-Sumner over 2 years ago

To upgrade:

bun upgrade

# If you run into problems, try this instead:
curl https://bun.sh/install | bash

bun v0.0.69

Highlights:

  • Reliability improvements to bun's https client, which means reliability improvements to bun install, fetch(), bun create, bun upgrade, and everything else depending on it
  • bunfig.toml lets you configure bun from a config file instead of only CLI arguments
  • import foo from "./file.toml" is now supported (thanks to bun's new TOML parser)
  • No longer need to install the react-refresh npm package for React Fast Refresh to work
  • Native support for Node.js path module
  • bun dev includes a default favicon, and the favicon becomes a red ⚠️ on build error

HTTPS client

I rewrote the TLS part of bun's https client to match Chromium's behavior.

This fixes many bugs:

  • On some websites using TLS 1.3, the https client would infinite loop during handshaking
  • On some machines, bun dev would crash after 30 seconds due to bugs with the https client. Since it happened in a random interval between 0 and 30 seconds, it appeared to be in many places
  • On Ubuntu 20.04 when running Linux kernel 5.4 (the default for ubuntu server), sending http requests simply did not work at all. This was due to using io_uring APIs which are only available on Linux Kernel 5.6. Now, bun detects the linux kernel version in use and uses a (slower) fallback if the APIs are unavailable
  • In some cases, it was closing socket file descriptors multiple times, leading to strange bugs like files failing to extract files during bun install or data corruption
  • In some cases, it was never closing socket file descriptors. This eventually led to errors about all sockets being busy
  • Previously, bun cached the results returned from getaddrinfo. On Linux, this sometimes caused it to crash. Now bun does not cache it. This makes it a little slower, but this way of doing DNS resolution needs to be replaced with a non-blocking implementation regardless.

bunfig.toml

bunfig.toml is bun's configuration file.

Everything in it is optional. You don't need a bunfig.toml to use bun, this exists so you don't have to pass flags to the CLI each time.

Options specific to bun install will be added in a future release.

# Set a default framework to use
# By default, bun will look for an npm package like `bun-framework-${framework}`, followed by `${framework}`
framework = "next"
logLevel = "debug"

# publicDir = "public"
# external = ["jquery"]

[macros]
# Remap any import like this:
#     import {graphql} from 'react-relay';
# To:
#     import {graphql} from 'macro:bun-macro-relay';
react-relay = { "graphql" = "bun-macro-relay" }

[bundle]
saveTo = "node_modules.bun"
# Don't need this if `framework` is set, but showing it here as an example anyway
entryPoints = ["./app/index.ts"]

[bundle.packages]
# If you're bundling packages that do not actually live in a `node_modules` folder or do not have the full package name in the file path, you can pass this 
"@bigapp/design-system" = true

[dev]
# Change the default port from 3000 to 5000
port = 5000

[define]
# Replace any usage of "process.env.bagel" with the string `lox`. 
# The values are parsed as JSON, except single-quoted strings are supported and `'undefined'` becomes `undefined` in JS.
# This will probably change in a future release to be just regular TOML instead. It is a holdover from the CLI argument parsing.
"process.env.bagel" = "'lox'"

[loaders]
# When loading a .bagel file, run the JS parser
".bagel" = "js"

TOML imports

bun now has a custom TOML 1.0 parser, which means you can import .toml files from bun.

Note that parsing dates/timestamps is not implemented yet.

import config from 'my-config-file.toml';

console.assert(config.hi === "hello");
hi = "hello"

A future version might support importing top-level properties instead of only default. I think supporting both ways would be a better DX.

bun dev

This release improves using bun for static sites. bun dev now automatically looks for .html files in the same folder as code. Previously, .html files needed to be in either public or static

You no longer need to install the react-refresh npm package to use React Fast Refresh with bun. bun embeds it into bun's binary and automatically enables it if resolving "react" (or otherwise, the JSX import source) is successful

bun sets a default favicon so you can more easily see which tab is your dev server:
image

Path module

bun.js gets native support for Node's path module. This is a performance improvement, but it's also good for consistency & reliability. It means that resolving file paths in JavaScript is consistent with native code.

// Any of these work
import * as path from "node:path";
import * as path from "path";
const path = require("path");

As part of that work, a bug was fixed when generating relative file paths where, in some cases, it would cut off the first letter if the destination file path did not have any folders in common with the from file path


Misc:

  • Missing newline in errors in bun install - 1064b9dada6e9920f3f2e241bedb70570de032f5
  • Fix JS printing edgecase with nested vars using destructuring - d47e0de1750c9d234febdebeac4415470deea008
  • Fix CommonJS <> ESM interop edgecase when require() bundled code - 73449bf43373ee3a23f080e3b9ce144bc93db27c
  • bun.js resolve dynamic imports lazily - https://github.com/Jarred-Sumner/bun/commit/0e0bfe91d050fc7fa645c8a1169db600a2ecd0ed
  • Reduced memory usage for object pools. For many things, bun uses object pools to spend less time allocating and deallocating memory. Once allocated, these are never freed. Now object pools have a limit to how many are kept alive in the pool. 213960a04a22bed4d0ffb3cdc9e20439bd1dcc10
  • Use a special heap for the https client

Thanks to:

bun - bun v0.0.68

Published by Jarred-Sumner over 2 years ago

To upgrade:

bun upgrade

bun v0.0.68

This release is mostly focused on bun.js, bun's JavaScript runtime environment. Fixes to bun install will be part of the next release, but the infrastructure work from this release will help with bun install in the next release.

TLDR:

  • Bun.Transpiler lets you run Bun's JS/TSX transpiler programmatically from bun.js
  • bun.js natively implements Node.js' fs module (sync functions), and its fast
  • bun.js has more support for the Node.js process object

Bun.Transpiler - API access to Bun

const bun = new Bun.Transpiler({
  loader: "tsx", // set default loader
});

// logs transpiled code without resolving imports
console.log(bun.transformSync("export default <div />"));

// return list of imports & exports without resolving imports or printing code
const { imports, exports } = bun.scan(`
  import { Component } from "react";
  export const foo: boolean = true;
`);

console.log({ exports, imports });

Bun.Transpiler exposes part of Bun's JavaScript & TypeScript transpiler from native code to JavaScript, and it's fast.

End-to-end, transpiling this JSX file inside JavaScript via Bun.Transpiler runs:

  • 8x faster than swc
  • 15x faster than esbuild
  • 40x faster than babel

image

See benchmark code

Bun.Transpiler supports JavaScript plugins with AST access via macros. Macros are not entirely done yet, but simple ones work. There will be docs on this.

Bun.Transpiler is builtin to bun.js, there's nothing extra to import or install. Eventually there will be a WASM build for some of this, but not sure when

However, a transpiler API is not very useful without a way to read/write files to disk.

Node.js fs module implementation

// This works in bun.js now
import {readFileSync} from 'fs';

// require("fs") also works in both .mjs files and .js/.cjs files
require("fs").writeFileSync("foo.txt", "bar!")

// you can also use the node: namespace if you want
import {readlinkSync} from 'node:fs';

You can now use most of the sync functions from Node.js' fs module inside bun.js. These are implemented from scratch in Zig & exposed to JS. Buffer & streams are not implemented yet, but you can pass a Uint8Array or ArrayBuffer where Node accepts a Buffer. The async versions of the functions will come in a future release (this already was a lot of stuff for one release), but generally sync outperforms async for local file access.

fs.realpathSync is about 7x faster in bun.js (50,000 iterations)

image

fs.existsSync runs about 30% faster in bun.js (100,000 iterations)

image

The following functions are implemented:

  • fs.accessSync
  • fs.appendFileSync
  • fs.chmodSync
  • fs.chownSync
  • fs.closeSync
  • fs.copyFileSync
  • fs.existsSync
  • fs.fchmodSync
  • fs.fchownSync
  • fs.fstatSync
  • fs.fsyncSync
  • fs.ftruncateSync
  • fs.futimesSync
  • fs.lchmodSync
  • fs.lchownSync
  • fs.linkSync
  • fs.lstatSync
  • fs.lutimesSync
  • fs.mkdirSync
  • fs.openSync
  • fs.readdirSync
  • fs.readFileSync
  • fs.readlinkSync
  • fs.readSync
  • fs.realpathSync
  • fs.renameSync
  • fs.statSync
  • fs.symlinkSync
  • fs.truncateSync
  • fs.unlinkSync
  • fs.utimesSync
  • fs.writeFileSync
  • fs.writeSync

Bun also includes an implementation of Node's SystemError with pretty printing. Note that since source maps are not implemented yet, sometimes the line:column will be off by a little.

image

This is what the same error looks like in Node

image

Node.js process object

bun.js has more support for the process object from Node.js.

// These work now in bun.js
process.chdir("insert-dir-name-here");
process.cwd();
// arguments used to launch, excluding "run" if via "bun run" for compatibility with npm packages
process.argv;
// current process id
process.pid;
// parent process pid
process.ppid;

// returns bun's version
process.version

process.versions
{
  // fake version for compatibility with npm packages potentially looking this up
  "node": "17.0.0",
  "modules": "67",
  // bun version
  "bun": "0.0.68",
  // git shas/tag of bun dependencies
  "webkit": "96e77eccfde8dc9c207520d8ced856d8bdb8d386",
  "mimalloc": "f412df7a2b64421e1f1d61fde6055a6ea288e8f5",
  "libarchive": "dc321febde83dd0f31158e1be61a7aedda65e7a2",
  "picohttpparser": "066d2b1e9ab820703db0837a7255d92d30f0c9f5",
  "boringssl": "b3ed071ecc4efb77afd0a025ea1078da19578bfd",
  "zlib": "959b4ea305821e753385e873ec4edfaa9a5d49b7",
  "zig": "0.10.0-dev.315+4d05f2ae5"
}

// process.nextTick() is now implemented (currently only supports up to 4 arguments)
process.nextTick(() => console.log("second"));
console.log("first");

More stuff

import.meta in bun.js returns an object with file and dir

const {
  // import.meta.dir returns absolute path to the directory the script is in. sort of like __dirname
  dir,
  // import.meta.file returns absolute path to the script
  file,
} = import.meta;
  • queueMicrotask is implemented
  • If bun exits due to running out of file descriptors, bun will print some platform-specific instructions explaining how to fix it.
  • No longer need a ./ to run a script with bun.js, e.g. instead of bun ./foo.js, bun foo.js works now
  • Bun actually detects .mjs or .mts files now and treats them as ESM. Before it was reading them but ignoring the extension
  • Fixed a couple regressions that caused bun to start up slower, now it's back to about 3.5ms on macOS aarch64 and 0.5ms on linux amd64
  • Fixed a bug in the upgrade checker that would sometimes cause bun to crash, typically after about 30 seconds
  • Bun.gc(force) lets you manually run the garbage collector
  • Bun.shrink() runs a JavaScriptCore VM function that attempts to shrink the amount of memory used by JavaScriptCore
  • Bun.generateHeapSnapshot() returns a heap snapshot in a format I'm not entirely sure how to visualize yet

If you look hard enough, you'll also find a new subcommand for a very incomplete but fast Jest-like test runner. Hopefully will talk more about that next release or the one after.

Thanks

bun - bun v0.0.66

Published by Jarred-Sumner almost 3 years ago

To upgrade:

bun upgrade

These changes are since bun v0.0.56 (the previous release notes 13 days ago)

TLDR:

  • ~25% faster bun install when packages aren't downloaded
  • 5% faster JavaScript parser
  • Many bugfixes to bun install (but still more work to do!)
  • Improved filesystem watcher reliability on Linux
  • Docker images

bun install:

~25% faster when downloading lots of new packages. devDependencies were incorrectly being prioritized.

image

Plus:

  • bun add @scoped/package works now
  • >= ranges for package versions work correctly now
  • Fixed a bug in the retry logic for the HTTP client that would sometimes cause undefined memory to be returned. There still is more work to be done on the HTTP client to improve reliability.
  • On some Linux machines, bun install would error with error: SystemResources. This is an issue with the memlock limit that impacts io_uring. Now bun lowers memlock usage when this error returns until it finds a value that works
  • On Linux, bun had a dependency on glibc 2.32 which is too new for many machines. Now it depends on glibc 2.29
  • "no compatible binaries" error message was printing bytes instead of the string
  • Fixed a crash when removing the only dependency in package.json. When there are no dependencies in package.json, bun install will delete the lockfile
  • On Linux, when /tmp was mounted on a different filesystem, extracting packages failed with error: RenameAcrossMountPoints. Now bun tests if it can rename files from the temporary directory to the cache directory and chooses a different temporary directory if it cannot
  • Better error handling if lockfile is invalid or package.json is not found
  • bun install --production works better now. Just before installing, it clones the original lockfile in-memory and then removes any devDependencies listed in the root package.json.

bun run

  • Passing an absolute path to a JavaScript-like file will run the file with bun.js. Before, absolute paths were ignored

bun dev

Improved filesystem watcher reliability on Linux

bun now handles atomic file updates better in the filesystem watcher. To filesystem watchers, atomic file updates appear as a delete followed by a new file being moved to an existing directory. bun previously only noticed the delete. Most editors do not save atomically, but if vim swapfiles are enabled or if using replit, this may help.

Improved support for reverse-proxying bun

Due to same-origin policy, bun's HMR needs to use absolute URLs that match what the browser expects. Previously, to proxy bun you had to pass --origin to bun dev and it would maybe still not work for https. Now bun reads headers proxies send & what browsers send to determine which protocol, host, and/or origin is expected.

Misc:

  • If you use tailwind, it only warns once that @tailwind is not supported instead of on every single request to that .css file

bun-framework-next

  • A regression broke fetch() in SSR. This is fixed
  • The lack of a URL polyfill broke navigation in some cases. Now there is a URL polyfill. Eventually, bun.js will have this as a builtin implemented in native code.

bun.js

  • Add Bun.argv which returns string[] containing the CLI arguments used to open the currently running process. It is basically process.argv

bun bun

DevContainer

If you're interested in contributing to bun, you can now use a VSCode DevContainer to quickly setup the dev environment. Note that it currently requires at least 11 GB of ram in the dockerized OS to compile debug builds of bun.

Docker

bun now has automatic docker releases for Linux AMD64 compiled on every push to main. The tag name is jarredsumner/bun:${gitSHA}

Zig upgrade

bun is now using the latest version of Zig and LLVM 13, instead of a hacky patched version of Zig. This was a large change affecting basically every file in bun.

image

JavaScript Parser

5% faster JavaScript parser

image

Crash reporter

If bun crashes, it reports a little more metadata now and (on macOS) save a crash report to disk.

image

Sublime Text plugin for bun.lockb

@alexkuz wrote a Sublime Text plugin that opens bun.lockb (the lockfile for bun install) as a yarn.lock file and adds syntax highlighting. Thank you @alexkuz!

image

GitHub: https://github.com/alexkuz/sublime-yarn-lock

Thanks

  • Thanks @alexkuz and @afonsoduarte for fixing typos in the readme
  • Thanks @ylukem for replacing all usages of Bun with bun
bun - Bun v0.0.56

Published by Jarred-Sumner almost 3 years ago

To upgrade:

bun upgrade

bun install

Today is an exciting day. Introducing bun install – an incredibly fast npm client.

Before I get into perf numbers, consider this especially early.

  • workspaces not implemented yet
  • link: not implemented yet
  • github: not implemented yet
  • git: not implemented yet
  • Config file where you can set registry and auth tokens is not implemented yet. That means private packages won't really work yet (though it does read $npm_config_registry)
  • The lockfile format may change a little in the coming weeks (which would invalidate existing lockfiles)
  • postinstall will not be supported (probably won't be opt-in either). esbuild and turbo get special treatment I'm calling "native bin linking". I plan to write a more generalizable proposal for this that other npm clients can adopt to make shipping binary executables on npm faster & simpler
  • node-gyp isn't supported yet either, but that will be fixed.

Linux

100x faster npm install for incremental installs. In this case, only react is missing (the cleanup resets node_modules), each package manager has an up-to-date lockfile, and packages have previously downloaded before (disk cache)

20x faster than npm install when node_modules is empty. In this case, each package manager has an up-to-date lockfile and packages have also been downloaded before.

image

When there are no changes, bun install is 100x faster than npm install

image

macOS

Note: currently macOS installs are single-threaded & parallelism may help when there are > 100 packages, so these numbers may improve later

80x faster npm install for incremental installs.

image

4x faster npm install when there is no node_modules folder

image

When there are no changes, 80x faster than npm install

image

Autocomplete

Thanks to @evanwashere, bun add has autocomplete for the top 10,000 npm packages. It also searches your shell's history to complete from.

Screen_Recording_2021-12-19_at_11 32 08_PM

Fish completions:

image

Why is it faster?

I will do a longer write up on why it's faster. Zig is part of that, but a lot of work went into data layout, the lockfile format, the https client, the manifest cache format, and a lot of other stuff.

bun - Bun v0.0.55

Published by Jarred-Sumner almost 3 years ago

This release is mostly just bug fixes.

CommonJS <> ESM interop reliability improvements

Bun now preserves the behavior of live bindings when referencing bundled symbols. This fixes a number of subtle bugs in different packages.

This also updates the preferred extension order depending on how code is imported. Previously, .mjs files were ignored and that was silly. Now, when you use import and the path has no file extension, Bun will attempt to load .mjs or .mts before trying .js or .cjs

// CommonJS or `require`, `require.resolve`
// configurable via --extension-order CLI flag
pub const ExtensionOrder = [_]string{
    ".tsx",
    ".ts",
    ".jsx",
    ".cts",
    ".cjs",
    ".js",
    ".mjs",
    ".mts",
    ".json",
};

// ES Modules or `import`
pub const ModuleExtensionOrder = [_]string{
    ".tsx",
    ".jsx",
    ".mts",
    ".ts",
    ".mjs",
    ".js",
    ".cts",
    ".cjs",
    ".json",
};

Template literal parsing bug

Before, this code caused an assertion failure in Bun's JavaScript parser due to the function being defined in the template tag:

import styled from 'styled-components'

export const HoverableBox = styled.div.attrs<{
  disabled?: boolean
}>(({ disabled }) => ({
  cursor: disabled ? undefined : 'pointer',
}))<{ disabled?: boolean }>`
  ${({ disabled }) => (disabled ? 'pointer-events: none;' : '')}
`

The problem was related to when scopes for template literal tags were visited. This has been fixed.

try & require()

Previously, this code would produce a build error:

try {
  require("this-package-should-not-exist");
} catch (exception) {}

try {
  await import("this-package-should-not-exist");
} catch (exception) {}

import("this-package-should-not-exist").then(
  () => {},
  () => {}
);

In each of these cases, errors are caught at runtime, so it should not produce a build error.

Top-level await is now enabled

Top-level await will no longer error when targeting browsers, however you should know that since Bun does not transpile for backwards compatibility, you will need to be sure it is safe to use in the target environment.

Using module.exports with top-level await is undefined behavior

bun - Bun v0.0.46

Published by Jarred-Sumner almost 3 years ago

To upgrade:

bun upgrade

Like last release, this one is mostly bug fixes.

Better ZSH completions

The zsh completions now include flags, descriptions of subcommands, and "scripts" appear above package bins.

Also:

  • Filter out post.* and pre.* scripts from completions
  • Filter out .js files that start with . from completions
  • Filter out builtin commands from showing up at the top

The plugin for the typeahead here is zsh-autocomplete

macOS Mojave & macOS Catalina support

For absolutely no good reason, Bun was not able to run on any macOS version before macOS 11. Now bun should work for macOS Mojave and macOS Catalina.

However, I don't have a test machine so please let me know if it still doesn't work.

Bug fixes:

  • [resolver] Fix a bug with importing modules from packages using /*.extension in "exports" package.json and improve test coverage
  • [internal] Improve error messages when Bun fails to build due to a missing dependency
  • [zsh] zsh completions should more reliably find a directory to put them in
  • [zsh] Command not found: compdef previously appeared if zsh completions weren't installed. That's fixed now
bun - Bun v0.0.45

Published by Jarred-Sumner almost 3 years ago

To upgrade:

bun upgrade

This release is mostly bug fixes.

Improved fish completions

  • less noisy: no more file paths unless relevant and package executables are shown on bun run instead of bun
  • Before the description for a script was "script", now it's the actual script
  • If the first part of the script is NODE_OPTIONS=".*" (or any variation of NODE_OPTIONS), it's stripped out from the description. This is slightly nicer for larger repos that set --max-heap-size

bun

bun run:

Bug fixes

  • [bun run] Fix bug when running bun run yarn or a script that runs yarn --prod
  • [bun run] Fix a bug with how quotes & spaces were being passed through
  • [bun create] Fix npm install/yarn install for people using Volta (symlinks)
  • [bun run] Fix invoking node when using Volta (symlinks)
  • [JSX parser] Match esbuild behavior for JSX multi-line string literals and improve test coverage
  • [JSX parser] Fix regression with decoding JSX entities (e.g. &amp;) and improve test coverage
  • [JS parser] Decode input as WTF-8 instead of UTF-8. Insert a unicode replacement character for invalid unicode codepoints. Amongst other things, this fixes an error that occurred on require("faker")
  • [installer] Auto-detect when an Apple Silicon device is running on Rosetta 2 and download the arm64 version instead

Full Changelog: https://github.com/Jarred-Sumner/bun/compare/bun-v0.0.44...bun-v0.0.45

bun - Bun v0.0.44

Published by Jarred-Sumner almost 3 years ago

To upgrade:

bun upgrade

Next.js 12

Bun works with Next.js 12 now. Before, it only supported 11.1.2. This includes support for React 18 (react@alpha). React Server Components is not supported yet, but it will be. I promise :)

Other stuff

  • (bun run) ZSH completions should auto-install correctly now. This will automatically apply when you run bun upgrade
  • (bun dev) Fixed a mistranspilation when using require from app code to a bundled module (e.g. require("relay-devtools"))
  • (bun bun) Fixed an issue with symlinked workspace packages when using alwaysBundle that prevented them from being correctly imported if enough levels of indirection were added
  • Fixed undefined behavior when invalid UTF-8 codepoints were inside source code text printed in an error message
  • (bun-macro-relay) Worked around a bug that could cause it to not correctly import graphql depending on the environment
  • (bun create) bumped the hardcoded Next.js version set to 12.0.2
  • Bun.js: rename Bun.sleep -> Bun.sleepSync

Full Changelog: https://github.com/Jarred-Sumner/bun/compare/bun-v0.0.42...bun-v0.0.44

bun - Bun v0.0.42

Published by Jarred-Sumner almost 3 years ago

To upgrade:

bun upgrade

tab completions for bun run

bun run now has tab completions for zsh and fish that show scripts from package.json and bins from node_modules/.bin.

Install:

bun upgrade
bun completions 

Going forward, bun upgrade also updates completions, so you shouldn't have to do that again.

Bun.js

Bun now has a builtin "supports-color" polyfill, the package used by chalk to detect ANSI color support.

The TypeScript in this screenshot runs 2x faster in Bun.js than in Node.js:

image

Other stuff:

  • node-fetch & isomorphic-fetch polyfills work now. When an npm package imports node-fetch, Bun.js will automatically replace it with Bun's native implementation.
  • Bun.sleep(ms) lets you synchronously sleep. No promises
  • Fixed an edgecase with the CommonJS transform that affected export default (thank you @evanwashere for flagging)
  • Several more encoding issues specific to the JavaScriptCore integration were found & fixed, though there are a couple more I still need to fix.

JavaScript Lexer

  • Fixed a regression with \0 (and added an integration test)

Misc

  • --version now prints a newline at the end
  • -v is now shorthand for --version
  • Fixed spacing with the CLI help menu (thanks @KishanBagaria for flagging)
  • -u is now shorthand for --origin. Might rename that to --url in a future release.
bun - Bun v0.0.41

Published by Jarred-Sumner almost 3 years ago

To upgrade:

bun upgrade

What's new:

bun run:

bun run ./file.js now supports running JavaScript, TS, TSX, and JSX files using Bun.js. If you pass bun run a filepath to a .js, .jsx, .tsx, or .ts file, it will run it with Bun.js instead of saying "error: Missing script". This is very experimental!

Bun.js

Bun.js is Bun's JavaScript runtime environment.

  • Top-level await works now
  • performance.now() is implemented

Bug fixes

  • [.env loader] functions from bash were exported incorrectly due to parsing process environment variables similarly to .env files which is unnecessary. Now process environment variables are passed through without extra parsing
  • fetch() wasn't working due to a silly mistake. That's fixed
bun - Bun v0.0.40

Published by Jarred-Sumner almost 3 years ago

It's been a busy couple weeks.

Important: the bun-cli npm package is deprecated. It will not receive updates.

Please upgrade Bun by running:

# Remove the npm version of bun
npm uninstall -g bun-cli

# Install the new version
curl https://bun.sh/install | bash

For future upgrades:

bun upgrade

Now the fun part.

bun run

~35x faster package.json "scripts" runner, powered by Bun. Instead of npm run, try bun run.

Like npm run, bun run reads "scripts" in your package.json and runs the script in a shell with the same PATH changes as npm clients. Unlike npm clients, it's fast.

You can use bun run in projects that aren't using Bun for transpiling or bundling. It only needs a package.json file.

When scripts launch a Node.js process, bun run still beats npm run by 2x:

Why? Because npm clients launch an extra instance of Node.js. With npm run, you wait for Node.js to boot twice. With bun run, you wait once.

For maximum performance, if nested "scripts" run other npm tasks, bun run automatically runs the task with Bun instead. This means adding many tasks won't slow you down as much.

bun run supports lifecycle hooks you expect like pre and post and works when the package.json file is in a parent directory.

Two extra things:

  • bun run also adds any node_modules/.bin executables to the PATH, so e.g. if you're using Relay, you can do bun run relay-compiler and it will run the version of relay-compiler for the specific project.
  • bun run has builtin support for .env. It reads: .env.local, then .env.development || .env.production (respecting your NODE_ENV), and .env in the current directory or enclosing package.json's directory

Oh and you can drop the run:

Reliability

Lots of work went into improving the reliability of Bun over the last couple weeks.

Here's what I did:

  • Rewrote Bun's filesystem router for determinism and to support catch-all + optional-catch-all routes. This is an oversimplification, but the routes are sorted now
  • Improved testing coverage. Bun now has integration tests that check a simple Next.js app bundles & server-side prerenders successfully. If JavaScriptCore's JIT is not enabled while server-side rendering, the tests fail. Another integration test checks that a simple Create React App loads. It uses bun create to bootstrap the projects.
  • Fix all known unicode encoding & decoding bugs. Part of what makes parsing & printing JavaScript complicated is that JavaScript officially uses UTF-16 for strings, but the rest of the files on your computer likely use UTF-8. This gets extra complicated with server-side rendering because JavaScriptCore expects either a UTF-16 string for source code or a UTF-8 string. UTF-16 strings use about twice as much memory as UTF-8 strings. Instead of wasting memory, Bun escapes the strings where necessary (but only for server-side rendering)
  • Fixed several edgecases with the .env loader. .env values are now parsed as strings instead of something JSON-like

There's still a lot of work ahead, but Bun is getting better.

Sometimes, speed and reliability is a tradeoff. This time, it's not. Bun seems to be about 3% faster overall compared to the last version (v0.0.36). Why? Mostly due to many small changes to the lexer. Inlining iterators is good.

bun - Bun v0.0.36

Published by Jarred-Sumner about 3 years ago

bun create

bun create is a new subcommand that lets you quickly create a project from a template.

this

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 supports Transfer-Encoding: chunked. It didn't before, which was embarrassing.
  • Set self to globalThis in Bun.js. This improves compatibility with some npm packages
  • There are two new test binaries in misctools/, tgz and fetch. tgz is like gunzip except harder to use and fetch is sort of like curl? These are really just to help me test some things in isolation from the rest of Bun
bun - Bun v0.0.34

Published by Jarred-Sumner about 3 years ago

Features

Slightly better tsconfig.json handling:

  • jsxImportSource support – if you set jsxImportSource 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 <> becomes React.Fragment normally.
  • jsxFactory support – if you set jsxFactory to "h", when using the classic JSX runtime, it will run h instead of createElement

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 - Bun v0.0.32

Published by Jarred-Sumner about 3 years ago

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 - Bun v0.0.29

Published by Jarred-Sumner about 3 years ago

5% end-to-end performance improvement by reducing allocations for Identifiers in the JavaScript/TypeScript parser.

image

Also, bun-cli wasn't installing on Linux correctly. Now it is!

bun - Bun v0.0.28

Published by Jarred-Sumner about 3 years ago

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 - Bun v0.0.27

Published by Jarred-Sumner about 3 years ago

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 accepts default, which is the default import alias and you can pass a namespace 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 - Bun v0.0.26

Published by Jarred-Sumner about 3 years ago

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 and Bun.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() (from fetch)
  • 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 a User-Agent header by default. This is overridable, but it defaults to Bun.js v0.0.version-number
bun - Bun v0.0.24

Published by Jarred-Sumner about 3 years ago

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