are you using npm? The default Dockerfile generated by phoenix does not include npm. If you need npm deps, you need to modify your docker file to do your node things:
hi @semdinsp could you please share the Dockerfile you used to do this successfully ? My Dockerfile generated by Fly does not have npm so the great tutorial by Andrew Barr to set up tailwind did not work for me. I’ve tried adding npm and nodejs to docker image but still end up with
#24 4.928 ✘ [ERROR] Could not resolve "alpinejs"
#24 4.928
#24 4.928 js/app.js:27:19:
#24 4.928 27 │ import Alpine from "alpinejs"
#24 4.928 ╵ ~~~~~~~~~~
#24 4.928
#24 4.928 You can mark the path "alpinejs" as external to exclude it from the bundle, which will remove this error.```
Both tailwind and alpine are working fine in dev however i cant `fly deploy` successfully :/
thank you!!!
@johnsonlincoln What did you try in your Dockerfile? The lines to use npm are included in the file on the tutorial, they are just commented out.
Although, are you using Phoenix 1.6 with esbuild? And are you using npm for anything besides Alpine? If you are on 1.6 and only using npm for alpine, another option is to skip npm completely and just vendor the JS directly in your assets folder. This is what I do and it works fine for me locally and in prod on fly, with no changes to the vanilla Dockerfile.
visit unpkg.com/alpinejs to get source code of the latest version of Alpine
create a file assets/vendor/alpine.js and paste the Alpine code
in assets/js/app.js add the line import Alpine from "../vendor/alpine"
just for my own edification though; what do you mean by adding alpine to root.html.heex , do you mean in the header as script from cdn? would you mind posting that part of your your root.html.heex file please ?
i ended up just saving alpine source to assets/vendor/alpine.js and adding import Alpine from "../vendor/alpine" in app.js and all good
I started off with this but quickly switched to vendoring for a few reasons:
Version control. unpkg.com/alpinejs always returns the latest version, so if you’re pulling it in on every page load eventually something could break. Vendoring locks the version until you decide to hit that url yourself to copy and replace the code
Bundles everything with your response to avoid the extra http call on page load to fetch the JS
Yes your explanation for my poor communication skills is exactly correct.
I added a script tag to root.html.heex to pull in alpine in the header section
I was also trying to say that if you did not like that approach (ie pulling from the web) you could install the same file ‘alpinejs’ in your project file system and pull it in from there
Here is header of root.html.heex
The body section is normal
@johnsonlincoln I tried to save the alpine source to assets/vendor/alpine.js and added this to my app.js file.
import Alpine from "../vendor/alpine"
window.Alpine = Alpine
Alpine.start()
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
params: {_csrf_token: csrfToken},
dom: {
onBeforeElUpdated(from, to) {
if (from._x_dataStack) {
window.Alpine.clone(from, to)
}
}
}
})
Alpine seems to load, but I get an error in the console that breaks form bindings LiveView. Removing the alpine import fixes the form binding issue, but of course, breaks alpine.
Have you experienced the same thing?
Here’s the error I get
Uncaught TypeError: import_alpine.default.start is not a function
I found myself here with a project that needed Node/NPM to install other packages in addition to Alpine. If you’re in a similar situation, you can add Node/NPM as dependencies in your Dockerfile, in between COPY assets assets and RUN mix assets.deploy. I understand these deps were recently removed from the default Dockerfile with the advent of esbuild, but should you need Node/NPM for any reason, the below advice will work.
I followed a StackOverflow answer on how to add Node to my Dockerfile using NVM:
COPY assets assets
ENV NODE_VERSION=16.17.0
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
ENV NVM_DIR=/root/.nvm
RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"
RUN node --version
RUN npm --version
# install npm deps before running esbuild
RUN npm install --prefix ./assets
# compile assets
RUN mix assets.deploy
You’ll also need to add curl as a dependency to your package for this installation script to work, so the RUN line at line 25 needs to be modified slightly:
That being said, if you’re just using Alpine and don’t expect the JS footprint of your app to grow significantly, inlining Alpine as per @msimonborg’s answer works too, with fewer modifications required.
[builder 13/17] RUN mix assets.deploy: #22 0.676 #22 0.676 22:37:52.496 [debug] Downloading esbuild from https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.0.tgz #22 0.964 > js/app.js:24:19: error: Could not resolve “alpinejs” (mark it as external to exclude it from the bundle) #22 0.964 24 │ import Alpine from “alpinejs” #22 0.964 ╵ ~~~~~~~~~~ #22 0.964 #22 0.965 > js/hooks/home.hooks.js:2:25: error: Could not resolve “ftellipsis” (mark it as external to exclude it from the bundle) #22 0.965 2 │ import { Ellipsis } from “ftellipsis”; #22 0.965 ╵ ~~~~~~~~~~~~ #22 0.965 #22 0.966 > js/hooks/article.hooks.js:2:25: error: Could not resolve “ftcolumnflow” (mark it as external to exclude it from the bundle) #22 0.966 2 │ import FTColumnflow from “ftcolumnflow”; #22 0.966 ╵ ~~~~~~~~~~~~~~ #22 0.966 #22 0.975 3 errors #22 0.982 ** (Mix) mix esbuild default --minify exited with 1
Error failed to fetch an image or build from source: error building: executor failed running [/bin/sh -c mix assets.deploy]: exit code: 1
It looks like the 3 packages are not packeged by esbuild. (not sure why)
Dockerfile by default uses:
ARG DEBIAN_VERSION=bullseye-20210902-slim
You need to install npm inside docker
since debian removed npm from main, you can only get it from backports.
– you could add backports repo as: #adding backports
RUN echo ‘deb Index of /debian bullseye-backports main’ >>/etc/apt/sources.list
but package nodejs i still not found, How can I troubleshoot and see what is the output of below ??
RUN apt search nodejs
One way to add (not my preferred way), is to add a foreign repository
So if you need npm add this to your Dockerfile (note you might need to add curl right after apt -get install …git