Code Monkey home page Code Monkey logo

bun's Introduction

Bun Logo

Bun

Mix tasks for installing and invoking bun.

This is an adaptation of the Elixir esbuild installer made by Wojtek Mach and José Valim.

Installation

If you are going to build assets in production, then you add bun as dependency on all environments but only start it in dev:

def deps do
  [
    {:bun, "~> 1.3", runtime: Mix.env() == :dev}
  ]
end

However, if your assets are precompiled during development, then it only needs to be a dev dependency:

def deps do
  [
    {:bun, "~> 1.3", only: :dev}
  ]
end

Once installed, change your config (i.e. config/config.exs or config/runtime.exs) to pick your bun version of choice:

config :bun, version: "1.1.22"

Now you can install bun by running:

$ mix bun.install

And invoke bun with:

$ mix bun default assets/js/app.js --outdir=priv/static/assets/

The executable is kept at _build/bun. You can access it directly to manage packages and many more things:

# Install a NPM package such a htmx.org
_build/bun add htmx.org
# Install a local package such as phoenix_html
_build/bun add ./deps/phoenix_html
# Remove a dependency
_build/bun remove htmx.org

Profiles

The first argument to bun is the execution profile. You can define multiple execution profiles with the current directory, the OS environment, and default arguments to the bun task:

config :bun,
  version: "1.1.22",
  default: [
    args: ~w(build js/app.js),
    cd: Path.expand("../assets", __DIR__)
  ]

When mix bun default is invoked, the task arguments will be appended to the ones configured above.

Adding to Phoenix

To add bun to an application using Phoenix, you need only four steps. Installation requires that Phoenix watchers can accept module-function-args tuples which is not built into Phoenix 1.5.9.

First add it as a dependency in your mix.exs:

def deps do
  [
    {:phoenix, github: "phoenixframework/phoenix"},
    {:bun, "~> 1.3", runtime: Mix.env() == :dev}
  ]
end

Now let's change config/config.exs to configure bun to use assets/js/app.js as an entry point and write to priv/static/assets:

