---
options:
  command_prefix: "pr:"
theme:
  name: tokyonight-storm
  override:
    default:
      # colors:
        # foreground: "4c4f69"
        # background: "ffffff"
    palette:
      colors:
        base00: "24283B"
        base01: "16161E"
        base02: "343A52"
        base03: "444B6A"
        base04: "787C99"
        base05: "A9B1D6"
        base06: "CBCCD1"
        base07: "D5D6DB"
        base08: "C0CAF5"
        base09: "A9B1D6"
        base0A: "0DB9D7"
        base0B: "9ECE6A"
        base0C: "B4F9F8"
        base0D: "2AC3DE"
        base0E: "BB9AF7"
        base0F: "F7768E"
---
<!-- LTeX: language=fr -->
<!-- pr:column_layout: [1,2] -->
<!-- pr:column: 0 -->
# Définition des environnements de développement du package
* on défini un seul
environnement (**default**)
* la fonction <span style="color: p:base0F">**forEachSupportedSystem**</span> à pour
fonction de générer un élément pour chaque architecture supportée par le package
  * ces architectures sont définie à la ligne 8 et correspondent aux architectures
  supportée par nix.
* Dans cet environnement, on fournis les packages suivants
  * **nodejs**
    c'est un projet vue.js, donc faut bien un runtime
  * **yarn**
    ici on préfèrera yarn pour pouvoir utiliser yarn2nix afin de générer les
    dépendances.
  * webstorm
    * je l'installe que pour ce projet, donc ça me permet de le garbage collecter
    quand j'en ai pas besoin (merci nix)
  * **yarn2nix**
    * yarn2nix est un outil qui vas lire notre fichier package.json et générer
    un fichier yarn.nix avec toutes nos dépendances packager pour nix, pour des
    question de reproductibilité, lors du build avec nix, les outils n'ont pas accès
    à internet, il n'est donc pas possible de juste faire un "yarn add".
<!-- pr:column: 1 -->
```file +line_numbers {13-18}
path: shoblog_code.nix
language: nix
```
<!-- pr:end_slide -->

<!-- pr:column_layout: [1,2] -->
<!-- pr:column: 0 -->
# Définition des packages

* d'une manière similaire aux **devShells**, on vas ici générer un package par
architecture supportée. Lors du build (qui se fait généralement localement),
nix va néanmoins builder uniquement le package correspondant à l'architecture
de la machine.
* Pour ce faire, on utilise la fonction <span style="color: p:base0F">
**mkYarnPackage**</span> qui fournit diverses options pour générer un package
manager par **Yarn**
  * **name**: assez explicite, le nom du package générer
  * **src**: les source sur lequel la fonction va se baser pour générer le package
  * **PackageJSON**: package.json 
  * **yarnLock**: yarn.lock
  * <span style="color: p:base0F">**yarnNix**</span>: Ah ! C'est ici qu'on
  retrouve notre fameux **yarn.nix**.
    * En fait, lors du process de build et pour
    pour des raisons de reproductibilité, les programmes n'ont pas accès à internet. Chez nix,
    toutes les dépendances doivent être connue et regroupée à l'avance. Pour ce faire,
    **yarn2nix** nous génère un fichier **yarn.nix** définissant sous forme de package
    nix toutes les dépendances de notre projet, ainsi lors du build, nix vas toutes
    les pull, donner le résultat à mkYarnPackage qui vas les installer dans son
    environnement de build.
  * Et pour finis, les phases de notre build. Par défaut, **mkYarnPackage** va
  juste chercher à build un binaire basée sur la configuration de notre package.json,
  dans notre cas 
<!-- pr:column: 1 -->
```file +line_numbers {20-45}
path: shoblog_code.nix
language: nix
```
<!-- pr:end_slide -->

