How to bundle multiple files into different directories using the EsBuild config

I have two seperate js & css files relating to two external HTML projects and I want them to be bundled into two different folders within priv/static/assets.
My current setup for one of my projects is:

config :esbuild,
  version: "0.12.18",
  default: [
    args:
      ~w(
		js/bundle-one.js js/bundle-one.css
		--bundle --target=es2017
		--outdir=../priv/static/assets/bundle_one
		--external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

How do I add a bundle-two.js and bundle-two.css to bundle into a /priv/static/assets/bundle_two folder?

FYI: I’m sure someone can tell you how to do whatever you want with the elixir wrapper for esbuild, but I really think if you need anything beyond the bare minimum, you should just use esbuild directly. It’s not difficult to do, I can provide some help if you’re interested in that.

I am not sure, because I haven’t tried, but can’t you just make a second next to :default and add a second watcher for this and a second esbuild in mix.exs, etc…

With this solution will I be able to watch for any changes to the .js and .css bundles whilst I am in dev mode running iex -S mix phx.server and have the files automatically updated in priv/static/assets?

Not sure what else you think would be more direct, given the elixir package is not really a wrapper, but just a different way of downloading the binary.

I got it working with the help of this comment and the esbuild ‘wrapper’ documentation here

What I did:

mix.exs file

  defp aliases do
    [
      ...
      "assets.deploy": ["esbuild bundle_one bundle_two --minify", "phx.digest"]
    ]
  end

dev.exs

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

config.exs

config :esbuild,
  version: "0.12.18",
  bundle_one: [
    args:
      ~w(
		js/bundle-one.js js/bundle-one.css
		--bundle --target=es2017
		--outdir=../priv/static/assets/bundle_one
		--external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ],
	bundle_two: [
    args:
      ~w(
		js/bundle-two.js js/bundle-two.css
		--bundle --target=es2017
		--outdir=../priv/static/assets/bundle_two
		--external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

Files names replaced for obvious reasons.
And it seems to be working.
Can anyone improve on this?

1 Like

Because you can interact with the NPM ecosystem directly, write your own JS script that runs ESBuild instead of relying upon it’s CLI interface, etc. I think they even say themselves that the CLI interface is meant for quick use.