sreenadh_tc

sreenadh_tc

I am trying to migrate our app (that uses Tailwindcss, and React on the frontend) from Phoenix v1.5 to v1.6.11

Everything works perfectly on local, but the CSS classes are not being loaded in production deployments.

dockerfile
ARG ELIXIR_VERSION=1.13.4
ARG OTP_VERSION=25.0.3
ARG ALPINE_VERSION=3.14.6

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-alpine-${ALPINE_VERSION}"
ARG RUNNER_IMAGE="alpine:${ALPINE_VERSION}"

#####################################################
# 1. Build elixir backend and compile assets
#####################################################
FROM ${BUILDER_IMAGE} as builder

# install build dependencies
RUN apk add --update git npm build-base

# prepare build dir
WORKDIR /app

# install hex + rebar
RUN mix local.hex --force && \
    mix local.rebar --force

# set build ENV
ENV MIX_ENV="prod"

# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config

# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile

COPY priv priv

COPY lib lib

COPY assets assets

# compile assets
RUN npm --prefix assets install && mix assets.deploy

# Compile the release
RUN mix compile

# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/

COPY rel rel
RUN mix release

#####################################################
# 2. Build release image
#####################################################

FROM ${RUNNER_IMAGE}

RUN apk add --update --no-cache ncurses-libs libssl1.1 openssh

# set runner ENV
ENV MIX_ENV=prod
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

WORKDIR "/app"
RUN chown nobody /app

# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/diffity ./

USER nobody


EXPOSE 4000
CMD ["/app/bin/server"]
tailwind.config.js
const defaultTheme = require("tailwindcss/defaultTheme");

module.exports = {
  content: [
    "../lib/**/*.ex",
    "../lib/**/*.leex",
    "../lib/**/*.*ex",
    "./js/**/*.js",
    "./js/**/*.tsx",
    "./js/**/**/*.tsx",
  ],

  theme: {
    extend: {
      fontFamily: {
        sans: ["Poppins", ...defaultTheme.fontFamily.sans],
        serif: [...defaultTheme.fontFamily.serif],
        mono: [...defaultTheme.fontFamily.mono],
      },
    },
  },
  variants: {
    extend: {},
  },
  plugins: [require("@tailwindcss/forms")],
};
app.css
@tailwind base;
@tailwind components;
@tailwind utilities;
...

@layer components {
  .btn {
    @apply py-2 font-medium rounded shadow focus:ring-4 px-4 text-center;
  }

  .btn-blue {
    @apply text-blue-700 bg-blue-200 hover:bg-blue-300 focus:ring-blue-400;
  }
}
confix.exs
...
# Configure esbuild (the version is required)
config :esbuild,
  version: "0.14.29",
  default: [
    args: [
      "js/app.js",
      "--bundle",
      "--loader:.js=jsx",
      "--target=es2017",
      "--outdir=../priv/static/assets",
      "--external:/fonts/*",
      "--external:/images/*"
    ],
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

# Tailwind CSS
config :tailwind,
  version: "3.1.7",
  default: [
    args: [
      "--config=tailwind.config.js",
      "--input=css/app.css",
      "--output=../priv/static/assets/app.css"
    ],
    cd: Path.expand("../assets", __DIR__)
  ]
...
mix deps
{:esbuild, "~> 0.4", runtime: Mix.env() == :dev},
{:tailwind, "~> 0.1", runtime: Mix.env() == :dev},

I have made sure these suggestions from Chris are in place even though the phoenix version i use has already taken care of the changes: comment-#2 and comment-#8

When inspecting the network tab, i can confirm that the app.css file is being downloaded by the browser just fine.

Anyone have any debugging suggestions on this? :thinking:

Showing Posts 1 to 10

odix67

odix67

have you looked in the content of the downloaded app.css, it seems quite small ?

… and why you use npm to build the assets, you have esbuild for that job ?

and btw, welcome to the forum !!

sreenadh_tc

sreenadh_tc OP

have you looked in the content of the downloaded app.css, it seems quite small ?

yea i did. :smile:
The response does not have anything related to Tailwind

and why you use npm to build the assets, you have esbuild for that job

correct. npm is only used to fetch additional packages, like React

assets are being built by esbuild itself.
I forgot to add this part in the actual question. but here is my alias for mix assets.deploy:

# mix.exs
"assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"]
odix67

odix67

check in the root template the entry for the css inclusion and further more check if there exists more than one app.css in ./priv directory and the root template points to the wrong one. This often happens during updating a project.

sreenadh_tc

sreenadh_tc OP

check in the root template the entry for the css inclusion

yep, its already included:

# lib/*_web/templates/layout/root.html.heex
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/app.css")}/>

from the build image, contents of the priv/ only has app.css

check if there exists more than one app.css in ./priv directory

/app $ ls lib/diffity-0.2.0/priv/static/assets/
app-469c82a27400fa9c0e39ac67e4d75104.js      app.css
app-469c82a27400fa9c0e39ac67e4d75104.js.gz   app.css.gz
app-d21dde08b813306cb995ada660dbf46e.css     app.js
app-d21dde08b813306cb995ada660dbf46e.css.gz  app.js.gz

the content of this css file however only has styles related to react-loading-skeleton. one of the additional react packages.

/app $ cat lib/diffity-0.2.0/priv/static/assets/app-d21dde08b813306cb995ada660dbf46e.css
@keyframes react-loading-skeleton{to{transform:translate ...

This often happens during updating a project.

yea, I might have missed something in between, but been over this for a few hours and still can’t figure it out :smile:

odix67

odix67

maybe, I’m not quite sure, in the app.js file there usually exists an include of the app.css file, as you use tailwind to build the final css, you have to remove it. Maybe I’m wrong, but give it a try

sreenadh_tc

sreenadh_tc OP

Well I think I missed this attention to detail.

It’s important to note that you don’t need to use a preprocessor with Tailwind — you typically write very little CSS on a Tailwind project anyways so using a preprocessor just isn’t as beneficial as it would be in a project where you write a lot of custom CSS.

Since I have some customization to tailwind, doing so would need Preprocessor I guess?

@tailwind base;
@tailwind components;
@tailwind utilities;
...

@layer components {
  .btn {
    @apply py-2 font-medium rounded shadow focus:ring-4 px-4 text-center;
  }

  .btn-blue {
    @apply text-blue-700 bg-blue-200 hover:bg-blue-300 focus:ring-blue-400;
  }
}

So i used GitHub - CargoSense/dart_sass: Install and run Dart Sass using Elixir. · GitHub and things are working now!

odix67

odix67

It’s good that it is working now, but I think your working around the problem. Let me explain the reason why I think the app.css is doesn’t include the expected css:

  • tailwind builds app.css with tailwind default --minify
  • in the case you include the app.css in app.js, esbuild overwrites the correct app.css with the nearly empty one with command esbuild default --minify

as it works in dev, you usually do not need a Preprocessor for production build.

sreenadh_tc

sreenadh_tc OP

I don’t have it included in app.js

odix67

odix67

I stick to my opinion ;-), as you mentioned that the app.css file included just the react-loading-skeleton, the tailwind produced css is definitely overwritten by esbuild build run. try to reverse the order, first do the esbuild, then the tailwind stuff in “assets.deploy”, if you need the react-loading-skeleton css, include it in the app.css

sreenadh_tc

sreenadh_tc OP

ah ofcourse, that makes sense. That should work :slightly_smiling_face:
thanks!

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews