@starterlib/cli 0.10.8 → 0.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/package.json +1 -1
- package/src/construction/precompresser.mjs +28 -2
- package/src/etapes/budget.mjs +5 -3
package/README.md
CHANGED
|
@@ -31,17 +31,17 @@ Scripts d'une SPA :
|
|
|
31
31
|
|
|
32
32
|
## Commandes
|
|
33
33
|
|
|
34
|
-
| Commande | Ce qu'elle fait
|
|
35
|
-
| --------------------------- |
|
|
36
|
-
| `starter-web start` | L'hote de developpement : sprite, simulations (remote), puis `ng serve` sous `STARTER_WEB_HOTE_DEV=1` (`--port N`)
|
|
37
|
-
| `starter-web verify` | Les etapes ci-dessous, dans l'ordre, arretees a la premiere qui echoue, dont le nom est ecrit
|
|
38
|
-
| `starter-web construire` | Sprite, `ng build`, prechargement de la police (hote), manifeste, precompression
|
|
39
|
-
| `starter-web sprite` | Pose le sprite hache (`public/`) et sa constante engendree (`sprite-genere.ts`)
|
|
40
|
-
| `starter-web manifeste` | Engendre `manifest.json` dans le dossier livre ; idempotent
|
|
41
|
-
| `starter-web precompresser` | Ecrit les variantes `.br` et `.gz` ; `starter-web precompresser <dossier>` pour un autre dossier
|
|
42
|
-
| `starter-web i18n:types` | Engendre `src/app/i18n/cles.ts`, le type des cles de chaque perimetre (`injecterTraduction<C>`)
|
|
43
|
-
| `starter-web simulations` | Recopie les stubs WireMock du service (`../src/mock`), corps compris, pour l'hote de developpement (`src/hote-dev/simulations.engendre.json`)
|
|
44
|
-
| `starter-web etapes` | Liste les etapes et les roles qu'elles concernent
|
|
34
|
+
| Commande | Ce qu'elle fait |
|
|
35
|
+
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| `starter-web start` | L'hote de developpement : sprite, simulations (remote), puis `ng serve` sous `STARTER_WEB_HOTE_DEV=1` (`--port N`) |
|
|
37
|
+
| `starter-web verify` | Les etapes ci-dessous, dans l'ordre, arretees a la premiere qui echoue, dont le nom est ecrit |
|
|
38
|
+
| `starter-web construire` | Sprite, `ng build`, prechargement de la police (hote), manifeste, precompression |
|
|
39
|
+
| `starter-web sprite` | Pose le sprite hache (`public/`) et sa constante engendree (`sprite-genere.ts`) |
|
|
40
|
+
| `starter-web manifeste` | Engendre `manifest.json` dans le dossier livre ; idempotent |
|
|
41
|
+
| `starter-web precompresser` | Ecrit les variantes `.br` et `.gz`, et `precompression.index` (chaque variante et le condense de son source, que le serveur confronte) ; `starter-web precompresser <dossier>` pour un autre dossier |
|
|
42
|
+
| `starter-web i18n:types` | Engendre `src/app/i18n/cles.ts`, le type des cles de chaque perimetre (`injecterTraduction<C>`) |
|
|
43
|
+
| `starter-web simulations` | Recopie les stubs WireMock du service (`../src/mock`), corps compris, pour l'hote de developpement (`src/hote-dev/simulations.engendre.json`) |
|
|
44
|
+
| `starter-web etapes` | Liste les etapes et les roles qu'elles concernent |
|
|
45
45
|
|
|
46
46
|
Codes de sortie : `0` conforme ; `1` une etape a echoue ; `2` la commande ne peut pas s'executer
|
|
47
47
|
(argument inconnu, projet illisible).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starterlib/cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.10",
|
|
4
4
|
"description": "Chaine de verification et de construction des SPA du socle frontal starter : starter-web verify, construire, sprite, manifeste, precompresser. Jamais en dependance de production.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -27,11 +27,21 @@
|
|
|
27
27
|
* morceau d'une construction precedente) est retiree, et une variante devenue inutile aussi :
|
|
28
28
|
* le serveur servirait sinon un contenu que plus rien ne produit.
|
|
29
29
|
*
|
|
30
|
+
* LE CONDENSE DE CHAQUE SOURCE (lot 120)
|
|
31
|
+
*
|
|
32
|
+
* Dans l'image, Jib fige toutes les dates : le serveur ne peut pas voir qu'une variante vient
|
|
33
|
+
* d'une construction precedente (une copie sans purge garde l'ancien `remoteEntry.json.gz` quand
|
|
34
|
+
* la nouvelle construction n'ecrit plus que le `.br`). L'etape ecrit donc `precompression.index`
|
|
35
|
+
* a la racine du dossier : une ligne par VARIANTE ecrite, le condense de son SOURCE (SHA-256
|
|
36
|
+
* tronque a 128 bits, comme l'ETag du serveur), deux blancs, le chemin de la variante.
|
|
37
|
+
* `ActifsStatiques` ne sert une variante que si l'index la nomme avec le condense de son source.
|
|
38
|
+
*
|
|
30
39
|
* L'etape vient APRES la generation du manifeste, qui renomme les catalogues i18n.
|
|
31
40
|
*/
|
|
32
41
|
import { brotliCompressSync, constants, gzipSync } from 'node:zlib';
|
|
42
|
+
import { createHash } from 'node:crypto';
|
|
33
43
|
import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
34
|
-
import { extname } from 'node:path';
|
|
44
|
+
import { extname, join } from 'node:path';
|
|
35
45
|
import { fichiers, ko, relatif } from '../commun.mjs';
|
|
36
46
|
|
|
37
47
|
/** Exactement ce que le serveur declare compressible (ActifsStatiques.EXTENSIONS_COMPRESSIBLES). */
|
|
@@ -48,6 +58,14 @@ export const COMPRESSIBLES = new Set([
|
|
|
48
58
|
/** Reecrit a chaque reponse par le serveur : une variante figee serait fausse. */
|
|
49
59
|
const EXCLUS = new Set(['index.html']);
|
|
50
60
|
|
|
61
|
+
/** L'index des variantes, lu par `ActifsStatiques.INDEX_DES_VARIANTES`. */
|
|
62
|
+
export const INDEX_DES_VARIANTES = 'precompression.index';
|
|
63
|
+
|
|
64
|
+
/** Le condense d'un contenu tel que le serveur le calcule : SHA-256 tronque a 128 bits, en hexadecimal. */
|
|
65
|
+
export function condense(contenu) {
|
|
66
|
+
return createHash('sha256').update(contenu).digest('hex').slice(0, 32);
|
|
67
|
+
}
|
|
68
|
+
|
|
51
69
|
/**
|
|
52
70
|
* Precompresse `dossier`. Rend `{ compresses, orphelines, octetsAvant, octetsBrotli, sansVariante }`,
|
|
53
71
|
* `sansVariante` listant les `.js` qui devraient avoir une variante brotli et n'en ont pas.
|
|
@@ -69,6 +87,7 @@ export function precompresser(dossier) {
|
|
|
69
87
|
let octetsAvant = 0;
|
|
70
88
|
let octetsBrotli = 0;
|
|
71
89
|
const sansGain = new Set();
|
|
90
|
+
const index = [];
|
|
72
91
|
for (const fichier of fichiers(dossier)) {
|
|
73
92
|
const extension = extname(fichier);
|
|
74
93
|
if (extension === '.br' || extension === '.gz') continue;
|
|
@@ -88,6 +107,7 @@ export function precompresser(dossier) {
|
|
|
88
107
|
]) {
|
|
89
108
|
if (compresse.length < contenu.length) {
|
|
90
109
|
writeFileSync(variante, compresse);
|
|
110
|
+
index.push(`${condense(contenu)} ${relatif(dossier, variante)}`);
|
|
91
111
|
ecrit = true;
|
|
92
112
|
} else {
|
|
93
113
|
// Une variante d'une passe precedente, devenue plus lourde que l'original : retiree.
|
|
@@ -102,12 +122,18 @@ export function precompresser(dossier) {
|
|
|
102
122
|
sansGain.add(fichier);
|
|
103
123
|
}
|
|
104
124
|
}
|
|
125
|
+
const cheminDeLIndex = join(dossier, INDEX_DES_VARIANTES);
|
|
126
|
+
if (index.length > 0) {
|
|
127
|
+
writeFileSync(cheminDeLIndex, `${index.sort().join('\n')}\n`);
|
|
128
|
+
} else {
|
|
129
|
+
rmSync(cheminDeLIndex, { force: true });
|
|
130
|
+
}
|
|
105
131
|
|
|
106
132
|
const sansVariante = fichiers(dossier)
|
|
107
133
|
.filter((fichier) => extname(fichier) === '.js' && !sansGain.has(fichier))
|
|
108
134
|
.filter((fichier) => !existsSync(`${fichier}.br`))
|
|
109
135
|
.map((fichier) => relatif(dossier, fichier));
|
|
110
|
-
return { compresses, orphelines, octetsAvant, octetsBrotli, sansVariante };
|
|
136
|
+
return { compresses, orphelines, octetsAvant, octetsBrotli, sansVariante, indexes: index.length };
|
|
111
137
|
}
|
|
112
138
|
|
|
113
139
|
/** Le compte rendu d'une precompression, et ses defauts (une etape devenue inutile en est un). */
|
package/src/etapes/budget.mjs
CHANGED
|
@@ -25,14 +25,16 @@ import { natureDesFichiers } from '../livraison.mjs';
|
|
|
25
25
|
export const BUDGETS_DU_REMOTE = { pageKo: 60, totalKo: 250, catalogueKo: 30 };
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Les seuils de l'hote, en Ko brotli (ADR 0031) : 300 pour le premier ecran reel,
|
|
29
|
-
* charge initiale, ramenes au socle 0.10.0 (releves et historique dans l'ADR).
|
|
28
|
+
* Les seuils de l'hote, en Ko brotli (ADR 0031) : 300 pour le premier ecran reel, 281 pour la
|
|
29
|
+
* charge initiale, ramenes au socle 0.10.0 (releves et historique dans l'ADR). La charge initiale
|
|
30
|
+
* est passee de 280 a 281 le 2026-09-29, decision du proprietaire : 280,4 Ko mesures avec le socle
|
|
31
|
+
* 0.10.9, dont les controles d'empreinte S05 du lot 272 tournent au demarrage.
|
|
30
32
|
*
|
|
31
33
|
* ⚠️ Ce ne sont pas la cible du plan SPA §2.8 (170 Ko). L'ecart restant est STRUCTUREL : un paquet
|
|
32
34
|
* partage en singleton part ENTIER, parce que n'importe quel remote peut en avoir besoin. Un seuil
|
|
33
35
|
* se baisse ; il ne se leve jamais sans mesure ecrite et sans date.
|
|
34
36
|
*/
|
|
35
|
-
export const BUDGETS_DE_L_HOTE = { premierEcranKo: 300, chargeInitialeKo:
|
|
37
|
+
export const BUDGETS_DE_L_HOTE = { premierEcranKo: 300, chargeInitialeKo: 281, cibleDuPlanKo: 170 };
|
|
36
38
|
|
|
37
39
|
/** Les imports DYNAMIQUES d'un module : les pages qu'il charge a la demande. */
|
|
38
40
|
const IMPORT_DYNAMIQUE = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
|