How to build separate assets of multi Phoenix app in umbrella

I have two Phoenix apps in umbrella but get stuck when build assets for each Phoenix app because umbrella using root config and Phoenix apps generated same config key for esbuild.

example config/config.exs

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

as above config file, I just have one last is used for all Phoenix apps. When I run mix assets.build only app have corrected assets.

I need to separate config esbuild for every Phoenix apps, anyone has any idea for this case?

According to esbuild docs, you can define multiple profiles under the same config key. Something like this:

in config/config.exs

config :esbuild,
  version: "0.17.11",
  back: [
    args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets) ...,
    cd: Path.expand("../apps/back/assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ],
  front1: [
    args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets) ...,
    cd: Path.expand("../apps/front1/assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

then in mix.exs

  defp aliases do
    [
      "assets.build": ["esbuild back", "esbuild front1"],
      "assets.deploy": [
        "esbuild back --minify",
        "esbuild front1 --minify",
        "phx.digest apps/back/priv/static -o some/path",
        "phx.digest apps/front1/priv/static -o some/path"]
    ]
  end
5 Likes

Thank you for your support, it works!

I also apply for tailwind like esbuild and it works too!

my config:

config.exs:

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

config :tailwind,
  version: "3.2.7",
  back: [
    args: ~w(
      --config=tailwind.config.js
      --input=css/app.css
      --output=../priv/static/assets/app.css
    ),
    cd: Path.expand("../apps/back/assets", __DIR__)
  ],
  front1: [
    args: ~w(
      --config=tailwind.config.js
      --input=css/app.css
      --output=../priv/static/assets/app.css
    ),
    cd: Path.expand("../apps/front1/assets", __DIR__)
  ]

...

config :back, Back.Endpoint,
  ...
  watchers: [
    esbuild: {Esbuild, :install_and_run, [:back, ~w(--sourcemap=inline --watch)]},
    tailwind: {Tailwind, :install_and_run, [:back, ~w(--watch)]}
  ]

...
config :front1, Front1.Endpoint,
  ...
  watchers: [
    esbuild: {Esbuild, :install_and_run, [:front1, ~w(--sourcemap=inline --watch)]},
    tailwind: {Tailwind, :install_and_run, [:front1, ~w(--watch)]}
  ]

apps\back\mix.exs:

  ...
  defp aliases do
    [
      setup: ["deps.get", "assets.setup", "assets.build"],
      test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
      "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
      "assets.build": ["tailwind back", "esbuild back"],
      "assets.deploy": ["tailwind back --minify", "esbuild back --minify", "phx.digest"]
    ]
  end

apps\front1\mix.exs:

  ...
  defp aliases do
    [
      setup: ["deps.get", "assets.setup", "assets.build"],
      test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
      "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
      "assets.build": ["tailwind front1", "esbuild front1"],
      "assets.deploy": ["tailwind front1 --minify", "esbuild front1 --minify", "phx.digest"]
    ]
  end
2 Likes