2.1.0 • Published 2 years ago

hornet-js-builder v2.1.0

Weekly downloads
6
License
CECILL-2.1
Repository
github
Last release
2 years ago

hornet-js-builder

hornet-js-builder a été développé dans le but premier de masquer la complexité des différentes tâches nécessaires à la construction d'un projet. Son second objectif est d'accompagner le développeur en lui fournissant des outils tout au long du developpement d'un projet.

A cet effet, il surcharge les librairies gulp et npm pour fournir des tâches se rapprochant de la philosophie maven ainsi que des utilitaires pour simplifier et pérenniser la gestion des dépendances.

Les versions de chaque dépendance déclarée doivent également être fixes (sans ^, ~ ou *) afin de pérenniser les versions.

Installation

Depuis NPM

npm install -g hornet-js-builder

s'assurer que les liens symboliques hornetbuilder et hb ont bien été crées dans le répertoire "~/bin". Si ce n'est pas le cas:

se positionner dans le répertoire "~/bin", puis:

ln -s ${cheminAccesHornetBuilderInstalléDansNode}/bin/builder-cli.js hb
ln -s ${cheminAccesHornetBuilderInstalléDansNode}/bin/builder-cli.js hornetbuilder

Depuis les sources

Installer hornet-js-builder de manière globale:

  • Se placer dans le dossier de hornet-js-builder
  • Lancer la commande
npm install -g

En tant que devDependencies de l'application

Depuis La version 2.0.0, il est possible d'ajouter le builder en tant que dépendance d'une application. Ainsi, dans la partie script du package.json de l'application, il est possible de faire référence aux commandes du builder depuis les node_modules.

Exemple:

{
    //...
    "devDependencies" : {
        //...
        "hornet-js-builder": "2.x.x"
        //...
    },

    "script": {
        //...
        "clean": "./node_modules/.bin/hornetbuilder clean-all",
        "test": "./node_modules/.bin/hornetbuilder test",
        "init-dev": "./node_modules/.bin/hornetbuilder compile:ts",
        "start": "node index.js",
        "prestart": "npm run init-dev && ./node_modules/.bin/hornetbuilder ppc",
        "start-dev": "./node_modules/.bin/hornetbuilder w"
        //...
    }
    //...
}

Note

En cas de MAJ à partir d'une version antérieure de hornet-js-builder: supprimer les dossiers node_modules de chaque projet

Commandes

Suite à cette installation, les commandes hornetbuilder et hb (alias de la première) sont accessibles en globale dans les scripts, sauf dans le cas où le builder est installée en tant que dépendance de l'application

Variables d'environnement utilisées par le builder

  • HB_EXT_MODULES : Cette variable contient les chemins, séparés par un point virgule, des répertoires des externalModules utilisés par l'application. L'utilisation de cette variable est préconisée plutôt en cas d'utilisation de modules externes.

  • HB_WATCH_DELAY : Permet de surcharger la clé de configuration delay de nodemon.

Principe de gestion des dépendances

Un projet géré par le builder est un projet node classique avec une déclaration des dépendances dans le fichier package.json.

  • dependencies: Pour déclarer les dépendances applicatives
  • devDependencies: Pour déclarer les dépendances de build (les dépendances nécessaires uniquement pour les TU, la documentation des modules utilisés, les modules nécessaires lors du package etc.)
  • peerdependencies: Pour déclarer les dépendences du host qui sont nécessaires à l'installation du module
  • bundleddependencies: Pour déclarer un tableau de dépendances qui seront packagés lors de la publication du module
  • optionaldependencies: Pour déclarer les dépendances optionnelles c'est-à-dire celles dont une erreur d'install ne causera pas de build failure.

Utiliser hornetbuilder en ligne de commandes

  • Ouvrir une invite de commande et se placer dans le dossier du projet.

Exemple:

cd D:\dev\workspace\applitutoriel\applitutoriel-js
  • Taper la commande hornetbuilder (ou hb) suivi de la tâche à exécuter. Exemple:
hb test

Une aide est fournie en tapant la commande

hb --help

Les options suivantes sont alors proposées:

OptionRôle
-V, --versionAffiche la version du builder
-d, --debugActive les messages de logs du builder en mode debug
--show-webpack-filesActive le listing des fichiers embarqués par webpack lors de la construction du bundle de fichiers clients. Note: Les fichiers sont triés par taille croissante
--webpackVisualizerVisualisation de la répartition des sources projets et node modules dans un chart, /static/dev/webpack-visualizer.html
-i, --ideIndique que c'est l'IDE qui gère la compilation des fichiers .ts, .d.ts et .map. Dans ce mode la compilation des fichiers TypeScripts est désactivée ainsi que les watchers associés. De même, la tâche clean ne supprime plus ces fichiers. Cette option doit être utilisée dès lors qu'un IDE est lancé sur les projets
-r, --registry Permet d'utiliser un repository spécifique. Par défaut le repository défini dans le fichier .npmrc est utilisé
--publish-registry Permet de spécifier un repository npm spécifique pour la publication autre que celui par défaut. Par défaut le repository défini dans le fichier .npmrc est utilisé
-f, --forcePermet de forcer la mise à jour des dépendances
--skipTestsPermet de ne pas exécuter les tests si ceux-ci doivent être exécutés (ex: tâche package)
--skipDedupePermet de ne pas exécuter npm dedupe sur l'installation des dépendances
--stopOnErrorPermet de stopper toutes les tâches sur une erreur dans les tests
--skipMinifiedPermet de ne pas minifier les chuncks
--noWarnPermet de ne pas afficher les warning
-p, --debugPort Indique le port utilisé par node pour permettre la connexion d'un debugger externe"
--lintRulesIndique un fichier de rules tslint.json autre que celui utilisé par le builder
--lintReportIndique le format de sortie pour tslint : prose (défaut), json, verbose, full, msbuild
--fileIndique le chemin d'un fichier
--tsfileIndique le nom du fichier de configutaion typescript à utiliser
--devactive le mode developpement
--offlineactive le mode offline pour la récupération des dépendances, ex : coupure réseau. Prerequis avoir les node_modules, ajouter fetch-retries=0 dans .npmrc
--versionFixIndique la version ou suffixe si commence par '-', '.' ou si null calcule un suffixe avec timestamp, si 'RC' calucle la prochaine RC.
--versionSearchpréfixe de la dernière version

