<!--
  canonical-url: https://www.avonture.be/fr/blog/assets-minification
  published:     2026-04-13
  This is a static plain-Markdown mirror generated at build time.
  Visit the canonical URL above for the fully rendered page, with images and interactive components.
-->

# Optimisez votre frontend - Minifier vos assets avec Docker, Bash et YAML

> Oubliez les lourdes chaînes d'outils Node. Construisez un pipeline de minification d'assets rapide et sans dépendances avec un manifeste YAML déclaratif, Bash et Docker.

---
![Optimisez votre frontend - Minifier vos assets avec Docker, Bash et YAML](/img/v2/minification.webp)

**TL;DR**Ce guide montre comment construire un pipeline d'assets propre, modulaire et ultra-rapide sans polluer votre machine hôte. En combinant un manifeste YAML déclaratif, un orchestrateur Bash tout simple et un minifieur écrit en Go tournant dans Docker (`tdewolff/minify`), vous obtenez des builds reproductibles et isolés. C'est le setup parfait pour les projets qui veulent une approche Docker-first et légère de l'optimisation frontend.

Dans le développement web moderne, garder vos fichiers CSS et JavaScript légers est crucial pour la performance. Les bundlers lourds comme Webpack ou Vite sont excellents pour les applications complexes, mais parfois vous voulez juste une manière simple et portable de concaténer et minifier des fichiers, sans installer tout l'écosystème Node.js sur votre machine locale ou sur votre runner CI/CD.

Aujourd'hui, nous allons construire un pipeline de build maison avec :

1. **YAML** pour définir nos bundles d'assets.
2. **Bash** pour orchestrer la concaténation des fichiers.
3. **Docker** pour effectuer la minification avec des outils très performants.

## Le lancer {#running-it}

Une fois le manifeste et le script en place (voir plus bas), tout le pipeline tient en une seule commande :

![Exécution de la minification](./images/running.png)

Et oui, ça n'a pris que cinq secondes (téléchargement de l'image Docker compris).

## Pourquoi cette approche ? {#why-this-approach}

1. **Aucune dépendance Node** : pas besoin de `package.json` ni de dossier `node_modules`. Le moteur de minification vit dans un container Docker.
2. **Ultra-rapide** : `tdewolff/minify` est écrit en Go. Il est nettement plus rapide que beaucoup de minifieurs écrits en JavaScript.
3. **Déclaratif** : ajouter un nouveau fichier à votre bundle CSS se résume à ajouter une ligne dans votre `manifest.yaml`.
4. **Cohérence** : puisque nous utilisons Docker, le résultat de la minification sera exactement le même sur votre machine locale, sur le portable de votre collègue et sur votre serveur CI de production.

## L'architecture {#the-architecture}

Notre workflow est vraiment (vraiment !) simple :

