Using Parcel as Build Tool for Phoenix

Phoenix Framework is a Web Application Framework built in Elixir. With the recent 1.6 version release, Phoenix has no nodejs dependency. Prior to that, Phoenix used webpack as the build framework for static assets, CSS and JS. However, from version 1.6, Phoenix uses Esbuild as the build tool. The Esbuild package for Phoenix Framework can be found at

Esbuild for Javascript bundling and minification reduced the build times dramatically. The default generator for Phoenix creates the new application with Milligram as the default CSS framework. However, most people would need atleast SCSS support for their application. When you want to have an SCSS based framework or you want to write your design with SCSS, another package %[github.com/CargoSense/dart_sass] is used. This package creates a wrapper around the dart_sass cli and allows us to use scss inside our phoenix application. However, tailwindcss has been the goto CSS framework for a lot of developers in recent times. If you want to use tailwindcss in your Phoenix application, Tailwind package is provided, which is a wrapper around the tailwindcss-cli tool. So, in most cases, you can get started with application development in Phoenix without having to install nodejs ecosystem. However, tailwindcss-cli comes with some limitations.

  • It is not possible to use stylesheets with postcss-import or postcss-nested
  • tailwindcss-cli comes bundled with only official plugins. It is not possible to use any external plugins like daisyui or tailwind-scrollbar etc. which are used frequently by developers.

To meet these requirements invariably, we have to get into some node based build tool. A complete overview of asset management in Phoenix Framework can be found at Phoenix Asset Management. Apart from the regular webpack new age build tools like vite and parcel are used by Phoenix developers for asset management. In this article, we will explore integrating parcel as the build tool into a Phoenix application.

, calls itself as zero configuration build tool for various types of applications and libraries. parcel caught developer attention recently for the extremely fast parcel-css - a CSS parser, transformer and minifier written in Rust. parcel-css can be our one stop shop for CSS processing. It allows us to get rid of the entire host of postcss plugins. Enough of history lessons. Time for some hands-on coding.

Let us create a new phoenix application.

mix phx.new my_app

creates a new phoenix application with esbuild as the build tool.

Remove Esbuild

Removing esbuild from the application involves mainly 4 steps.

  1. Remove the esbuild configuration in config/config.exs and config/dev.exs
  2. Remove the assets.deploy task defined in mix.exs
  3. Remove the esbuild dependency from mix.exs
  4. Unlock the esbuild dependency

If you open config/config.exs file you would find a code snippet similar to this

# Configure esbuild (the version is required)
config :esbuild,
  version: "0.14.29",
  default: [
    args:
      ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

These lines configure the esbuild tool. Remove these lines and save the file. Then open config/dev.exs file. You would find in the watchers list a line like this

    # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}

This line downloads the esbuild executable and sets up a watcher for changes in css and javascript files. Remove these lines and save the file. These two changes will complete the step 1. Now, open the mix.exs file - and at the bottom, in the function list of aliases, under the "assets.deploy" task, you will find "esbuild default --minify",. Remove that part. That completes step 2. Now, in the same mix.exs file in the functiond defp deps you will find an entry for the esbuild module. The line will be something like {:esbuild, "~> 0.4", runtime: Mix.env() == :dev},. Remove the line and save the file. This completes step 3. And finally moving on to step 4. In the command line type and execute

mix deps.unlock esbuild

These 4 steps allow you to complete remove esbuild from the application. Now, let us move on to integrating parcel as the build tool for both css and javascript in the phoenix application. We will integrate tailwindcss also as part of the process. It is a regular practice for phoenix developers to keep everything related to static assets in the folder assets. Even the build tool configuration, tailwindcss configuration etc. are also kept in the assets folder normally. However, the parcel watcher is not working correctly if we install parcel in the assets folder. It needs to be configured from the application root folder. However, we can keep all the static assets still in the assets folder. From the root folder, execute the command

yarn add -D parcel tailwindcss

We need to make one change in our .gitignore file - to change assets/node_modules to node_modules as the node_modules directory will be in the application root directory now. Similarly, add the .parcel-cache directory to .gitignore file. Now, we have to add two tasks in the package.json file for watch and build Open your package.json file and add the following code:

  "scripts": {
    "watch": "parcel watch assets/js/app.js --dist-dir priv/static/assets",
    "build": "parcel build assets/js/app.js --dist-dir priv/static/assets"
  },

Here we are adding two tasks - watch and build in both cases we are taking assets/js/app.js as the input file and --dist-dir is the output directory. parcel handles both css and js also with almost zero configuration. Remember that we have a line

import "../css/app.css"

in the app.js file. So, both css and js files are handled with the single input file app.js and parcel generates two output files app.css and app.js in the --dist-dir folder. Now, we have to add a watcher in config/dev.exs to watch the files for changes and reload. Open config/dev.exs and add the following line to empty watchers list ( from where you removed the esbuild line earlier)

 yarn: ["run", "watch", cd: Path.expand("../assets", __DIR__)]

We have another small task to perform to configure parcel build for production. Open mix.exs file and in the function aliases, for the task "assets.deploy" ( the same place you removed esbuild default minify) add the task

"yarn build",

before the phx.digest task.

Finally, because we have removed the esbuild the 3 javascript libraries that are required for Phoenix, have to be installed from the local deps using yarn. At your terminal, type the command:

 yarn add "./deps/phoenix" "./deps/phoenix_html" "./deps/phoenix_live_view"

It installs these packages from the local deps. At this stage, if we want to use regular css or scss we are good to go. parcel true to its claim, with no further configuration will work - handling both css and js files. However, if we want to configure tailwindcss we have a few more steps to go. tailwindcss is considered as a postcss plugin and processed by parcel-css. parcel-css honors any postcss configuration in the same directory if the file is specified as .postcssrc. So create a file .postcssrc in the application root directory and add the following code

{
  "plugins": {
    "tailwindcss": true,
    "postcss-import": true,
  }
}

We add two plugins - tailwindcss and the postcss-import so that we can write our custom css in different files and import them. Now, the regular tailwindcss configuration is all that is pending. We need to import the tailwindcss css files in our app.css and create a tailwind.config.js for tailwind configuration. Let us create a tailwind.config.js file in our app root directory and paste the following code into it:

module.exports = {
  content: ["./assets/js/**/*.js", "./lib/*_web.ex", "./lib/*_web/**/*.*ex"],
  darkMode: "class",
  theme: {
  },
  plugins: [],
};

Pay attention to the relative folder reference. We are not in assets directory but we are in application root directory, hence the change. Now, let us import tailwindcss css files. Open assets/css/app.css file. You will observe that there is a line @import "./phoenix.css"; which actually imports the milligram css into the file. Remove that and paste the following:

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

Now, we have tailwindcss integrated into our application. Let us test it out. Open the file lib/my_app_web/templates/page/index.html.heex and go to,

and the first hero section code is available for free. Copy and paste the code into above file. Now, run

mix phx.server

Open the browser and go to localhost:4000 and you will find that tailwindcss is working well. You can make any changes to your code and can observe that even live reload also is working well. These are the sequence of steps you have to execute to integrate parcel as the build tool for phoenix framework.

You can find the complete application at,

Hope you find this walk-through useful.