Toutes les autres options non prises en charge par le builder, sont passées directement aux outils tiers. Pour le moment seul NPM est concerné par ce principe (donc les taches d'installation), exemple :

hb install --no-package-lock

ne sauvegardera pas les dépendances installées de le fichier package-lock.json.

hb install -E

sauvegardera les dépendances installées en version exacte dans le package.json mais qu'avec la présence d'external module, car chaque module est installé avec la commande 'npm i @' sinon c'est la commande 'npm i' donc pas besoin de présicer le -E (save exact)

au même titre que :

hb compile -E

exécutera l'installation des dépendances de dev avec l'option 'exact' sur le même principe que vu précédemment (suivant la présence de module externe).

donc cf https://docs.npmjs.com/misc/config.html et https://docs.npmjs.com/cli/install.html

Utiliser hornetbuilder en mode interactive

Le principe du mode interactive est d'être immergé dans les commandes du builder sans pour autant à avoir à retaper "hb ..." et de bénéficier d'un mode intuitif d'autocompletion.

hb 

Résultat :

[15:49:52] 
  _    _                       _       _      
 | |  | |                     | |     (_)     
 | |__| | ___  _ __ _ __   ___| |_     _ ___  
 |  __  |/ _ \| '__| '_ \ / _ \ __|   | / __| 
 | |  | | (_) | |  | | | |  __/ |_  _ | \_ \ 
 |_|  |_|\___/|_|  |_| |_|\___|\__|(_)| |___/ 
                                     _/ |     
                                    |__/      

[15:49:52] Démarrage de hornet-js-builder dans  /home/<user>/Dev/workspaceJS/applitutoriel-modules/applitutoriel-js
[ '/home/<user>/Dev/node-v8.14.0-linux-x64/bin/node',
  '/home/<user>/bin/hbn' ]
[16:01:33] Builder lancé sur le projet applitutoriel-js en version 5.4.0
[16:01:33] Utilisation du registry configuré dans NPM : http://artifactory.app.diplomatie.gouv.fr/artifactory-dev/api/npm/repository-npm-mae-dev
[16:01:35] Chargement des tâches du projet 'applitutoriel-js'
[16:01:35] __la task rewrite est terminée
[16:01:35] _Starting 'dependencies:install-dev'...
[16:01:35] Lancement installation des dépendances de applitutoriel-js
[16:01:37] _Finished 'dependencies:install-dev' after 2.67 s
[16:01:37] _Starting 'default'...
[16:01:37] __Starting 'interactive'...
hb$

le prompt "hb$" s'affiche est permet alors de lancer n'importe quelle commande du builder.

Il est possible de lister toutes les commandes avec un double "tab" ou bien d'utiliser l'aide

hb$ help

L'arrêt du mode interactive ce fait avec la commande "exit".

hb$ exit

Configurer un projet pour utiliser hornetbuilder

Fichier de configuration des dépendances : package.json

Exemple complet de package.json

{
  "name": "applitutoriel-js-lite",
  "version": "5.x.x",
  "license": "CECILL-2.1",
  "main": "index.js",
  "description": "Application tutoriel utilisant le Framework hornet",
  "bugs": {
    "url": "https://github.com/diplomatiegouvfr/applitutoriel-modules/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/diplomatiegouvfr/applitutoriel-modules.git"
  },
  "dependencies": {
    "applitutoriel-js-common": "5.x.x",
    "hornet-js-core": "5.x.x",
    "hornet-js-database": "5.x.x",
    "hornet-js-passport": "5.x.x",
    "hornet-js-react-components": "5.x.x",
    "hornet-js-logger": "5.x.x",
    "hornet-js-utils": "5.x.x",
    "hornet-js-bean": "5.x.x",
    "pg": "~7.3.0",
    "sequelize": "~4.33.4",
    "sqlite3": "~3.1.13",
    "tslib": "~1.9.3"
  },
  "devDependencies": {
    "@types/node": "~10.12.30",
    "@types/react": "~16.8.14",
    "@types/sequelize": "~4.27.48",
    "hornet-js-test": "5.x.x"
  },
  "scripts": {
    "init-dev": "hb install",
    "start": "node index.js"
  },
  "author": "MEAE - Ministère de l'Europe et des Affaires étrangères"
}

Fichier de configuration Typescript pour la compilation : tsconfig.json

Les projets doivent impérativement avoir un fichier tsconfig.json à la racine. Celui-ci regroupe les informations de compilation typescript nécessaire au projet.

ex :

{
  "compilerOptions": {
    "baseUrl": "./",
    "emitDecoratorMetadata": true,    
    "esModuleInterop": false,
    "experimentalDecorators": true,
    "importHelpers": true,
    "jsx": "react",
    "lib": ["dom", "es2015"],
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "target": "ES5",
    "preserveSymlinks": true
  },
  "include": [
    "index.ts",
    "src/**/*.ts*",
    "test/**/*.ts*",
    "./node_modules/applitutoriel-js-common/index.d.ts",
    "./node_modules/hornet-js-bean/index.d.ts",
    "./node_modules/hornet-js-components/index.d.ts",
    "./node_modules/hornet-js-core/index.d.ts",
    "./node_modules/hornet-js-database/index.d.ts",
    "./node_modules/hornet-js-logger/index.d.ts",
    "./node_modules/hornet-js-utils/index.d.ts",
    "./node_modules/hornet-js-passport/index.d.ts",
    "./node_modules/hornet-js-react-components/index.d.ts",
    "./node_modules/hornet-js-test/index.d.ts"
  ],
  "exclude": [
    "istanbul"
  ]
}

Fichier de configuration builder : builder.js

Les projets doivent comporter à la racine un fichier builder.js afin de déterminer le type de l'application : application, module, ... ainsi que les différentes tâches à éxécuter nécessaire à la construction.

Ce fichier doit comporter au minimum le code suivant pour hornet.js:

module.exports = {
    type: "application",
    authorizedPrerelease: "true",
    
    gulpTasks: function (gulp, project, conf, helper) {
        //Add task if needed
        /*gulp.beforeTask("compile", function () {
         helper.info("Exemple before compile task");
         });

         gulp.afterTask("compile", function () {
         helper.info("Exemple after compile task");
         });*/

        // Cas PARTICULIER de l'application tuto pour pouvoir la générer en mode SPA et ISOMORPHIC sur la PIC
        // => on force la tâche prepare-package:spa tout le temps
        // si mode fullSpa : on redéfini les tâches 'watch' & 'watch-prod' pour y inclure la tâche "prepare-package-spa"
        //gulp.task("watch", ["compile", "prepare-package:spa", "watch:client"]);
        //gulp.task("watch-prod", ["compile", "prepare-package:spa", "watch:client-prod"]);
        gulp.addTaskDependency("package-zip-static", "prepare-package:spa");
        // conf.template.messages = require("applitutoriel-js-common/src/resources/messages.json")
        conf.template.forEach((elt, idx) => {
            if (conf.template[idx].context.forEach) {
                conf.template[idx].context.forEach((elt, idx2) => {
                    conf.template[idx].context[idx2].messages = {"applicationTitle": "Application TUTORIEL"};
                });
            } else {
                conf.template[idx].context.messages = {"applicationTitle": "Application TUTORIEL"};
            }
        });

    },
    externalModules: {
        enabled: false,
        directories: [
        ]
    },
    config: {
        routesDirs: ["." + path.sep + "routes"],

        // Exemple d'exclusion de fichiers/répertoires local à l'application et de modules
        // Cet exemple n'est pas forcement cohérent puisque le client.js n'est pas dépendant des middlewares
        // Il est là à titre d'exemple uniquement

        clientExclude: {
            dirs: [
                path.join("src", "services", "data"),
                "src/middleware",
                "nodemailer",
                "applitutoriel-js-common/src/actions"],
            filters: [
                path.join("src", "services", "data") + "/.*-data-\.*",
                ".*/src/actions/.*",
                "^config/*"
            ],
            modules: [
                "config",
                "continuation-local-storage",
                "carbone",
                "pdfmake",
                "pdfmake/src/printer",
                "pdfkit",
                "nodemailer",
                "fontkit"
            ]
        },
        clientContext: [
            [/moment[\/\\]locale$/, /fr|en/],
            [/intl[\/\\]locale-data[\/\\]jsonp$/, /fr|en/],
            [/.appender/, /console/]
        ],
        typescript: { //bin: "~/Dev/node-v4.5.0-linux-x64/lib/node_modules/typescript"
        },
        template: [
            {
                context: [{
                    error: "404",
                    suffixe: "_404",
                    message: "Oops! Nous ne trouvons pas ce que vous cherchez!"
                }, {error: "500", suffixe: "_500", message: "Oops! Une erreur est survenue!"}],
                dir: "./template/error",
                dest: "/error"
            }, {
                context: {message: "test template"}
            }
        ],
        spaResources: [path.join("..", "applitutoriel-js-common", "src", "resources") + "**/*.json"],
        dev: {
            dllEntry: {vendor: ["ajv", "react-dom", "react", "bluebird", "moment", "intl", "moment-timezone", "lodash"]}
        }
    }
};

Ce fichier doit comporter au minimum le code suivant pour hornet.js-lite:

module.exports = {
    type: "application",

    gulpTasks: function (gulp, project, conf, helper) {

        helper.excludeNodeModulesFromWebpack(
            ["config", "continuation-local-storage", "sequelize", "pdfmake", "carbone", "csv-parser", "nodemailer"],
            conf.webPackConfiguration
        );
        conf.template.forEach((elt, idx) => {
            if (conf.template[idx].context.forEach) {
                conf.template[idx].context.forEach((elt, idx2) => {
                conf.template[idx].context[idx2].messages =  {"applicationTitle": "Application TUTORIEL"};
                });
            } else {
                conf.template[idx].context.messages =  {"applicationTitle": "Application TUTORIEL"};
            }
        });
    },

    externalModules: {
        enabled: false,
        directories: [
        ]
    },
    
    config: {
        routesDirs: ["." + path.sep + "routes"],
        ressources: ["database/**/*"],
        // Exemple d'exclusion de fichiers/répertoires local à l'application et de modules
        // Cet exemple n'est pas forcement cohérent puisque le client.js n'est pas dépendant des middlewares
        // Il est là à titre d'exemple uniquement
        clientExclude: {
            dirs: [
                path.join("src", "services", "data"),
                path.join("src", "dao"),
                "src/middleware",
                "nodemailer"],
            filters: [
                path.join("src", "services", "data") + "/.*-data-\.*"
            ],
            modules: [
                "hornet-js-database",
                "config",
                "continuation-local-storage",
                "sequelize",
                "pdfmake",
                "carbone",
                "csv-parser",
                "nodemailer",
                "tls"
            ]
        },
        clientContext: [
            [/moment[\/\\]locale$/, /fr|en/],
            [/intl[\/\\]locale-data[\/\\]jsonp$/, /fr|en/],
            [/.appender/, /console/]
        ],
        typescript: { //bin: "~/Dev/node-v4.5.0-linux-x64/lib/node_modules/typescript"
        },
        karma: {
            template: {
                debug: "./test/template/debug.html",
                context: "./test/template/context.html",
                clientContext: "./test/template/client_with_context.html"
            }
        },
        template: [
            {
                context: [{error: "404", suffixe: "_404", message: "Oops! Nous ne trouvons pas ce que vous cherchez!"}, {error: "500", suffixe: "_500", message: "Oops! Une erreur est survenue!"}],
                dir: "./template/error",
                dest: "/error"
            }, {
                context: {message: "test template"}
            }
        ]
        dev: {
            dllEntry: {vendor: ["hornet-js-react-components", "hornet-js-components", "hornet-js-utils"]}//"ajv", "d3", "react-dom", "react", "bluebird", "moment", "intl", "moment-timezone", "lodash"
        }
    }
};
  • La clé type indique au builder le type de projet actuel. Pour une application le type doit toujours être application (types possibles : "parent", "application", "application-server", "module", "composant", "custom").

    • parent: Comme son nom l'indique, c'est le type des projets parent.
    • application: C'est le type d'une application. Par exemple, une application lite (générée à travers generator-hornet-js-lite), ou full (générée à travers generator-hornet-js).
    • application-server: C'est le type d'une application exposant que des API, C'est par exemple le type des applications générée à travers generator-hornet-js-batch
    • module ou component: Ces deux types sont utilisés par le framework. Ce sont les types des modules hornet ou hornet-comminity. Les projets peuvent l'utiliser s'ils veulent mettre dans des artefacts des composants/modules utilisables par leurs applications.
    • custom: Le type custom est utilisé pour décrire les autres types ne cadrant pas avec les types ci-dessus. Ce type est utilisé par hornet-js-man
  • La fonction gulpTasks permet :

    • d'ajouter de nouvelles tâches gulp au moyen du paramètre gulp
    • de modifier la configuration par défaut du builder (ajouter un répertoire de sources, modifier la conf webpack, ...)
    • d'exécuter des traitements avant ou après une tâche spécifique au moyen des méthodes gulp.beforeTask(taskName, func) et gulp.afterTask(taskName, func)
    • d'ajouter des dépendances à une tâche existante au moyen de la méthode gulp.addTaskDependency(taskName, dependencyTaskName)
  • L'objet externalModules permet de déclarer des dépendances à partir de répertoires externes.
  • L'objet config permet de surcharger la configuration du builder dans chaque application
    • autoGenerateIndex permet d'autogénérer les index.js, index.ts (utile pour le mode dev et dll, ou l'import auto des dts). index.d.ts est autogénéré pour les types modules.
    • routesDirs permet de spécifier les répertoires des routes pour le code splitting automatique
    • clientExclude est un raccourci pour modifier la conf webpack et rajouter des externals
    • clientNoParse est un raccourci pour modifier la conf webpack et rajouter des module.noParse
    • typescript.bin permet de préciser une autre version de typescript pour la transpilation que celle utiliser ambarquée par le builder
    • spaResources liste de filtres permettant d'ajouter des ressources pour la génération de chunck SPA
    • dllEntry permet de préciser des dll webpack (gain de temps de construction des chunck)
    • template permet de configurer la tâche de templating html
      • dir répertoire des templates (par défault 'template')
      • context objet disponible pour le templating
      • dest répertoire de destination
    • clientContext Filtre les modules ex moment et intl : [/moment\/\locale$/, /fr|en/], [intl\/\locale-data\/\jsonp$/, /fr|en/]
    • spaFilter Filtre les ressources pour le packaging spa, copie des fichiers ressource dans /static
    • dev Expérimentation du builder
      • dllEntry optimisation de chargement des librairies en dev
  • context contiendra par défaut :
     {
       project: 
       { 
         name: project.name,
         version: project.version, 
         static: "static-" + project.version + "/"
       }
     }