1. Un script Bash lit un fichier `manifest.yaml`.
2. Il rassemble les fichiers sources et les fusionne dans un seul fichier temporaire.
3. Il lance un container Docker qui exécute le moteur [minify](https://github.com/tdewolff/minify) pour compresser le code.

### 1. La configuration (`manifest.yaml`) {#1-the-configuration-manifestyaml}

D'abord, il nous faut un moyen d'indiquer à notre script quels fichiers vont ensemble. Cette structure YAML vous permet de définir plusieurs bundles, aussi bien pour le CSS que pour le JS.

Voici ce dont nous avons besoin :

**manifest.yaml**

```yaml
bundles:
  - name: "Main Styles"
    type: "css"
    output: "dist/assets/app.min.css"
    inputs:
      - "public/assets/css/components.css"
      - "public/assets/css/layout.css"
      - "public/assets/css/reset.css"
      - "public/assets/css/variables.css"
  - name: "App Logic"
    type: "js"
    output: "dist/assets/bundle.min.js"
    inputs:
      - "public/assets/js/api.js"
      - "public/assets/js/main.js"
      - "public/assets/js/utils.js"
```

Nous avons deux parties, une pour le CSS et une pour le JS, et nous allons définir deux choses

1. Le nom de notre fichier cible (par ex. ici, le fichier CSS minifié sera `dist/assets/app.min.css`)
2. Une liste de fichiers d'entrée

### 2. Le script orchestrateur (`build.sh`) {#2-the-orchestrator-script-buildsh}

Ce script Bash utilise `yq` (un processeur YAML léger ; voyez-le comme le cousin YAML de [`jq`](/blog/linux-jq)) pour parser notre manifeste. Il concatène les fichiers puis appelle l'image Docker `[tdewolff/minify](https://hub.docker.com/r/tdewolff/minify)` pour faire le gros du travail. Résultat : nous ne polluons pas notre système avec des dépendances supplémentaires — juste une petite image Docker.

### 3. Comment l'exécuter {#3-how-to-run-it}

#### Prérequis {#prerequisites}

1. **Docker** : installé et démarré.
2. **yq** : un processeur YAML portable en ligne de commande. Vous pouvez l'installer avec `sudo apt-get update && sudo apt-get install yq` si vous ne l'avez pas encore.

#### Mise en place {#set-up}

Pour ce tutoriel, créons quelques fichiers d'exemple. Ouvrez un nouveau terminal et lancez cette longue commande :

```txt
mkdir /tmp/minification && cd $_ && \
mkdir -p public/assets/css public/assets/js dist/assets && \
cat << 'EOF' > public/assets/css/reset.css
html, body { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: sans-serif; line-height: 1.5; }
EOF
cat << 'EOF' > public/assets/css/variables.css
:root {
    --primary-color: #3498db;
    --secondary-color: #2ecc71;
    --dark-bg: #2c3e50;
    --light-text: #ecf0f1;
}
EOF
cat << 'EOF' > public/assets/css/layout.css
.container { width: 90%; margin: 0 auto; max-width: 1200px; }
.flex-row { display: flex; gap: 20px; flex-wrap: wrap; }
header { background: var(--dark-bg); color: var(--light-text); padding: 2rem; }
EOF
cat << 'EOF' > public/assets/css/components.css
.btn { padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; }
.btn-primary { background-color: var(--primary-color); color: white; }
.btn-primary:hover { filter: brightness(1.1); }
EOF
cat << 'EOF' > public/assets/js/utils.js
const logger = (msg) => {
    const timestamp = new Date().toISOString();
    console.log(`[${timestamp}] INFO: ${msg}`);
};
EOF
cat << 'EOF' > public/assets/js/api.js
async function fetchData(endpoint) {
    logger(`Fetching data from /api/${endpoint}`);
    const response = await fetch(`/api/${endpoint}`);
    return await response.json();
}
EOF
cat << 'EOF' > public/assets/js/main.js
document.addEventListener('DOMContentLoaded', () => {
    logger('Application initialized');
    const appContainer = document.querySelector('.container');
    if(appContainer) {
        appContainer.innerHTML += '<p>Assets loaded successfully.</p>';
    }
});
EOF
echo "Directory structure and files created successfully."
```

Cette instruction va créer un nouveau dossier `/tmp/minification` et automatiser la création de quelques fichiers :

```tree
├── dist
│   └── assets
└── public
    └── assets
        ├── css
        │   ├── components.css
        │   ├── layout.css
        │   ├── reset.css
        │   └── variables.css
        └── js
            ├── api.js
            ├── main.js
            └── utils.js
```

##### Créons maintenant le manifeste et le script {#now-please-create-the-manifest-and-the-script}

Cela fait, terminez la mise en place en créant le fichier manifeste `/tmp/minification/manifest.yaml` :

**manifest.yaml**

```yaml
bundles:
  - name: "Main Styles"
    type: "css"
    output: "dist/assets/app.min.css"
    inputs:
      - "public/assets/css/components.css"
      - "public/assets/css/layout.css"
      - "public/assets/css/reset.css"
      - "public/assets/css/variables.css"
  - name: "App Logic"
    type: "js"
    output: "dist/assets/bundle.min.js"
    inputs:
      - "public/assets/js/api.js"
      - "public/assets/js/main.js"
      - "public/assets/js/utils.js"
```

Et créez aussi le script Bash `/tmp/minification/build.sh` :

**build.sh**

```bash
#!/bin/bash

# Ensure yq is installed
if ! command -v yq &> /dev/null; then
    echo "Error: 'yq' is not installed."
    exit 1
fi

CONFIG_FILE="manifest.yaml"
DOCKER_IMAGE="tdewolff/minify:latest"

echo "--- Starting Build Process ---"

build_failed=0

# Create dist directory
mkdir -p dist/assets

# Iterate through bundles - Added -r flag to all yq calls
bundle_count=$(yq -r '.bundles | length' "$CONFIG_FILE")

for ((i=0; i<bundle_count; i++)); do
    # Using -r to get raw strings without quotes
    NAME=$(yq -r ".bundles[$i].name" "$CONFIG_FILE")
    TYPE=$(yq -r ".bundles[$i].type" "$CONFIG_FILE")
    OUTPUT=$(yq -r ".bundles[$i].output" "$CONFIG_FILE")

    echo "Processing Bundle: $NAME [$TYPE]"

    TEMP_FILE="temp_bundle.$TYPE"
    rm -f "$TEMP_FILE"

    input_count=$(yq -r ".bundles[$i].inputs | length" "$CONFIG_FILE")
    for ((j=0; j<input_count; j++)); do
        INPUT_PATH=$(yq -r ".bundles[$i].inputs[$j]" "$CONFIG_FILE")

        # Now INPUT_PATH is "public/assets/css/reset.css" (no literal quotes)
        if [[ -f "$INPUT_PATH" ]]; then
            cat "$INPUT_PATH" >> "$TEMP_FILE"
            echo "  + Added $INPUT_PATH"
        else
            echo "  ! Warning: File $INPUT_PATH not found. Skipping."
        fi
    done

    if [[ -f "$TEMP_FILE" ]]; then
        echo "  > Minifying..."
        # We ensure the output directory exists for this specific file
        mkdir -p "$(dirname "$OUTPUT")"

        if docker run --rm -v "$(pwd):/src" "$DOCKER_IMAGE" \
            --type="$TYPE" \
            "/src/$TEMP_FILE" > "$OUTPUT"; then
            rm "$TEMP_FILE"
            echo "  ✓ Generated: $OUTPUT"
        else
            echo "  × Error: minification failed for bundle $NAME." >&2
            build_failed=1
        fi
    else
        echo "  × Error: No input files found for bundle $NAME." >&2
        build_failed=1
    fi
done

if [[ "$build_failed" -eq 1 ]]; then
    echo "--- Build Failed ---" >&2
    exit 1
fi

echo "--- Build Complete ---"
```

Dernière chose : le rendre exécutable (`chmod +x /tmp/minification/build.sh`).

#### Exécution {#execution}

Vous êtes prêt. Lancez simplement `./build.sh` pour démarrer la concaténation et la minification — c'est exactement la commande derrière la capture d'écran au début de cet article.

##### Jetez un œil aux options de l'image Docker {#look-at-the-docker-image-flags}

Rendez-vous sur [tdewolff/minify](https://hub.docker.com/r/tdewolff/minify) et regardez le [site de démo](https://go.tacodewolff.nl/minify), les [options CLI](https://github.com/tdewolff/minify/tree/master/cmd/minify) et la documentation.

## Conclusion {#conclusion}

En combinant la puissance du scripting Bash avec l'isolation de Docker, nous avons créé un pipeline d'assets robuste. Ce setup est parfait pour les sites statiques, les projets PHP legacy, ou tout environnement où vous voulez garder votre outillage de développement le plus léger possible.

Des assets minifiés ne représentent toutefois que la moitié du chemin côté performance : les images sont généralement la partie la plus lourde d'une page. Voyez [Running some checks on your Docusaurus images](/blog/docusaurus-check-images) pour l'audit automatisé que je fais tourner sur les miennes.
