La réponse est la même qu'à la simple question "pourquoi Webpack ?". L'intérêt principal est d'obtenir des rapports d'erreurs liés à la gestion des assets (images, fonts, etc).
Qu'y a-t-il de si particulier à savoir pour utiliser Webpack pour gérer un thème WordPress ? Pas grand chose, mais voici de quoi vous faire gagner (peut-être) un peu de temps.
Il y a certainement plusieurs façons de gérer son thème WordPress avec Webpack. Celle que je vous propose va se limiter à des choses simples en concentrant le code dans le répertoire du thème pour plus de modularité.
Pour commencer, deux choses importantes à savoir :
style.css
à la racine de votre thème,
laissez juste le cartouche en commentaire (sans lequel WordPress ne détectera
pas votre thème...) ;src
dans votre thème, où nous mettrons nos "sources", la
partie du thème "compilé" sera dans un dossier dist
et n'aura donc pas
besoin d'être versionnée.La seule petite chose à laquelle il faut faire attention finalement, c'est de
bien configurer le publicPath
de Webpack afin que les fichiers qu'il génère
soient bien dans le bon chemin, et que les ressources liées (dans les fichiers
CSS par exemple) comportent les bons chemins relatifs (à la racine du site).
Avec l'arborescence suivante, nous n'aurons pas de difficulté à faire une configuration portable :
- htdocs
- wp-content
- themes
- putaindetheme
- node_modules
- src
- index.js
- index.css
- images/*
- fonts/*
- style.css
- webpack.config.babel.json
- package.json
- package.json
En plus de cela, nous pouvons ajouter une sorte de raccourci via un
package.json
supplémentaire à la racine de notre projet :
{
"private": true,
"scripts": {
"start": "cd htdocs/wp-content/themes/putaindetheme && npm start",
"build": "cd htdocs/wp-content/themes/putaindetheme && npm run build"
}
}
Ce petit raccourci nous évitera de devoir nous taper en CLI tout le chemin du
thème et nous pourrions même, pourquoi pas, rajouter un
"prestart": "open http://yourlocalhost.tld"
afin d'ouvrir automatiquement le
projet dans le navigateur lorsque nous démarrerons notre développement via
$ npm start
.
Voyons rapidement donc le package.json
du thème ainsi que la config Webpack.
package.json
{
"private": true,
"scripts": {
"start": "webpack --config=webpack.config.babel.js --watch",
"build": "webpack --config=webpack.config.babel.js -p"
},
"devDependencies": {
"babel": "^5.8.12",
"babel-core": "^5.8.12",
"babel-loader": "^5.3.2",
"css-loader": "^0.15.6",
"eslint": "^0.24.1",
"eslint-loader": "^0.14.2",
"extract-text-webpack-plugin": "^0.8.2",
"file-loader": "^0.8.4",
"json-loader": "^0.5.2",
"postcss-cssnext": "^2.1.0",
"postcss-import": "^7.0.0",
"postcss-loader": "^0.6.0",
"postcss-url": "^5.0.2",
"style-loader": "^0.12.3",
"webpack": "^1.10.5"
},
"dependencies": {
"normalize.css": "^3.0.3"
}
}
Quelques petites notes sur ce contenu :
private
sert à éviter la publication de votre "paquet" sur npm, ainsi qu'à
devoir remplir certains champs tels que name
et compagnie ;devDependencies
les dépendances pour le développement et
dans dependencies
les dépendances qui seront dans le build final. Ici, j'ai
simplement mis normalize.css
pour exemple, mais vous pourriez très bien
avoir aussi jQuery (:trollface:) ou React ;webpack.config.babel.js
afin de pouvoir définir la
configuration en es6/7 via babel.Voyons maintenant la config webpack.config.babel.js
:
// Note: le code ci-dessous est mal rendu
// Une issue est ouverte à ce propos
// https://github.com/isagalaev/highlight.js/issues/958
import "babel/polyfill";
import path from "path";
import ExtractTextPlugin from "extract-text-webpack-plugin";
import postcssImport from "postcss-import";
import postcssUrl from "postcss-url";
import postcssCssnext from "postcss-cssnext";
const production = process.argv.includes(`-p`);
const theme = path.basename(__dirname);
const src = path.join(__dirname, `src`);
export default {
entry: {
index: [`${src}/index.js`],
},
output: {
path: path.join(__dirname, `dist`),
filename: `[name].js`,
publicPath: `wp-content/themes/${theme}/dist/`,
},
resolve: {
extensions: [``, `.js`, `.json`],
},
module: {
loaders: [
{
test: /\.json$/,
loader: `json-loader`,
},
{
test: /\.js$/,
loaders: [`babel-loader`, `eslint-loader`],
include: src,
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract(
`style-loader`,
[`css-loader`, `postcss-loader`].join(`!`),
),
},
{
test: /\.(ico|jpe?g|png|gif)$/,
loader: `file-loader?name=[path][name].[ext]&context=${src}/`,
},
],
},
plugins: [new ExtractTextPlugin(`[name].css`, { disable: !production })],
postcss: function() {
// https://github.com/postcss/postcss-loader/issues/31
const webpack = this;
return [
postcssImport({
onImport: files => files.forEach(webpack.addDependency),
}),
postcssUrl(),
postcssCssnext({
browsers: `last 2 versions`,
}),
];
},
};
Bien entendu, libre à vous d'adapter les loaders Webpack à utiliser, ainsi que la configuration PostCSS par exemple. Faites un tour sur notre article de premier exemple de configuration Webpack afin d'y voir plus clair.
Il nous reste maintenant à ajouter dans notre thème WordPress les références à
nos points d'entrées CSS et JavaScript que sont index.css
et index.js
.
Pour faire simplement, dans votre fichier functions.php
(oui, le fichier qui a
un nom qui n'indique pas du tout ce pour quoi tout le monde se sert du fichier,
c'est à dire la configuration du thème au runtime...), on va ajouter une petite
constante qui servira à adapter votre thème en fonction de l'environnement :
// ENV est à définir dans votre configuration Apache par exemple.
// Si vous ne voulez pas y toucher, vous pouvez plutôt définir d'une autre façon
// en testant le SERVER_NAME par exemple
define('ENV', getenv('ENV'));
// en local, on pourrait définir ENV à "development"
_Nous pourrions dans ce fichier utiliser l'API de Wordpress pour enregister nos
index.css
et index.js
via les méthodes wp_(de)register*
, mais nous
resterons simples pour l'exemple.*
Vu qu'on utilise le style-loader
de Webpack en développement, on ne va ajouter
notre feuille de style qu'en production (dans le <head>
).
<?php if (ENV != "development"): ?>
<link rel="stylesheet" href="<?php echo get_bloginfo('template_directory') ?>/dist/index.css" />
<?php endif; ?>
Pensez aussi à supprimer la référence à style.css
dans header.php
.
Dans la même idée mais en plus simple, on va ajouter dans notre footer.php
.
<script src="<?php echo get_bloginfo('template_directory') ?>/dist/index.js"></script>
Rien de bien compliqué finalement.
Attention si votre thème hérite d'un autre,
get_bloginfo('template_directory')
ne pointera pas vers votre thème mais le
thème parent. Il vous faudra donc ajuster le code 😑.
Pour le test vous pouvez mettre dans les CSS et JS :
index.css
@import "normalize.css";
body {
background: red;
}
Notez ici que par la façon dont nous avons défini Webpack ci-dessus, vous
devriez placer et référencer vos assets (images & co), depuis src
. Exemple :
html {
background: url(./images/background.jpg);
/* => wp-content/themes/putaindetheme/src/images/background.jpg */
}
Ensuite, dans index.js
, je vous laisse vous débrouiller :)
console.log("Hey !");
Libre à vous maintenant d'ajouter vos dépendances favorites et de remplir vos
index.css
et index.js
avec une gestion d'erreurs autre que des requêtes HTTP
en 404 !