Exemple:

...
    gulpTasks: function (gulp, project, conf, helper) {
        gulp.task("maNouvelleTache", function(done) {
            helper.info("Execution de 'maNouvelleTache'");
            done();
       });
    },
...
hb maNouvelleTache

Objet de configuration du builder

La configuration par défaut du builder est la suivante:

{
    src: "src",
    test: "test",
    static: staticDir,
    header: {},
    database: "database",
    environment: {
        dir: "environment",
        configuration: "environment/configuration",
        templates: "environment/templates"
    },
    testEnvironment: {
        dir: "test-environment",
        configuration: "test-environment/configuration",
        templates: "test-environment/templates"
    },
    js: "js",
    dll: "dll",
    config: "./config",
    generatedTypings: {
        dir: ".",
        file: "definition.d.ts"
    },
    clientJs: "client.js",
    routesDirs: ["." + path.sep + "routes"],
    componentsDirs: [path.join("..", "src")],
    buildWorkDir: "target",
    testReportDir: testReportDir,
    testWorkDir: testWorkDir,
    templateDir: "html",
    mocha: {
        preserveSymlinks: true
    },
    istanbul: {
        coverageVariable: "__coverage__",
        dir: path.join(testReportDir),
        reporters: ["lcov", "text", "text-summary", "cobertura", "json", "html"],
        reportOpts: {
            dir: path.join(testReportDir, "mocha"),
            lcov: { dir: path.join(testReportDir, "mocha", "lcov"), file: "lcov.info" },
            html: { dir: path.join(testReportDir, "mocha", "html") },
            json: { dir: path.join(testReportDir, "mocha"), file: "coverage_mocha.json" },
            cobertura: { dir: path.join(testReportDir, "mocha") }
        },
        instrumenter: {
            includeUntested: true,
            preserveComments: true,
            noCompact: true,
            all: true,
            "include": [
                "src/**/*.js"
            ],
            "exclude": [
                "node_modules/**/*"
            ],
            inPlace: true,
            sourceMap: true
        }
    },
    karma: {
        reporters: ["mocha", "coverage"],
        reportOpts: {
            dir: path.join(testReportDir, "karma"),
            lcov: { dir: path.join(testReportDir, "karma", "lcov"), file: "lcov.info" },
            html: { dir: path.join(testReportDir, "karma", "html") },
            json: { dir: path.join(testReportDir, "karma"), file: "converage_karma.json" }
        }
    }, merge: {
        reporters: ["lcov", "text", "text-summary", "cobertura", "json", "html"],
        reportOpts: {
            dir: path.join(testReportDir, "merge"),
            lcov: { dir: path.join(testReportDir, "merge", "lcov"), file: "lcov.info" },
            html: { dir: path.join(testReportDir, "merge", "html") },
            json: { dir: path.join(testReportDir, "merge"), file: "coverage.json" },
            cobertura: { dir: path.join(testReportDir, "merge") }
        }
    }, remap: {
        reporters: ["lcovonly", "text", "text-summary", "cobertura", "json", "html"],
        reportOpts: {
            dir: path.join(testReportDir, "remap"),
            lcovonly: { dir: path.join(testReportDir, "remap", "lcov"), file: "lcov.info" },
            html: { dir: path.join(testReportDir, "remap", "html") },
            json: { dir: path.join(testReportDir, "remap"), file: "coverage.json" },
            cobertura: { dir: path.join(testReportDir, "remap"), file: "cobertura-coverage.xml" }
        }

    },
    webPackConfiguration: {
        module: {}
    },
    webPackMinChunks: 3,
    template: {
        context: {}
    }
}

