164 lines
4.5 KiB
Markdown
164 lines
4.5 KiB
Markdown
|
# Esbuild
|
||
|
|
||
|
[![CI](https://github.com/phoenixframework/esbuild/actions/workflows/main.yml/badge.svg)](https://github.com/phoenixframework/esbuild/actions/workflows/main.yml)
|
||
|
|
||
|
Mix tasks for installing and invoking [esbuild](https://esbuild.github.io/).
|
||
|
|
||
|
## Installation
|
||
|
|
||
|
If you are going to build assets in production, then you add
|
||
|
`esbuild` as dependency on all environments but only start it
|
||
|
in dev:
|
||
|
|
||
|
```elixir
|
||
|
def deps do
|
||
|
[
|
||
|
{:esbuild, "~> 0.7", runtime: Mix.env() == :dev}
|
||
|
]
|
||
|
end
|
||
|
```
|
||
|
|
||
|
However, if your assets are precompiled during development,
|
||
|
then it only needs to be a dev dependency:
|
||
|
|
||
|
```elixir
|
||
|
def deps do
|
||
|
[
|
||
|
{:esbuild, "~> 0.7", only: :dev}
|
||
|
]
|
||
|
end
|
||
|
```
|
||
|
|
||
|
Once installed, change your `config/config.exs` and [pick a version
|
||
|
for the esbuild CLI](https://github.com/evanw/esbuild/releases) of your choice:
|
||
|
|
||
|
```elixir
|
||
|
config :esbuild, version: "0.18.6"
|
||
|
```
|
||
|
|
||
|
Now you can install esbuild by running:
|
||
|
|
||
|
```bash
|
||
|
$ mix esbuild.install
|
||
|
```
|
||
|
|
||
|
And invoke esbuild with:
|
||
|
|
||
|
```bash
|
||
|
$ mix esbuild default assets/js/app.js --bundle --minify --target=es2016 --outdir=priv/static/assets/
|
||
|
```
|
||
|
|
||
|
The executable is kept at `_build/esbuild-TARGET`.
|
||
|
Where `TARGET` is your system target architecture.
|
||
|
|
||
|
## Profiles
|
||
|
|
||
|
The first argument to `esbuild` is the execution profile.
|
||
|
You can define multiple execution profiles with the current
|
||
|
directory, the OS environment, and default arguments to the
|
||
|
`esbuild` task:
|
||
|
|
||
|
```elixir
|
||
|
config :esbuild,
|
||
|
version: "0.18.6",
|
||
|
default: [
|
||
|
args: ~w(js/app.js),
|
||
|
cd: Path.expand("../assets", __DIR__)
|
||
|
]
|
||
|
```
|
||
|
|
||
|
When `mix esbuild default` is invoked, the task arguments will be appended
|
||
|
to the ones configured above. Note profiles must be configured in your
|
||
|
`config/config.exs`, as `esbuild` runs without starting your application
|
||
|
(and therefore it won't pick settings in `config/runtime.exs`).
|
||
|
|
||
|
## Adding to Phoenix
|
||
|
|
||
|
To add `esbuild` 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`:
|
||
|
|
||
|
```elixir
|
||
|
def deps do
|
||
|
[
|
||
|
{:phoenix, github: "phoenixframework/phoenix", branch: "v1.5", override: true},
|
||
|
{:esbuild, "~> 0.7", runtime: Mix.env() == :dev}
|
||
|
]
|
||
|
end
|
||
|
```
|
||
|
|
||
|
Now let's change `config/config.exs` to configure `esbuild` to use
|
||
|
`assets/js/app.js` as an entry point and write to `priv/static/assets`:
|
||
|
|
||
|
```elixir
|
||
|
config :esbuild,
|
||
|
version: "0.18.6",
|
||
|
default: [
|
||
|
args: ~w(js/app.js --bundle --target=es2016 --outdir=../priv/static/assets),
|
||
|
cd: Path.expand("../assets", __DIR__),
|
||
|
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
|
||
|
]
|
||
|
```
|
||
|
|
||
|
> 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:
|
||
|
|
||
|
```elixir
|
||
|
esbuild: {Esbuild, :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:
|
||
|
|
||
|
```elixir
|
||
|
"assets.deploy": ["esbuild default --minify", "phx.digest"]
|
||
|
```
|
||
|
|
||
|
## Third-party JS packages
|
||
|
|
||
|
If you have JavaScript dependencies, you have two 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 `npm install topbar --save` inside your assets
|
||
|
directory and `esbuild` will be able to automatically
|
||
|
pick them up:
|
||
|
|
||
|
import topbar from "topbar"
|
||
|
|
||
|
## CSS
|
||
|
|
||
|
`esbuild` has basic support for CSS. If you import a css file at the
|
||
|
top of your main `.js` file, `esbuild` will also bundle it, and write
|
||
|
it to the same directory as your `app.js`:
|
||
|
|
||
|
```js
|
||
|
import "../css/app.css"
|
||
|
```
|
||
|
|
||
|
However, if you want to use a CSS framework, you will need to use a separate tool.
|
||
|
Here are some options to do so:
|
||
|
|
||
|
* Use [standalone Tailwind](https://github.com/phoenixframework/tailwind) or
|
||
|
[standalone SASS](https://github.com/CargoSense/dart_sass). Both similar to
|
||
|
`esbuild`.
|
||
|
|
||
|
* You can use `esbuild` plugins (requires `npm`). See [Phoenix' official
|
||
|
guide on using them](https://hexdocs.pm/phoenix/asset_management.html).
|
||
|
|
||
|
## License
|
||
|
|
||
|
Copyright (c) 2021 Wojtek Mach, José Valim.
|
||
|
|
||
|
esbuild source code is licensed under the [MIT License](LICENSE.md).
|