Asset Management
Beside producing HTML, most web applications have various assets (Javascript, CSS, images, fonts and so on).
Phoenix applications use esbuild to prepare assets via the Elixir esbuild wrapper.
This direct integration with esbuild means that newly generated applications do not have dependencies on Node.js or an external build system (e.g. Webpack).
Custom Builds
There are cases where you will want to customize your assets build to use another tool, or use esbuild in ways that go beyond the possibilities of the default system.
The main changes that you will need to make are:
- Change the
assets.deploy
task defined inmix.exs
, - Replace the
esbuild
configuration inconfig/config.exs
andconfig/dev.exs
, - Remove the
esbuild
dependency frommix.exs
, - Unlock the
esbuild
dependency:
$ mix deps.unlock esbuild
A Custom esbuild Setup
Phoenix's default configuration of esbuild (via the Elixir wrapper) does not allow you to use esbuild plugins. If you want to use an esbuild plugin, for example to compile SASS files to CSS, you can replace the default build system with a custom build script.
The following is an example of a custom build using esbuild via Node.JS.
First of all, you'll need to install Node.js in development and make it available for your production build step.
Then you'll need to add esbuild to your Node packages:
npm install esbuild --save-dev
or, for Yarn:
yarn add --dev esbuild
Next, add a custom Javascript build script. We'll call the example assets/build.js
:
const esbuild = require('esbuild')
const bundle = true
const logLevel = process.env.ESBUILD_LOG_LEVEL || 'silent'
const watch = !!process.env.ESBUILD_WATCH
const plugins = [
// Add and configure plugins here
]
const promise = esbuild.build({
entryPoints: ['js/app.js'],
bundle,
target: 'es2016',
plugins,
outdir: '../priv/static/assets',
logLevel,
watch
})
if (watch) {
promise.then(_result => {
process.stdin.on('close', () => {
process.exit(0)
})
process.stdin.resume()
})
}
This script works both for development (in 'watch' mode) and for the production build (the default).
For development, we just need to set the environment variable ESBUILD_WATCH
.
Modify config/dev.exs
so that the script is run whenever you change files:
config :hello, HelloWeb.Endpoint,
...
watchers: [
node: [
"build.js",
cd: Path.expand("../assets", __DIR__),
env: %{"ESBUILD_LOG_LEVEL" => "silent", "ESBUILD_WATCH" => "1"}
]
],
...
Modify the assets.deploy
task in mix.exs
:
defp aliases do
[
...
"assets.deploy": ["cmd --cd assets node build.js", "phx.digest"]
]
end
Disabling Asset Management
If you are writing an API, or for some other reason you do not need to serve any assets, you can disable asset management completely.
- Remove the
esbuild
configuration inconfig/config.exs
andconfig/dev.exs
, - Remove the
assets.deploy
task defined inmix.exs
, - Remove the
esbuild
dependency frommix.exs
, - Unlock the
esbuild
dependency:
$ mix deps.unlock esbuild