Configuration projet

Configuration webpack

Le builder propose une configuration webpack par défaut pour les applications. Cependant, les projets sont libres de la surchager ou même de fournir leur configuration. Celle-ci doit être dans un fichier à la racine du projet :

  • webpack.config.js : Ce fichier doit contenir toute la configuration webpack dont a besoin le projet. Il doit exporter une fonction et retourner la configuration à utiliser. Si ce fichier est présent, aucune configuration du builder ne sera usitée. Il est possible de le décliner par environnement par exemple webpack.config.prod.js, webpack.config.dev.js etc, avec la valeur de la variable d'environnement NODE_ENV.
/**
 * @param {object} project information du projet concerné.
 * @param {object} conf configuration du projet.
 * @param {object} helper classe Helper du builder.
 * @param {object} webpackConfigPart méthodes de constitution de la configuration webpack (hornet-js-builder/src/builders/configuration/webpack/config-parts.js).
 * @param {object} configuration configuration webpack calculée pour le projet.
 * @param {object} webpack instance de webpack.
 */
module.exports = (project, conf, helper, webpackConfigPart, webpack) => {
     return {
       // Retourner la config complète de l'application
     }
}
  • webpack.addons.config.js: Pour fournir une partie de la configuration ou surchager celle du builder, utiliser plutôt le fichier webpack.addons.config.js. Ce dernier doit exporter une fonction et retourner la configuration à utiliser. Il est également possible de le décliner par environnement par exemple webpack.addons.config.prod.js, webpack.addons.config.dev.js etc, avec la valeur de la variable d'environnement NODE_ENV.
module.exports = (project, conf, helper, webpackConfigPart, configuration, webpack) => {
        return {
        ...configuration,
        "node": {
            "global": true,
            "process": true,
            "__filename": true,
            "__dirname": true,
            "Buffer": true,
            "setImmediate": true,
            "cluster": "empty",
            "child_process": "empty"
        }
    }
}

NB: Le builder ne fait pas de merge entre la configuration fournie et celle qu'elle propose. Il passe en argument de la fonction sa configuration. Le projet a la responsabilité de renvoyer dans l'objet retourné toute sa configuration.

Configuration karma

Le builder propose une configuration karma par défaut pour les applications. Cependant, les projets sont libres de la surchager ou même de fournir la configuration complète. Les projets qui souhaitent fournir une configuration karma spécifique doivent la décrire dans un des fichiers suivants à la racine :

  • karma.config.js : Ce fichier doit contenir toute la configuration karma dont a besoin le projet. Il doit exporter une fonction et retourner la configuration à utiliser. Si ce fichier est présent, aucune configuration du builder ne sera usitée. Il est possible de le décliner par environnement par exemple karma.config.prod.js, karma.config.dev.js etc, avec la valeur de la variable d'environnement NODE_ENV.

Exemple:

module.exports = (project, conf, helper, webpackConfigPart) => {
    return {
       // Retourner la config karma complète de l'application
    }
}
  • karma.addons.config.js: Ce fichier est utilisé pour fournir une configuration spécifique ou surchager celle proposée par le builder. Il doit exporter une fonction et retourner la configuration à utiliser. Il est également possible de le décliner par environnement par exemple karma.addons.config.prod.js, karma.addons.config.dev.js.etc, avec la valeur de la variable d'environnement NODE_ENV.
const path = require("path");

module.exports = (karmaConfig) => {
    return {
        ...karmaConfig,
        browsers: ["FirefoxHeadless"],
        customLaunchers: {
            FirefoxHeadless: {
                base: 'Firefox',
                flags: ['-headless'],
            },
        },
        template: {
            debug: "./test/template/debug.html",
            context: "./test/template/context.html",
            clientContext: "./test/template/client_with_context.html"
        },
        clientContext: [
            [/moment[\/\\]locale$/, /fr|en/],
            [/intl[\/\\]locale-data[\/\\]jsonp$/, /((fr)|(en))$/],
            [/^\.$/, (context) => {
                if (!/\/log4js\/lib$/.test(context.context)) return;
                context.regExp = /^\.\/appenders\/console.*$/;
                context.request = ".";
            }]
        ],
        clientExclude: {
            modules: ["cluster", "continuation-local-storage"]
        }
    };
}

NB: Le builder ne fait pas de merge entre la configuration fournie et celle qu'elle propose. Il passe en argument de la fonction sa configuration. Le projet a la responsabilité de renvoyer dans l'objet retourné toute sa configuration.

Les tâches fournies par hornetbuilder

Les tâches de gestion des dépendances

hornetbuilder fourni les tâches suivantes afin de gérer les dépendances d'un projet :

TâcheRôleDépendancesTypes de projet supportés
dependencies:clean-allsupprime toutes les dépendances et le package-lock.json*
dependencies:cleansupprime les dépendances (contenu du répertoire node_modules)*
dependencies:installlance la commande npm install --prod*
dependencies:install-linkCopie dans les node_modules les dependencies en lien*
dependencies:install-devLance la commande npm install --dev*
dependencies:install-dev-linkCopie dans les node_modules les devDependencies en lien`| |*
dependencies:install-ci-prodLance la commande npm ci --prod*
dependencies:install-ci-devLance la commande npm ci --dev*
installinstall les dépendances de l'applicationdependencies:install, dependencies:install-link, dependencies:install-dev, dependencies:install-dev-link*
versions:setpermet de changer la version du projet*
versions:getpermet de récupérer les versions du projet*
dependency:setpermet de changer la version d'un module de dépendance du projet*
dependency:set-snapshotpermet de changer la version d'un module de dépendance du projet avec une version snapshotversions:get*
dependencies:versions:updatepermet de changer la version d'une ou un ensemble de dépendances du projet avec une dernière version. A utiliser avec les options versionSearch et module.*
iAlias de "install"install*

NB: Le type de projet fait référence au type défini dans le ficher builder.js. La valeur * indique que la tâche est disponible pour tous les types de projet.

Le diagramme de séquence suivant explique les enchaînements effectués par la tâche install Diagramme de séquence de la tâche install

Les tâches de compilation

hornetbuilder fourni les tâches suivantes afin de compiler les sources d'un projet :

TâcheRôleDépendancesTypes de projet supportés
compile:tsTranspile les sources TS en Javascript.S'exécute uniquement si l'option "-i" (--ide) n'est pas utilisée.clean*
compileTranspile les sources TS en Javascriptinstall, compile:tsparent, application, application-server, custom
compile:runTranspile les sources TS en Javascript compile:ts parent, application, application-server, custom
compile:runTranspile les sources TS en Javascriptcompile:ts, clean:index-dts, compute-index:dts, rewrite:modulemodule, composant
compileTranspile les sources TS en Javascriptinstall, compile:ts, clean:index-dts, compute-index:dts, rewrite:modulemodule, composant

Diagramme de séquence de la tâche compile

Les tâches de test

hornetbuilder fourni les tâches suivantes afin d'exécuter les tests d'un projet :

TâcheRôleDépendancesTypes de projet supportés
prepare:testSourcesCopie les sources originales et compilées dans le répertoire de travail des tests : istanbulcompileparent, application, application-server, custom
prepare:testSourcesCopie les sources originales et compilées dans le répertoire de travail des tests : istanbulcompile:ts, clean:index-dts, compute-index:dtsmodule, composant
test:instrumentDéfini les instruments de couverture de code sur les sourcesprepare:testSources*
testExécute les tests unitaires et la mesure de couverture de codeclean:test, install, compile:ts, test:mocha:run, test:karma:run, test:merge-reports, test:remap-reportsparent, application, application-server, custom
testExécute les tests unitaires et la mesure de couverture de codeclean:test, install, compile:ts, generate-index:dts, test:mocha:run, test:karma:run, test:merge-reports, test:remap-reports, rewrite:modulecomponent, module
test:runExécute les tests mocha et karmaclean:test, test:mocha:run, test:karma:run, test:merge-reports, test:remap-reportsparent, application, application-server, custom
test:runExécute les tests mocha et karmaclean:test, generate-index:dts, test:mocha:run, test:karma:run, test:merge-reports, test:remap-reports, rewrite:modulemodule, composant
test:karma:runExécute les tests karmaclean-test:karma*
test:karmaExécute les tests basées sur KarmaJsinstall, compile:ts, test:karma:run*

Diagramme de séquence de la tâche test

Les tâches de nettoyage

hornetbuilder fournit les tâches suivantes afin de nettoyer un projet :

TâcheRôleRépertoire/fichierDépendancesTypes de projet supportés
cleanSupprime les fichiers générés (.js, .map et .d.ts dans le dossier de sources)clean:src, clean:test*
clean:buildSupprime le répertoire de build./target*
clean:testSupprime le dossier istanbul ainsi que les fichiers générés (.js, .map et .d.ts dans le dossier de tests)test, test_report, karma_html*
clean:staticSupprime les fichiers statics générés par webpack./static/js*
clean:static-dllSupprime les fichiers dll statics générés par webpack./static/js/dll*
clean:static-allSupprime les fichiers dll statics générés par webpack + les dll./static/js/dll/*clean:static, clean:static-dll*
clean:srcSupprime les fichiers généré dans le répertoire source ./srcextended/.js", "**/.json", "*/.jsx*
clean:templateSupprime les templates générées dans la partie static./static/templateDir*
clean:publishSupprime le tmpPublish généré suite à la pubbkication./tmpPublish*
clean:projectSupprime tous les fichiers et dépendancesclean, clean:build, dependencies:clean, clean:static, clean:template, clean:publish*
clean-allSupprime tous les fichiers, dépendances et package-lockclean, clean:build, dependencies:clean-all, clean:static, clean:template, clean:publish*

Les tâches de construction des livrables

hornetbuilder fourni les tâches suivantes afin de construire les livrables d'un projet :

TâcheRôleDépendancesTypes de projet supportés
prepare-package-dllLance WebPack pour la construction des dll's js clientapplication
prepare-packageLance WebPack pour la construction du js client en mode production (pour les types application) et copie les livrables dans le répertoire targetprepare-package:minified(pour les types application), prepare-all-packageapplication, application-server
prepare-package:minifiedLance WebPack avec la minification pour la construction du js client, mode Production par défautapplication
prepare-package-clientLance WebPack avec la minification pour la construction du js client, mode développementprepare-package-dllapplication
prepare-package:spaCopie les ressources nécessaire pour le mode spa dans le répertoire staticapplication
prepare-package-spaPrépare les fichiers à packager pour un projet en FullSpa mode Productionprepare-package:spa, prepare-packageapplication
prepare-all-packagecopie les livrables dans le répertoire targetprepare-cleanapplication, application-server
template-htmlLance le templating htmlapplication
zip-staticConstruit le livrable statique (zip)application
zip-dynamicConstruit le livrable dynamique (zip)application, application-server
find-unused-template-varRetrouve dans les fichiers *.json des templates de test les variables inutiliséesapplication, application-server
generate-props2jsonTransforme les *.properties en jsonapplication, application-server
generate-templateGénère les templates de configuration en valorisant correctement les variablesgenerate-props2jsonapplication, application-server
validate-templateVérifie que les variales dans les fichiers template sont correctement valoriséesgenerate-templateapplication, application-server
zip-environmentConstruit le livrable environment (zip)validate-template, find-unused-template-varapplication, application-server
zip-databaseConstruit le livrable database (zip)application, application-server
package-zip-staticConstruit le livrable statique (zip)prepare-package-client:minified, zip-staticapplication
package-zip-dynamicConstruit le livrable dynamique (zip)prepare-package-client:minified, zip-dynamicapplication application-server
packagePackage global de l'application en mode Productiontemplate-html, dependencies:install-ci-prod, prepare-package, zip-static, zip-dynamic,zip-environment, zip-databaseapplication
packagePackage global de l'application en mode Productioncompile, test, dependencies:install-ci-prod, prepare-all-package, zip-dynamic, zip-environment, zip-databaseapplication-server
packagePackage global de l'application en mode Productiontestcustom, parent, module, composant
package:spaPackage SPA de l'application en mode Productioncompile, test, template-html, dependencies:install-ci-prod, prepare-package-spa, zip-static, zip-dynamic, zip-environment, zip-databaseapplication
process-imgDéplacement des images vers le répertoires staticapplication
process:scssGeneration des css à partir des scssapplication
process:sassLance node sassprocess:img, process:scssapplication

Le diagramme suivant montre les enchainements effecués lors du lancement de la tâche package

Diagramme de séquence de la tâche package

Les tâches de watch

hornetbuilder fourni les tâches suivantes afin d'outiller le démarrage d'une application en développement

TâcheRôleDépendancesTypes de projet supportés
watch:ts:exeEcoute les modifications sur les fichiers TS et les recompile à la volée.S'exécute uniquement si l'option "-i" (--ide) n'est pas utiliséeapplication, application-server
watch:ts:runEcoute les modifications sur les fichiers TS et les recompile à la volée.S'exécute uniquement si l'option "-i" (--ide) n'est pas utiliséecompileapplication, application-server
watch:ts:exeEcoute les modifications sur les fichiers TS et les recompile à la volée.S'exécute uniquement si l'option "-i" (--ide) n'est pas utiliséecustom, parent, composant, module
watch:ts:runEcoute les modifications sur les fichiers TS et les recompile à la volée.S'exécute uniquement si l'option "-i" (--ide) n'est pas utiliséedependencies:install, dependencies:install-link, generate-index, generate-index:dts, rewrite:modulecustom, parent, composant, module
watch:serveur:exeEcoute les modifications sur les fichiers et redémarre le serveur node pour les prendre en compte.Démarre nodejs en mode developmentapplication, application-server
watch:serveur:runEcoute les modifications sur les fichiers et redémarre le serveur node pour les prendre en compte.Démarre nodejs en mode developmentwatch:ts:runapplication, application-server
watch:serveur-prodEquivalent à watch:serveur mais avec nodejs en mode productionwatch:ts:runapplication, application-server
watch:exeEcoute les modifications des fichiers et redémarre le serverwatch:ts:exe, watch:client:exe, watch:serveur:exeapplication
watch:exeEcoute les modifications des fichiers et redémarre le serverwatch:ts:exe, watch:serveur:exeapplication-server
watch:exeEcoute les modifications des fichiers et redémarre le serverwatch:ts:exe, watch:serveur:exeparent, custom, composant, module
watch:runEquivalent à watch:exe mais effectue en plus l'install et la compile des fichiercompile, watch:ts:exe, watch:client:exe, watch:serveur:exeapplication
watch:runEquivalent à watch:exe mais effectue en plus l'install et la compile des fichiercompile, watch:ts:exe, watch:serveur:exeapplication-server
watchEquivalent à watch:exe mais effectue en plus l'install et la compile des fichierdependencies:install, compile, watch:ts:exe, watch:client:exe, watch:serveur:exeapplication
watchEquivalent à watch:exe mais effectue en plus l'install et la compile des fichierdependencies:install, compile, watch:ts:exe, watch:serveur:exeapplication-server
watch:client:exeEcoute les modifications sur les fichiers et relance WebPack à la volée.Lance WebPack en mode development.clean:static, prepare-package-dllapplication
watch:client:runEcoute les modifications sur les fichiers et relance WebPack à la volée.Lance WebPack en mode development.clean:static, prepare-package-dllapplication
watch:clientEcoute les modifications sur les fichiers et relance WebPack à la volée.Lance WebPack en mode development.clean:static, prepare-package-dll, watch:ts:runapplication
watch:client-prodSimilaire à watch:client:run mais avec WebPack en mode production sans lancer prepare-package-dllclean:static, watch:tsapplication
watch-prodCompile et écoute les modifications pour redémarrer nodejs et relancer WebPack si besoin.mode : productiondependencies:install, compile, watch:client-prod, watch:serveur-prodapplication
watch-prodCompile et écoute les modifications pour redémarrer nodejs et relancer WebPack si besoin.mode : productiondependencies:install, compile, watch:serveur-prodapplication-server
wAlias de "watch"watch*
wrAlias de "watch:run"watch:run*
weAlias de "watch:exe"watch:exe*
wpAlias de "watch-prod"watch-prodapplication, application-server

Le diagramme suivant explique les enchaînements de la tâche watch:exe

Diagramme de séquence de la tâche watch

Les tâches de qualimétrie

hornetbuilder fourni les tâches suivantes afin de construire des rapports de qualimétrie :

TâcheRôleDépendances
lintLance le tslint sur les sources ts (qualité de code)
hb lint
hb lint --lintReport json

divers

entête des fichers

TâcheRôleDépendances
file:headerajoute une entête aux fichiers sources

Permet d'ajouter une entête dans les fichiers sources. Par défault les fichiers traités sont :

  • ./builder.js
  • ./index.ts
  • ./index.dts
  • répertoires src et test
    • /*/.ts
    • /*/.tsx
    • /*/.scss
    • /*/.js
    • /*/.jsx

Il est possible de gérer plus de répertoires et d'extensions grace à de la configuration dans le builder.js avec conf.header.otherDirs et conf.header.otherExts qui attendent toutes les deux des tableaux de string.

L'entête ajouter est le contenu de licenceFile et headerFile avec comme variable de templating possible tout le contenu du fichier package.json

licenceFile

Le fichier "file-header-license.txt" si le projet en contient un sinon c'est la licence CECILL-2.1

headerFile

Le fichier "file-header.txt" si le projet en contient un sinon le template est :

/**
 * <%= pkg.name %>
 *
 * @author MEAE - Ministère de l'Europe et des Affaires étrangères
 * @version <%= pkg.version %>
 * @license CECILL-2.1
 */

Le cycle de vie d'un projet

Première utilisation du builder

Lors de la première utilisation du builder et peu importe la commande, le builder va installer les dépendances de construction/test afin que celles-ci soient disponibles dans le fichier builder.js. Cela permet d'ajouter à un projet des tâches de construction dépendantes de modules non fournis par le framework. Il sera ainsi possible d'écrire dans le fichier builder.js :

var maDependanceSpecifique = require("maDependanceSpecifique");

En cours de développement

Dès la première utilisation du builder sur un projet, il est possible d'utiliser la commande :

hb watch

Dans un ide qui compile automatiquement les fichiers typescript, il est recommandé d'utiliser l'option -i

hb watch -i

ou bien :

hb w -i

Les dépendances entre les tâches du builder font que l'arbre des dépendances applicatives va être calculé, que les versions non fixées vont l'être, que l'ensemble des dépendances vont s'installer, que les sources vont se compiler, que le serveur nodejs va démarrer et que les modifications des fichiers seront écoutées.

Il est néanmoins possible de lancer indépendemment les différentes tâches :

hb dependencies:install
hb compile
hb watch

Lancement des tests

MochaJs

hb test

Exécute les tests et fournit sur la console :

  • la description de chaque test exécuté
  • le nombre de tests OK et KO
  • si tous les tests sont OK : le taux de couverture de code total et fichier par fichier

Les fichiers exécutés doivent se trouver dans le répertoire ./test et se nommer *-spec.js sachant que la phase de compile passe avant.

KarmaJs

hb test:karma
hb test:karma --file ./test/page/test.karma.js

Le test à exécuter est donné par le paramètre -file ou si aucun n'est précisé, il prend la configuration karma et par défaut c'est tests.webpack.js. Ce dernier référence tous les tests à exécuter grace à require, exemple qui tire tous les fichiers *.karma.js dans le répertoire test:

var context = require.context('./test', true, /\.karma\.js$/);
context.keys().forEach(context);

Les rapports sont générés dans le répertoire ./test_report

Le navigateur utilisé par défaut est Firefox. Pour en ajouter ou en utiliser un autre, il faut surcharger la configuration dans le fichier karma.addons.config.js ou dans karma.config.js ou dand karma.addons.config.env.js ou dans karma.config.env.js, exemple :

    config : {
        ....
        ..
        karma: {
            browsers: ["Chrome", "Firefox"],
        }
    }
    

Par défaut, lorsque les tests sont ouverts dans un navigateur, aucune feuille de style hornet n'est chargée. Il est possible de surcharger les templates karma:

    config : {
        ....
        ..
        karma: {
            template: {
                debug: "./test/template/debug.html",
                context: "./test/template/context.html",
                clientContext: "./test/template/client_with_context.html"
            }
        }
    }
    

les templates fournis nécessitent de démarrer un serveur de thèmes.

Templating Html

hb template-html

Lance le templating basé sur EJS et écrit les fichiers dans 'static/html' du projet.

Si l'objet de configuration tempate est un tableau, il lancera autant de templating que d'élément dans le tableau, exemple :

template: [ 
    {
        context: [{error: "404", suffixe: "_404", message: "Oops! Nous ne trouvons pas ce que vous cherchez!"}, {error: "500", suffixe: "_500", message: "Oops! Une erreur est survenue!"}],
        dir: "./template/error",
        dest: "/error"
    }, {
        context: {message: "test template"}
    }
]
    

Dans cet exemple, le templating suivant est lancé :

  1. Sur le répertoire "./template/error" et autant de fois que d'item dans l'attribut context (2). Les fichiers seront suffixés par l'attibut suffixe de chaque contexte (_404, _500) et générés dans le répertoire error (attibut dest) dans static/html du projet.
  2. Sur le répertoire "./template" (valeur par défaut)

Construction des livrables

hb package

Construit les différents livrables et les place dans le répertoire target à la racine du projet.

Publication

hb publish --publish-registry <URL>

Publie le module sur un repository spécifique.

Changement de version

hb versions:set --versionFix=1.2.3

Modifie la version du projet ou des projets si on est sur un type parent en '1.2.3'.

hb versions:set --versionFix=

Modifie la version du projet en suffixant par un timestamp 'YYYYMMDDHHmmss'.

hb versions:set --versionFix=RC

Modifie la version du projet en suffixant la prochaine version 'RC' trouvé sur le repository de publication.

hb versions:set --versionFix=\'-123\'

Modifie la version du projet en suffixant par '-123', il faut echapper les caractères `.

