Phoenix : changer de bundler

Depuis sa version 1.4, Phoenix embarque Webpack pour bundler les différentes dépendances. Nous allons voir qu'il est facile de changer d'outil en prenant Parcel comme exemple. Cet outil a l'avantage de ne pas nécessiter de configuration pour fonctionner.
Initialisation
Créons un nouveau projet, sans "ecto" pour ne pas avoir besoin de configurer une base de données.
mix phx.new app --no-ecto
Lançons le serveur de Phoenix.
mix phx.server
Phoenix exécute Webpack pour nous et écoute les changements de fichiers pour nous apporter les modifications en hot reload.
Si j'édite le fichier
assets/css/app.css
/* This file is for your main application css. */
@import "./phoenix.css";
body {
background: darkgray;
}
Notre but est donc de garder ce comportement, qui offre un confort de développement, mais en utilisant un autre outil.
Webpack build nos assets à destination de
priv/static
Avant de continuer coupons notre serveur et supprimons le dossier généré par Webpack pour partir sur une base propre
rm -rf priv/static
Configuration de Parcel au sein de Phoenix
Installons Parcel ainsi qu'un plugin magique dont le détail ne rentre pas dans le cadre de cet article.
cd assets/ && npm install --save-dev parcel-bundler parcel-plugin-static-files-copy
Dans le fichiers
config/dev.exs
config :app, AppWeb.Endpoint,
http: [port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [
node: [
"node_modules/webpack/bin/webpack.js",
"--mode",
"development",
"--watch-stdin",
cd: Path.expand("../assets", __DIR__)
]
]
par
config :app, AppWeb.Endpoint,
http: [port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [
node: [
"node_modules/.bin/parcel",
"watch",
"js/app.js",
"-d",
"../priv/static",
cd: Path.expand("../assets", __DIR__)
]
]
Désormais lorsque nous lançons un
mix phx.server
Et le dossier de destination est bien
priv/static
Mais malheureusement, nos css et js ne sont plus chargés
Webpack générait un dossier
css
js
lib/app_web/templates/layout/app.html.eex
On remplace
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
</head>
<body>
###
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
</body>
</html>
par
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/app.css") %>"/>
</head>
<body>
###
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/app.js") %>"></script>
</body>
</html>
Et 🎉, ça ne marche pas 😢.
Ce comportement vient du fait que Phoenix autorise uniquement les fichiers respectant certains patterns à être servi comme fichiers statiques. Ces patterns sont configurables dans le fichier
lib/app_web/endpoint.ex
plug Plug.Static,
at: "/",
from: :app,
gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt)
Cette configuration signifie que seul les fichiers présents dans les dossiers
css
fonts
images
js
favicon.ico
robots.txt
priv/static
plug Plug.Static,
at: "/",
from: :app,
gzip: false,
only: ~w(app.css fonts images app.js favicon.ico robots.txt)
Comme nous n'avons pas de dossiers intermédiaires
css
js
app.css
app.js
Maintenant l'application fonctionne correctement. Si j'édite le fichier
assets/js/app.js
console.log
import "phoenix_html";
import css from "../css/app.css";
console.log("Meeeeeeeeh");
Un "Meeeeeeeeh" apparait dans la console de notre navigateur sans avoir besoin de recharger la page 🎉.
Nettoyage
Maintenant que nous avons ajouté Parcel il ne nous reste plus qu'à supprimer les vestiges de Webpack :
cd assets && npm uninstall babel-loader copy-webpack-plugin css-loader mini-css-extract-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin webpack webpack-cli && rm webpack.config.js
Conclusion
Peut importe que vous choisissiez de garder Webpack, d'utiliser Rollup, Parcel… Si vous choisissez de modifier la configuration de votre bundler, il faut penser à :
- configurer correctement son bundler (facile avec Parcel)
- changer le script surveillant les modifications de fichiers (dev.exs)
- veiller à ce que le fichiers statiques puissent être servi correctement (endpoint.ex)
- modifier les chemins dans les templates (app.html.eex)
Liens utiles
- Je me suis inspiré de ce dépôt Github. La base de code reprend la structure d'une ancienne version de Phoenix, ne l'utilisez pas tel quel si vous voulez être à jour.
- Mon ancien article
- La documentation sur la configuration du Endpoint