config :bun,
  version: "1.1.22",
  default: [
    args: ~w(build js/app.js --outdir=../priv/static/assets --external /fonts/* --external /images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{}
  ]

Make sure the "assets" directory from priv/static is listed in the :only option for Plug.Static in your lib/my_app_web/endpoint.ex

For development, we want to enable watch mode. So find the watchers configuration in your config/dev.exs and add:

  bun: {Bun, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}

Note we are inlining source maps and enabling the file system watcher.

Finally, back in your mix.exs, make sure you have a assets.deploy alias for deployments, which will also use the --minify option:

"assets.deploy": ["bun default --minify", "phx.digest"]

Phoenix JS libraries

By default, Phoenix comes with three JS libraries that you'll most likely use in your project: phoenix, phoenix_html and phoenix_live_view.

To tell bun about those libraries you will need to add the following to the assets/package.json file:

{
  "workspaces": [
    "../deps/*"
  ],
  "dependencies": {
    "phoenix": "workspace:*",
    "phoenix_html": "workspace:*",
    "phoenix_live_view": "workspace:*"
  }
}

and run:

_build/bun install

Third-party JS packages

If you have JavaScript dependencies, you have three options to add them to your application:

  1. Vendor those dependencies inside your project and import them in your "assets/js/app.js" using a relative path:

    import topbar from "../vendor/topbar"
    
  2. Call _build/bun add topbar inside your assets directory and bun will be able to automatically pick them up:

    import topbar from "topbar"
    

CSS

bun has support for CSS. If you import a css file at the top of your main .js file, bun will also bundle it, and write it to the same directory as your app.js:

import "../css/app.css"

License

Copyright (c) 2023 Cristian Álvarez.

bun source code is licensed under the MIT License.

bun's People

Contributors

axelson avatar crbelaus avatar hauleth avatar lostkobrakai avatar nshafer avatar pepicrft avatar wigny avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

bun's Issues

Feature request: Load runtime config by default

Currently if you configure bun in config/runtime.exs then that configuration is silently ignored, and no warning is printed when running mix bun.install (although there is a warning logged on app startup).

Is there a reason that the runtime configuration isn't loaded by default in the mix tasks? To my understanding there isn't a large performance hit in loading the runtime configuration for an application (and it's much faster than starting the application).

Fail to install Bun with Elixir 1.15 on Docker

In a CI pipeline, I'm receiving the same error reported on phoenixframework/phoenix#5502, where the module :http_util is not available making the command mix bun.install fail.

** (UndefinedFunctionError) function :http_util.timestamp/0 is undefined (module :http_util is not available)
    (inets 9.0.1) :http_util.timestamp()
    (inets 9.0.1) httpc.erl:750: :httpc.handle_request/9
    (bun 1.0.0) lib/bun.ex:276: Bun.fetch_body!/1
    (bun 1.0.0) lib/bun.ex:198: Bun.install/0
    (mix 1.15.4) lib/mix/task.ex:447: anonymous fn/3 in Mix.Task.run_task/5
    (mix 1.15.4) lib/mix/task.ex:506: Mix.Task.run_alias/6
    (elixir 1.15.4) lib/enum.ex:984: Enum."-each/2-lists^foreach/1-0-"/2
    (mix 1.15.4) lib/mix/task.ex:447: anonymous fn/3 in Mix.Task.run_task/5

While I was not able to reproduce the issue locally (running our CI pipeline based on the elixir:1.15-slim image though), ensuring :inets and :ssl are available when executing the command should solve the problem.

Need for a more detailed documentation

After reading thoroughly the README and going along with it, I still struggle to make Bun work with Phoenix.

Couple of questions to consider:

  1. What to do with esbuild? Should it run along Bun? Or maybe it should be removed?
  2. After implementing Bun in Phoenix, what's next? How do I do write my frontend with Bun?

Thank you

Consider renaming to bun

When I started working on this package I wanted to name it bun to follow the convention set by the esbuild and tailwind packages.

Unfortunately the bun package name was already taken so I had to go with the current elixir_bun name. This was also surprising for others when I did the initial release.

I took a look at Hex.pm rules for acquiring an existing package name and tried to get in touch with bun's package owner on christopherlai/bun#1 and also got in touch with the Hex.pm team as their docs suggest.

If both parties agree to transfer me the ownership of the bun package I will rename this project from elixir_bun to just bun. This should make it much easier to find and, as mentioned before, keeps the naming convention set by the esbuild and tailwind packages.

Run bun in the context of `./assets` folder

Following the documenatation on the README the lockfile as well as package.json are created in the root folder of a phoenix project. How do I make them be in the ./assets folder? I expect just moving things there won't help.

Document how to replace the default Phoenix stack with just Bun

A great idea was shared on #20 that consists on replacing the default Phoenix stack (esbuild + tailwind packages) with just Bun.

This makes a lot of sense and I believe would be a great addition to the documentation. We could have a section dedicated to how to make this change and how to configure bun build as an esbuild replacement and bun run tailwind as a tailwind replacement.

tailwindcss --watch doesn't work when used with elixir bun

I am in the process of replacing the elixir tailwindcss package with bun. To do this, I added tailwindcss as a dev dependency to my package.json. I then altered the bun config like this:

config :bun,
  version: "1.1.21",
  js: [
    args:
      ~w(build js/app.js --outdir=../priv/static/assets --external /fonts/* --external /images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{}
  ],
  css: [
    args: ~w(run tailwindcss --input css/app.css --output ../priv/static/assets/app.css),
    cd: Path.expand("../assets", __DIR__),
    env: %{}
  ]

and my dev config like this:

config :lctr, LctrWeb.Endpoint,
  watchers: [
    bun_js: {Bun, :install_and_run, [:js, ~w(--sourcemap=inline --watch)]},
    bun_css: {Bun, :install_and_run, [:css, ~w(--watch)]}
  ]

The following commands work as expected:

mix bun css: Builds the css correctly
cd assets && ./../_build/bun tailwindcss --input css/app.css --output ../priv/static/assets/app.css --watch builds the css correctly and watches for changes in the CSS

But running mix bun css --watch does nothing. No output, no css generation. The watch task also does nothing (no ouptut, no css generation). Add the --watch command the config results in the same issue.

The watch paramter works for js.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.