[Boilerplate needed] Phoenix 1.6 + esbuild + Tailwind + SCSS + Alpine

I’ve been trying to migrate my current project to use Phoenix 1.6 + esbuild + Tailwind + SCSS + Alpine, and I’ve been only partially successful.

Can you help me find some boilerplate code for this config?

1 Like

Upgrade using PhoenixDiff. Then add Tailwind and Alpine.

4 Likes

Here you go: Phoenix 1.6.0 LiveView + esbuild + Tailwind JIT + AlpineJS - A brief tutorial.

5 Likes

Oh lordy this is a godsend, yesterday I went through the chore of upgrading from 1.6 alpha to 1.6 and it was painful. I had already used Bamboo and moving to runtime.exs was complex as a newbie :slight_smile:

For reference, this is my full commit, if it helps anyone! Upgrade to Phoenix 1.6 · matteing/stack@f8a54bf · GitHub

2 Likes

Thanks for this guide. Are you able to use SCSS in a 1.6 project alongside tailwindcss? I’ve tried incorporating dart sass but it seems to interfere with tailwindcss.

1 Like

Also check out the s3-upload branch here:

1 Like

Yeah, I’m having this exact issue. I downgraded my scss to css to fix this, but it’s a less than optimal solution.

For anyone who needs a Fly.io Dockerfile for this:

Note: Change the XXXX’s below to your app name

ARG MIX_ENV="prod"

FROM hexpm/elixir:1.12.1-erlang-24.0.1-alpine-3.13.3 AS build

# install build dependencies
RUN apk add --no-cache build-base git python3 curl npm
# If you prefer yarn instead, swap out the runs here and at the NPM install section below, 
# and be sure to update your mix.exs to run yarn instead of npm
# RUN apk add --no-cache build-base git python3 curl yarn

# prepare build dir
WORKDIR /app

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

# set build ENV
ARG MIX_ENV
ENV MIX_ENV="${MIX_ENV}"

# 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

# note: if your project uses a tool like https://purgecss.com/,
# which customizes asset compilation based on what it finds in
# your Elixir templates, you will need to move the asset compilation
# step down so that `lib` is available.

COPY assets assets
#If you prefer yarn instead
# RUN yarn install --cwd ./assets 
RUN npm install --prefix ./assets
RUN mix assets.deploy

# compile and build the release
COPY lib lib
RUN mix compile
# changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/
# uncomment COPY if rel/ exists
# COPY rel rel
RUN mix release

# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM alpine:3.12.1 AS app
RUN apk add --no-cache libstdc++ openssl ncurses-libs

ARG MIX_ENV
ENV USER="elixir"

WORKDIR "/home/${USER}/app"
# Creates an unprivileged user to be used exclusively to run the Phoenix app
RUN \
  addgroup \
  -g 1000 \
  -S "${USER}" \
  && adduser \
  -s /bin/sh \
  -u 1000 \
  -G "${USER}" \
  -h "/home/${USER}" \
  -D "${USER}" \
  && su "${USER}"

# Everything from this line onwards will run in the context of the unprivileged user.
USER "${USER}"

COPY --from=build --chown="${USER}":"${USER}" /app/_build/"${MIX_ENV}"/rel/XXXX ./

ENTRYPOINT ["bin/XXXX"]

# Usage:
#  * build: sudo docker image build -t elixir/XXXX .
#  * shell: sudo docker container run --rm -it --entrypoint "" -p 127.0.0.1:4000:4000 elixir/XXXX sh
#  * run:   sudo docker container run --rm -it -p 127.0.0.1:4000:4000 --name XXXX elixir/XXXX
#  * exec:  sudo docker container exec -it XXXX sh
#  * logs:  sudo docker container logs --follow --tail 100 XXXX
CMD ["start"]
4 Likes

This is exactly what I need, thank you so much :wink:

Have you searched the forums beforehand? I’ve seen at least a couple of posts about it in the past week alone. If you have the time to combine the pieces of information here and there I’m certain you’ll be successful.

Also, I’ll link my answer from another post here because I think using ViteJs today is the pit of success for Phoenix 1.6 (coming from Webpack), see if that helps: Bootstrap 5 and scss usage in Phoenix 1.6 - #4 by thiagomajesk.

Yes I did. The problem I have is with using tailwind & SCSS.

Are you aware that TailwindCSS has documentation on this topic as well?

I wouldn’t use Sass with Tailwind, but if you absolutely must, try configuring Vite in your project, you’ll get esbuild, postcss, and sass, practically out of the box.

Maybe it’s just the way it came across to me, but your tone seems to imply I should have RTFM instead of posting and I don’t appreciate it.

Was there any doubt, given the title, that I wanted a ready-to-go config boilerplate? I spent a couple of hours trying to solve this and I couldn’t, so, as I thought it was a pretty common use case and none of the dozens of articles I read solved this particular issue, a question was in place. I’m not trying to offshore my problem (actually I kinda desisted on using scss, but would be better thou), I’m just asking: Have you solved this? Can you share?

Cool, thanks. This kinda approaches an answer, but I don’t want to introduce more complexity.

1 Like

If you are not dead-set on SCSS, then Mike Clark over at pragmaticstudio.com has an excellent write up on installing TW and Phoenix 1.6 with esbuild here: Adding Tailwind CSS to Phoenix 1.6.

To add Alpine, just install v2.8.2 with npm and esbuild will pick it up. BTW…not specifying a version did not work for me, but 2.8.2 did.

npm i --save alpinejs@2.8.2
[updated to use latest alpine@3.4.2]

npm i --save alpinejs

Then in your app.js:

add: import Alpine from "alpinejs"

new for alpine 3, add:

window.Alpine = Alpine

Alpine.start()

change the liveSocket line to:

let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  dom: {
    onBeforeElUpdated(from, to) {
      if (from.__x) { Alpine.clone(from.__x, to) }
    }
  }
})

I think that’s about it. Hope that helps.

2 Likes

I’m sorry if you feel that way, but since written language is very difficult to convey tone and you will probably be dealing with a lot of people in this community where English is not their first language, you shouldn’t be taking this personally.

The way I see I have not been disrespectful to you in any way so far… I tried to understand where you were coming from to understand what was the problem. I understand how my reply could sound like RTFM, but since your question didn’t give that much information on what did you try and where did you fail, it doesn’t help either.

You shouldn’t come to the forum and expect that people will do the work for you if you are not willing to provide enough information or discuss the problem you are facing. Anything you get out from this thread is a bonus, no one owes you anything.

It’s actually not that complex if you are coming from Webpack, I’d give it a try if I were you. BTW, It seems that Parcel 2 has been announced. You could check if have better luck using it as well.

2 Likes

Yeah, probably. Been under a lot of stress lately, so I guess my reading glasses are a little tarnished. Sorry about that :sweat_smile:

Great, thanks for the tip :wink:

2 Likes