Changement de version d'une dépendance

hb dependency:set --versionFix=1.2.3 --dependencyVersionFix=monpackage

Reprend les principes de versions:set mais sur les dépendances d'un projet.

Changement de version d'une dépendance en snapshot

hb dependency:set-snapshot --dependencyVersionFix=monpackage --module=monpackage

Recherche de dernière version d'une dépendance

hb versions:get --versionSearch=5.0.2 --module=hornet-js-core

Retourne la dernière version commencant par 5.0.2 du module hornet-js-core, exemple : 5.0.2-20180109183247. Si le module n'est pas renseigné, c'est sur le projet lui-même que la recherche est faite, et si versionSearch n'est pas renseigné c'est la dernière version qui est retournée (sans contrainte de préfixe)

hb versions:get --versionSearch=snapshot --module=hornet-js-core

Permet d'avoir la dernière version snapshot d'un module présent dans les dépendances du projet (dependencies, devDependencies, ...).

Recherche de dernière version d'une dépendance

hb dependencies:versions:update --versionSearch=.* --module=hornet-js-.*

Permet de mettre la version des dépendances hornet-js-.* (expression régulière) a la dernière version .*-rc\..* (expression régulière contenant -rc.) en utlisant semver.

hb dependencies:versions:update --versionSearch=.*-rc\..* --module=hornet-js-.*
Tâches SASS

