I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into the next-gen of Phoenix!
How do we handle fonts using this build chain?
For example Inter | Fontsource - how do we add and use?
In your app.css you just import and use normally.
@import url("../vendor/fonts/Inter Web/inter.css");
html {
font-family: "Inter var";
}
And then in your endpoint watcher config for esbuild in dev.exs you have to pass the loaders to the command.
watchers: [
# Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch --loader:.woff=file --loader:.woff2=file)]}
]
You could also use dataurl instead of file and esbuild will embed the fonts encoded as base64 (not recommended, my css file went to more than 6MB with dataurls).
Edit: Sorry, didn’t read the entire post, they remove the css processing from esbuild and handle it with postcss, in this case what I would do is ignore the esbuild base config of phoenix, install it manually and use the api to load the esbuild postcss plugin (esbuild plugins aren’t available through the cli), but in this case you will have to make a tradeoff between simplicity (no need for node, npm or anything else in phoenix 1.6) and power.
not quite as easy as @thomas.fortes suggests…
but close if you are OK with a seperate css file for the font (face) and thus using esbuild for it…
- download the font Inter font family
- copy the
Inter Web
folder into say /assets/vendor/fonts and rename the folder toInterWeb
(need to avoid spaces!) - change the esbuild args in config.exs to:
~w(js/app.js vendor/fonts/InterWeb/inter.css --bundle --loader:.woff2=file --loader:.woff=file --target=es2016 --outdir=../priv/static/assets),
- notice that the app.js is now outputted inside a js folder
go to your layout and change the js script src toRoutes.static_path(@conn, "/assets/js/app.js")
- above your app.css stylesheet do a:
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/assets/vendor/fonts/InterWeb/inter.css") %>"/>
for bonus points:
add https://github.com/semencov/tailwindcss-font-inter by doing:
npm install --save-dev tailwindcss-font-inter
(in the assets folder)
and then add the plugin in the tailwind config:
plugins: [require('tailwindcss-font-inter')({
importFontFace: false,
})]
now you can use the css class font-inter
wherever you want…
will Tailwind be also default for Phoenix 1.6?
No, in this article you can see he is installing it from NPM:
npm install autoprefixer postcss postcss-import postcss-cli tailwindcss --save-dev
woo nice! Quick question - how would I enable scss
?
Going with dart-sass npm package is one alternative. But, if you only need sass - GitHub - CargoSense/dart_sass: An installer for sass is a very good alternative to consider.
Great job @sergio!
Now that Phoenix 1.6.0-rc.0 is out, I tried to migrate my app and this other post also provided me some insights: https://www.mitchellhanberg.com/how-i-handle-static-assets-in-my-phoenix-apps.
I ended up with something like this:
package.json
"scripts": {
"deploy": "npm-run-all --parallel deploy-styles deploy-files",
"deploy-styles": "NODE_ENV=production tailwindcss -i css/app.css -o ../priv/static/assets/app.css --minify",
"deploy-files": "cpx 'static/**/*' ../priv/static",
"watch": "npm-run-all watch-styles watch-files",
"watch-styles": "tailwindcss --input=css/app.css --output=../priv/static/assets/app.css --postcss --watch",
"watch-files": "cpx 'static/**/*' ../priv/static --watch"
}
[...]
"devDependencies": {
"autoprefixer": "^10.2.6",
"npm-run-all": "^4.1.5",
"postcss-import": "^14.0.2",
"tailwindcss": "^2.2.4"
}
dev.exs
watchers: [
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
npm: ["run", "watch", cd: Path.expand("../assets", __DIR__)]
]
PS.: Even though there’s too much configuration for my taste still, the recompilations are fast, really really fast now with esbuild.
Update: BTW: It seems you don’t need to have postcss installed at all if you are using just Tailwind for your styles. You can replace the deploy script with: NODE_ENV=production tailwindcss -i css/app.css -o ../priv/static/assets/app.css --minify
This guide was super helpful; thank you! I noticed that it doesn’t minify CSS. If you want that, it’s very easy to add if you’re already using PostCSS:
- Install CSSNano:
npm --prefix assets install --save-dev cssnano
- Add it to your
postcss.config.js
:
module.exports = {
plugins: {
"postcss-import": {},
tailwindcss: {},
autoprefixer: {},
cssnano: {
preset: "default",
},
},
}
esbuild also supports Typescript out of the box; just make sure to read the caveats if you’re going to use it.
Just wanted to add a thank you for the guide—was very helpful.
Just to offer an alternative solution how to add a font file, you can also include the font using the postcss-url
plugin as follows. (cc @cvkmohan )
1. Place the font in assets/fonts
I only need the one variable font file in WOFF2 format so for me it’s at assets/fonts/Inter.var.woff2
.
2. Add postcss-url
dependency
npm install postcss-url --save-dev
3. Add the plugin to assets/postcss.config.js
Mine looks like this after adding it:
module.exports = {
plugins: {
'postcss-import': {},
'postcss-url': { url: 'inline' },
tailwindcss: {},
autoprefixer: {},
}
}
4. Add the @font-face
definition to your app.css
@font-face {
font-family: 'Inter';
font-weight: 1 999;
src:
url('../fonts/Inter.var.woff2') format('woff2-variations');
}
–
The above configuration will inline the font into your CSS like this:
@font-face { font-family: "Inter"; src: url("data:font/woff2;base64,d09G[...]d6eMC") format("woff2-variations"); font-weight: 1 999; }
If you prefer to keep the font(s) in separate files, use copy
instead of inline
.
i have successfully made new phoenix 1.6.0 app with esbuild+tailwind+alpinejs everything fine even tailwind but tailwind-extension in vscode is not working the auto suggestion’s for tailwind are not showing up, i think it’s not working because of heex
file extension.
Have you tried changing the extensions in your config? There’s a tailwindCSS.includeLanguages
setting. If that doesn’t help you should probably open an issue on Tailwind’s extension repository.
Thank you
I tried that setting but no luck it’s still not working,
I’ll create a GitHub issue in their repository
If anyone has trouble getting this to work on Windows this did the trick for me.
watchers: [
# Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
node: [
"node_modules/tailwindcss/lib/cli.js",
"--input=css/app.css",
"--output=../priv/static/assets/app.css",
"--postcss",
"--watch",
cd: Path.expand("../assets", __DIR__)
]
]
You can also do cmd: ["/c", "npx", ... ]
to run npx
and other things that are .cmd
files, which Erlang doesn’t seem to be able to open a port to.
Never considered that. Very helpful.
Are there any tricks/methods for the additional css files you could use as an addition to tailwindcss. Like for example adding @import "./custom-base-styles.css";
to the assets/css/app.css file. Would this still work and where do I need to drop these additional files. When trying via the assets/css/
location doesn’t work.