Can I use Esbuild version 0.19.11 instead of 0.17.11 with Phoenix LiveView?

I have a Phoenix LiveView app that I deploy with Fly.io. I am trying to use a newer version of Esbuild, because it allows me to use nested CSS while supporting older browsers.

I have changed the version of Esbuild in config.exs.

I used to be this.

# Configure esbuild (the version is required)
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("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

And now it is.

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

In development my build works as expected. My nested CSS is flattened. However, in production (Fly.io) the CSS is not flattened.

I suspect it has to do with LiveView requiring version 0.17.11. Can I use Esbuild version 0.19.11 instead of 0.17.11?

Ty.

I’m using 0.17.18 and also configuring the following:

config :esbuild,
  version: "0.17.18",
  default: [
    args: ~w(js/app.js --bundle --target=es2016,chrome58 --outdir=../priv/static/assets --external:*.woff2 --external:*.svg),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

1 Like

I tried changing the version to 0.17.18 and that did not resolve the issue.

However, on closer inspection I see that the CSS in the bundle generated by Esbuild is flattened partly. In production, that is. In development the CSS is completely flattened.

Some examples.

  1. Not flattened in production
# ORIGINAL
.separator {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  color: rgb(135, 135, 135);
  margin-block: 6px;

  p {
    font-size: 0.9rem;
    margin-top: -8px;
    letter-spacing: 0.05rem;
  }

  hr {
    border: none;
    height: 2px;
    background-color: rgb(188, 188, 188);
  }

  &.for-auth {
    p {
      margin-top: -3px;
    }
  }
}

# PROD BUNDLE
.separator {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 14px;
    color: #878787;
    margin-block:6px;p {
        font-size: .9rem;
        margin-top: -8px;
        letter-spacing: .05rem;
    }

    hr {
        border: none;
        height: 2px;
        background-color: rgb(188,188,188);
    }

    &.for-auth {
        p {
            margin-top: -3px;
        }
    }
}

# DEV BUNDLE
.separator {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  color: rgb(135, 135, 135);
  margin-block: 6px;
}
.separator p {
  font-size: 0.9rem;
  margin-top: -8px;
  letter-spacing: 0.05rem;
}
.separator hr {
  border: none;
  height: 2px;
  background-color: rgb(188, 188, 188);
}
.separator.for-auth p {
  margin-top: -3px;
}
  1. Partly flattened in production
# ORIGINAL
#layout-footer {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  height: var(--layout-footer-height);
  background-color: var(--panda-grey);
  -webkit-box-shadow: 0px 0px 9px 0px rgba(0,0,0,0.29);
  -moz-box-shadow: 0px 0px 9px 0px rgba(0,0,0,0.29);
  box-shadow: 0px 0px 9px 0px rgba(0,0,0,0.29);

  .footer-extention {
    display: none;
    position: absolute;
    bottom: 100%;
    width: 100%;
    padding: 12px;
    background-color: var(--panda-grey);
    color: white;

    .chevron-icon {
      cursor: pointer;
      position: absolute;
      top: 4px;
      right: 4px;
      border-radius: 50%;

      &:hover {
        background-color: #b04539;
      }
    }

    li {
      margin-block: 4px;
    }
  }

  # ... continues
}

# PROD BUNDLE
#layout-footer {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    height: var(--layout-footer-height);
    background-color: var(--panda-grey);
    -webkit-box-shadow: 0px 0px 9px 0px rgba(0,0,0,.29);
    -moz-box-shadow: 0px 0px 9px 0px rgba(0,0,0,.29);
    box-shadow: 0 0 9px rgba(0,0,0,.29)
}

#layout-footer .footer-extention {
    display: none;
    position: absolute;
    bottom: 100%;
    width: 100%;
    padding: 12px;
    background-color: var(--panda-grey);
    color: #fff;
    li {
        margin-block: 4px;
    }
}

#layout-footer .footer-extention .chevron-icon {
    cursor: pointer;
    position: absolute;
    top: 4px;
    right: 4px;
    border-radius: 50%
}

#layout-footer .footer-extention .chevron-icon:hover {
    background-color: #b04539
}

# ... continues

# DEV BUNDLE
#layout-footer {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  height: var(--layout-footer-height);
  background-color: var(--panda-grey);
  -webkit-box-shadow: 0px 0px 9px 0px rgba(0, 0, 0, 0.29);
  -moz-box-shadow: 0px 0px 9px 0px rgba(0, 0, 0, 0.29);
  box-shadow: 0px 0px 9px 0px rgba(0, 0, 0, 0.29);
}
#layout-footer .footer-extention {
  display: none;
  position: absolute;
  bottom: 100%;
  width: 100%;
  padding: 12px;
  background-color: var(--panda-grey);
  color: white;
}
#layout-footer .footer-extention .chevron-icon {
  cursor: pointer;
  position: absolute;
  top: 4px;
  right: 4px;
  border-radius: 50%;
}
#layout-footer .footer-extention .chevron-icon:hover {
  background-color: #b04539;
}
#layout-footer .footer-extention li {
  margin-block: 4px;
}

# ... continues

Did you have to change any Fly.io settings? I simply deployed with fly deploy with the given config files. Maybe naively?

Ha, we have to continue the conversation in one place. I’ve made no changes to fly settings.

Are there any differences in your esbuild settings for dev vs prod? I’ve set mine up in config.exs rather than dev.exs / prod.exs.

All config for Esbuild is in config.exs.

# Configure esbuild
config :esbuild,
  version: "0.19.11",
  default: [
    args:
      ~w(js/app.js --bundle --target=es2016,chrome58,edge109,firefox115,safari11 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

This is working. So the difference with my original config is this part: --target=es2016,chrome58. As per your suggestion.

As I mentioned on Elixir Forum (https://elixirforum.com/t/esbuild-not-flattening-nested-css/61051/9), I still get weird styling on iOS on real devices (not Xcode Simulator). I don’t know why. So also not sure if it has anything to do with Fly.io, at this point.

I tried disabling caching, just in case. I’ll have another look at my html meta tags, but they should be alright.