2 tâches sont prévues pour manipuler des fichiers SCSS:

hb process:sass

Cette tâche permet de générer un fichier CSS (par défaut, le fichier sera ./static/css/generated.css comme indiqué dans la conf.)

hb watch:sass

Cette tâche permet de générer un fichier CSS puis de watcher les modifications des fichiers SCSS pour re-générer au besoin le fichier CSS.

Les tâches liées à SASS reposent sur la librairie gulp-sass-image laquelle génère par défaut un fichier ./static/css/_sass-image.scss. Ce dernier contient des méthods utiles afin de manipuler les images (cf. documentation github ). Ce fichier généré repose sur un template mustache qui'il est possible de surcharger.

Approche Composant

Il est également possible de générer des fichiers CSS à partir de fichiers SCSS en important ces derniers directement dans les composants React.

import * as React from "react";
import { Utils } from "hornet-js-utils";

if(!Utils.isServer) {
    require("path/vers/Scss/File.scss");
}


export class MyComponent extends HornetComponent<MyComponentProps, MyComponentState> {

...

}

La déclaration d'un simple require dans un composant .tsx en le protégeant d'un !Utils.isServer permettra à sass-loader de générer le fichier CSS associé

Licence

hornet-js-builder est sous licence cecill 2.1.

Site web : http://www.cecill.info

2.1.0

2 years ago

2.0.7

3 years ago

2.0.6

3 years ago

2.0.5

4 years ago

2.0.4

5 years ago

2.0.3

5 years ago

2.0.2

5 years ago

2.0.1

5 years ago

2.0.0

5 years ago

1.6.4

5 years ago

1.6.3

5 years ago

1.6.2

5 years ago

1.6.1

5 years ago

1.6.0

5 years ago

1.5.4

6 years ago

1.5.3

6 years ago

1.5.2

6 years ago

1.5.1

6 years ago

1.1.1

8 years ago

1.1.0

8 years ago

1.0.0

8 years ago