<!-- pr:column_layout: [1,2] -->
<!-- pr:column: 0 -->
## buildPhase
Le build d'un package sous nix est découpé en plusieurs phases, si la plupart
sont généralement transparente, celons le cas, certaines ont besoin d'être
override en fonction des besoins. Ici, l'on cherche à packager des assets statiques, donc:
* première étape, appeler `runhook preBuild`, rien à voir avec notre affaire, mais
cela permet à d'éventuel futur dev de venir surcharger notre package sans toucher
à notre buildphase, chaque phase à des pré et post hook de la même manière.
* `mkdir $TEMPDIR/dist`, on créer un dossier temporaire pour nos fichiers de build
* `yarn run build --outDir $TEMPDIR/dist`, on run notre script de build en précisant
notre dossier temporaire comme output
* et on run le hook de postBuild

<!-- pr:column: 1 -->
```file +line_numbers {29-34}
path: shoblog_code.nix
language: nix
```
<!-- pr:end_slide -->

<!-- pr:column_layout: [1,2] -->
<!-- pr:column: 0 -->
## installPhase
Cette phase a pour rôle de placer les fichiers résultant du build dans le store
de nix, je passe sur les hook qu'on à déjà vu précédemment 
* `mkdir -p $out/`, **$out** est une variable spécifique à cette phase de build
qui pointe vers le dossier final attribué par nix pour notre package.
* `cp -r $TEMPDIR/dist/ $out/`, on copie les fichiers de notre build dans le
dossier ainsi créer et zou ! :3

<!-- pr:column: 1 -->
```file +line_numbers {36-41}
path: shoblog_code.nix
language: nix
```

<!-- pr:end_slide -->
## Résultat
  Hop, un petit coup de `nix build` et sous vos yeux ébahis, nix nous pull toutes
  nos dépendances, build notre projet et le place au chaud dans son store. \
  Bon c'est vachement bien tout ça, mais pourquoi faire ?
  On verra les avantages en détails dans d'autres articles (peut-être même dès demain ?
  mystère mystère...) mais voici déjà quelques bullet points
  * Reproductibilité
    * Nix nous assure que, pour des entrées données, le résultat sera toujours le
    même, ainsi, il nous est possible de pin un commit spécifique de nixpkgs pour
    figer la release de notre paquet dans le temps. Contrairement à un package
    manager plus classique (apt par exemple), lors du build de votre paquet, vous
    serez ainsi assurer de toujours pull la même version de node tant que l'on
    update pas le flake.lock du projet. 
  * Isolation
    * Nix installe chaque dépendance dans un dossier appellé le **store**, chaque
    dépendance étant installer dans un dossier au hash unique basé sur le nom du
    package et sa version. Ce qui fait qu'il est parfaitement possible d'avoir
    deux projets utilisant deux versions de node différentes sans aucun problème,
    et ce sans avoir besoin de docker, d'environnement virtuel ou de faire mumuse
    avec des liens symboliques. Bonus, si un autre projet nécessite la même version
    de node, nix va simplement utiliser celle déjà installer, ce qui évite les
    duplicatas.
  * Tracking
    * étant donné que toutes les dépendances de chaque package sont déclarées dans
    le `flake.nix`, il suffit de lire ce dernier pour savoir quels paquets sont
    nécessaires à son déploiement. De plus, si l'on enlève un paquet de l'environnement,
    nix vas pouvoir checker si ses dépendances sont utiliser par d'autres paquets,
    et dans la négative, les supprimer pour économiser la place. 
  * Configuration
    * Un peu hors du scope de cet exemple, mais il est possible de définir une
    fonction d'override pour un paquet afin de permettre à l'utilisateur final
    de ce dernier de spécifier des paramètres à ce dernier au moment du build.
    Que ce sois l'utilisation d'une version spécifique de node, ou une clé d'API
    par exemple.
    * en utilisant NixOS, il est possible de définir des **modules** que
    l'utilisateur peut importer dans la configuration de son système afin de
    déclarer des services, installer et configurer d'autres packages, configurer
    des interfaces réseaux, ect... Cela peut permettre d'automatiser grandement
    le déploiement de certains projets et de grandement organiser ses configurations
    (comme avec la déclaration de virtualhost nginx par exemple, teasing teasing...)
