Étant donné que le répertoire lib/
d'un projet ne doit pas être archivé dans Git car les fichiers qu'il contient sont des fichiers dérivés (issus du processus de construction). Lors de l'installation d'un package à partir du github du projet (pendant le développement, par exemple), le répertoire lib/
n'existera pas. Par conséquent, le champ main
du package package.json
pointe vers (par exemple) lib/index.js
, il ne peut pas être compilé s'il est importé, car ces fichiers n'existent pas. le référentiel et donc dans le package installé dans node_modules
. Cela signifie que le paquet doit être construit (comme avant la version), mais cette fois localement pour que le répertoire lib
(ou tout autre fichier généré pendant le processus de construction) soit ajouté au répertoire du module.
En supposant qu'il y ait un script build
dans le champ scripts
du fichier package.json
, le paquet peut-il être configuré pour l'exécuter automatiquement dans le cas où il est installé à partir de github uniquement? Si ce n’est pas le cas, quelle est la meilleure approche pour s’assurer qu’il est construit une fois installé à partir de github?
Il existe désormais des hooks de cycle de vie prepublish
, prepublishOnly
et prepare
, mais aucun ne fournit de réponse à ce problème car ils ne permettent en aucun cas de différencier la source de l'installation. En bref, oui, ils vous permettent de construire sur l'installation, mais ils ne vous permettent pas de construire uniquement à partir de github. Il n'y a pas seulement aucune raison de forcer une construction lorsque les gens installent à partir de npm, mais plus important encore, les dépendances de développement ne seront pas installées (par exemple, babel
qui est essentiel à la construction).
Je suis au courant d'une stratégie pour faire face à ce problème:
lib/
de .gitignore
et archivez-le.lib/
dir à .gitignore
et supprimez dir de git.Mais c'est loin d'être idéal. Je suppose que cela pourrait être automatisé avec un githook cependant. Ainsi, tous les Push pour maîtriser le projet sont également générés et transmis à une branche distincte.
Il y a un numéro fermé sur le Github de NPM sans solution - il y a beaucoup de gens qui veulent une solution. De ce problème, il est clair que l'utilisation de prepare
n'est pas la solution.
Mon cas d'utilisation est que je développe un module qui est utilisé dans un certain nombre d'autres projets. Je souhaite utiliser la dernière version du module sans avoir à envoyer une publication au NPM chaque fois que je mets à jour le code - je préférerais utiliser moins de versions lorsque je serai prêt, mais je devrai toujours utiliser la dernière version de la lib est sur Github.
Remarque: j'ai également sollicité l'assistance de NPM pour résoudre ce problème et je vais ajouter leur réponse si j'en reçois une.
Je n'ai pas bien compris la question. Vous trouverez ci-dessous des choses que j'ai écrites mais qui sont un peu hors sujet. Pour l'instant, si vous souhaitez exécuter build.js uniquement lors de l'installation à partir du référentiel:
Fichiers en repo:
.gitignore
.npmignore
ThisIsNpmPackage
build.js
package.json
Le .gitginore
:
ThisIsNpmPackage
Le .npmignore
:
!ThisIsNpmPackage
Dans le package.json:
"scripts": {
"install": "( [ ! -f ./ThisIsNpmPackage ] && [ ! -f ./AlreadyInstalled ] && echo \"\" > ./AlreadyInstalled && npm install . && node ./build.js ) || echo \"SKIP: NON GIT SOURCE\""
}
L'idée est de rendre le fichier ThisIsNpmPackage
disponible sur le référentiel, mais pas dans le package npm.
Install hook C'est juste un morceau de script bashy pour vérifier si ThisIsNpmPackage
existe. Si oui, alors on exécute npm install .
_ (cela nous assurera que devDependencies
. fichier AlreadyInstalled
est généré pour éviter les boucles infinies (npm install invoquera de manière récursive le crochet d’installation)
Quand je publie, je fais git Push
et npm publish
Notez que la publication par npm peut être automatisée via des outils de CI - githooks
Ce petit hack avec le fichier ThisIsNpmPackage
rend la détection de source disponible.
Résultats de l'appel de npm install dumb-package
:
"SKIP: SOURCE NON GIT"
Et en exécutant npm install https://github.com/styczynski/dumb-package
Les fichiers seront construits
Les principaux problèmes auxquels nous sommes confrontés sont les suivants:
Devoir faire npm publish ...
à chaque fois
Parfois, il est trop pénible de corriger un petit bogue, puis de cliquer sur Push pour le dépôt et oublier de publier sur npm. Lorsque je travaillais avec un projet basé sur microservices comprenant environ 5 sous-projets autonomes divisés en modules, le problème qui se posait était de trouver un problème, de le réparer et d’oublier de publier dans tous les endroits où je devais être vraiment ennuyeux.
Vous ne voulez pas insérer lib
dans le dépôt, car il provient de sources
Rebaser et fusionner est encore plus ennuyant.
Pas de dégâts avec .gitgnore
Zut, je connais ce problème quand vous avez des fichiers gênants que vous devez inclure dans le repo mais ne jamais les modifier, ou parfois les supprimer? C'est juste malade.
Comme @Roy Tinker l'a mentionné, un package peut exécuter une commande lorsqu'il est installé.
Cela peut être réalisé avec des hooks npm.
"install": "npm run build"
Et nous exécutons le:
npm install https://github.com/<user>/<package>
Modifier:
OP question de commentaires:
Mais cela lancera une installation pour tous ceux qui téléchargeront le module à partir de npm, n'est-ce pas? Cela pose énormément de problèmes étant donné que les dépendances dev ne seront pas installées pour les personnes téléchargeant le module à partir de npm. Les bibliothèques utilisées pour créer l'application - babel, etc. ne seront pas installées.
Remarque: Mais si vous souhaitez une version spécifique du package (production/dev) avec ou sans dépendances dev vous pouvez l’installer via:
npm install --only=dev
L'argument --only = {prod [uction] | dev [elopment]} ne provoque l'installation que de devDependencies ou que de non-devDependencies quel que soit le NODE_ENV.
Une meilleure solution, à mon avis, consiste à utiliser:
npm install <git remote url>
Et puis à l'intérieur de package.json, spécifiez:
"scripts": {
"prepare": "npm run build"
}
Si le paquet en cours d'installation contient un script de préparation, ses dépendances et devDependencies seront installés et le script de préparation sera exécuté avant que le paquet ne soit empaqueté et installé.
Exemple:
npm install git+https://[email protected]/npm/npm.git
Lisez les documents npm à cet endroit: npm install
C'est un peu une mauvaise pratique, mais bon à savoir.
Parfois (comme dans le cas de Electron framework vous devez installer d'autres packages externes ou ressources/modules en fonction de diverses conditions).
Dans ces cas, l'idée de proxy est utilisée:
Dans votre cas , préparer un script sera suffisant, mais je laisse cette option, car elle peut parfois être utile.
L'idée est que vous écrivez un module et écrivez un installez kook pour cela:
"scripts": {
"install": "<do the install>"
}
Dans ce scénario, vous pouvez y placer:
npm install . && npm run build
De toute façon, qui installe toutes les devDependencies (comme nous l’avons déjà préparé,), mais c’est un peu de piratage informatique.
Si vous voulez faire le réel piratage là:
"scripts": {
"install": "curl -L -J -O \"<some_url>\""
}
qui télécharge manuellement des fichiers en utilisant la commande -nix curl
Cela devrait être évité, mais c'est une option dans le cas où le module contient d'énormes fichiers binaires pour chaque plate-forme et que vous ne voulez pas tous les installer.
Comme dans le cas de Electron où vous avez compilé des fichiers binaires (chacun pour la plate-forme séparée)
Donc, vous voulez que les gens fassent install package
ne pas install package-linux
ou package-window
etc.
Vous fournissez donc un script personnalisé install
dans le fichier package.json
{
...
"scripts": {
"install": "node ./install_platform_dep.js"
}
}
Ensuite, lors de l’installation de module
, le install_platform_dep.js
le script sera exécuté. À l'intérieur install_platform_dep.js
vous placez:
// For Windows...
if(process.platform === 'win32') {
// Trigger Windows module installation
exec('npm install fancy-module-windows', (err, stdout, stderr) => {
// Some error handling...
}
} else if ... // Process other OS'es
Et cela de manière purement manuelle installe tout.
Remarque: Une fois encore, cette approche est utilisable avec des modules dépendant de la plate-forme. Si vous l'utilisez, il s'agit probablement d'un problème de conception lié à votre code.
Ce qui me vient à l’esprit, c’est la solution que j’ai vraiment utilisée pendant longtemps (construction automatique avec services CI).
Le but principal des services de CI est de tester/construire/publier votre code lorsque vous appuyez sur la branche ou effectuez d'autres actions avec le référentiel.
L'idée est que vous fournissiez un fichier de paramètres (comme travis.yml ou . Gitlab-ci.yml) et les outils s'occupent du reste.
Si vous vraiment ne voulez pas inclure la bibliothèque dans le projet, faites simplement confiance à CI pour tout faire:
Maintenant, je travaille sur Gitlab sur mon propre projet en faisant (en tant que passe-temps) une page Web. La configuration Gitlab qui construit le projet se présente comme suit:
image: tetraweb/php
cache:
untracked: true
paths:
- public_html/
- node_modules/
before_script:
- apt-get update
stages:
- build
- test
- deploy
build_product:
stage: build
script:
- npm run test
build_product:
stage: build
script:
- npm run build
deploy_product:
stage: deploy
script:
- npm run deploy
Lorsque je fusionne dans la branche principale, les événements suivants se produisent:
build
stagetest
est lancéetest
phase est ok, alors finalement l'étape deploy
est déclenchéeLe script est la liste des commandes unix à exécuter.
Vous pouvez spécifier n'importe quelle image Docker dans la configuration, utilisez donc toute version Unix de votre choix avec certains outils préinstallés (ou non).
Il existe un package deploy-to-git qui déploie des artefacts dans la branche de référentiel souhaitée.
Ou ici (pour Travis CI) le morceau de config qui publie des artefacts dans le repo:
(Je l'ai utilisé par moi-même)
Ensuite, bien sûr, vous pouvez laisser CI s'exécuter:
npm publish .
Parce que CI exécute des commandes Unix, il peut alors (au moins un groupe de fournisseurs de CI):
Donc ce que je fais:
Je commets, poussez et laissez les outils faire tout ce que je veux.
Entre-temps, j'effectue d'autres modifications et, après une à dix minutes, je reçois le rapport de mise à jour par courrier.
Il y a beaucoup de fournisseur de CI là-bas:
Je joins ici un autre exemple de mon autre projet (. Travis.yml):
language: generic
install:
- npm install
script:
- chmod u+x ./utest.sh
- chmod u+x ./self_test/autodetection_cli/someprogram.sh
- cd self_test && bash ../utest.sh --ttools stime --tno-spinner
Si vous configurez CI pour Push et publiez votre package, vous pouvez toujours être sûr d'utiliser la dernière version de votre code sans vous soucier de eh. Je dois aussi exécuter cette commande maintenant. . problème.
Je vous recommande de choisir l’un des prestataires de services de CI sur le marché.
Les meilleurs vous offrent des centaines de capacités!
Lorsque vous vous habituerez à effectuer automatiquement les phases de publication, de test et de construction, vous verrez à quel point il est utile de profiter de la vie!
Ensuite, pour démarrer un autre projet avec des scripts automatiques, copiez simplement les configurations!
À mon avis , le script de préparation de npm est une option.
Vous pouvez aussi vouloir essayer d’autres.
Chacune des méthodes décrites présente des inconvénients et peut être utilisée en fonction de vos objectifs.
Je veux juste proposer quelques alternatives en espérant que certaines d’entre elles conviendront à votre problème!
En supposant qu'il y ait un script
build
dans le champ des scripts du fichier package.json, le package peut-il être configuré pour l'exécuter automatiquement dans cette situation?
Oui. Il y a 2 choses que vous devez faire:
Assurez-vous que votre système utilise npm
ou yarn
pour installer le paquet à partir de GitHub. Si ce paquet est une dépendance d'un autre paquet, vous pouvez utiliser l'URL GitHub à la place du numéro de version dans package.json
. Sinon, la commande suivante fonctionnera:
npm install https://github.com/YourUser/your-package
Vous pouvez ajouter /tags/v1.0.0
Ou autre chose à la fin de l'URL si vous recherchez une balise ou une branche spécifique.
Ajoutez ce qui suit au scripts
dans le module package.json
De votre module:
"install": "npm run build"
install
est un crochet que le gestionnaire de paquets exécute après l'installation du module. (preinstall
et postinstall
également - voir la documentation).
Documentation: https://docs.npmjs.com/misc/scripts
C'est une bonne question. Dommage qu'il n'y ait pas de solution fiable reconnue, mais ce qui suit semble fonctionner.
Créez un fichier marqueur .buildme
Et validez-le avec git.
Dans package.json
:
"files": ["lib"],
"scripts": {
"build": "echo DO WHAT YOU NEED TO BUILD",
"prepack": "[ ! -f .buildme ] || npm run build",
"preinstall": "[ ! -f .buildme ] || npm run build"
},
Voici les choses à noter.
Le fichier marqueur spécial .buildme
Doit être exclu du paquet npm avec la touche "files"
Ou via .npmignore
.
Le hook prepack
s'exécute lorsque vous publiez (prepublishOnly
pourrait également fonctionner, mais c'est bien qu'avec prepack
, npm pack
Produise une archive correcte).
Lors de l'installation à partir de npm, preinstall
s'exécute, mais ne fait rien car .buildme
Est manquant (grâce à la clause [ ! -f .buildme ]
).
Lors de l'installation à partir de github, .buildme
Existe. Sur npm6, prepack
hook exécute la construction (et produit un paquet sans .buildme
), Et preinstall
ne fait rien. Sur le fil 1.12, preinstall
fait le build.
Si vous installez une version mise à jour à partir de github, preinstall
sera exécuté à nouveau et compilé à nouveau.
NOTE: Lors de l’installation à partir de github, il appartient à la personne qui s’installe d’avoir assez de devDependencies
de votre paquet déjà installé pour que la compilation fonctionne. (Cette solution ne tente pas d'installer automatiquement devDependencies
.)
C'est ça. Il semble fonctionner avec différentes combinaisons de npm 6 et du fil 1.12.
prepare
est la bonne façonSi vous avez un référentiel avec des fichiers source mais qu'une étape de "compilation" est nécessaire pour l'utiliser, prepare
fait exactement ce que vous voulez dans tous les cas (à partir de npm 4).
prepare
: Exécutez les deux AVANT que le paquet ne soit compressé et publié, sur le répertoire localnpm install
sans aucun argument et lors de l'installation de dépendances git.
Vous pouvez même mettre vos dépendances de construction dans devDependencies
et elles seront installées avant que prepare
ne soit exécuté.
Voici n exemple d'un paquet de la mienne qui utilise cette méthode.
.gitignore
Il y a un problème avec cette option qui attire beaucoup de gens. Lors de la préparation d'une dépendance, Npm et Yarn uniquement conservent les fichiers répertoriés dans la section files
de package.json
. .
On pourrait voir que files
par défaut pour tous les fichiers inclus et penser qu'ils sont terminés. Ce qui est facilement oublié, c’est que .npmignore
généralement annule la directive files
et , si .npmignore
n’existe pas, .gitignore
est utilisé à la place.
Donc, si vos fichiers construits sont listés dans .gitignore
Comme une personne sensée, ne les listez pas dans files
, et n’utilisez pas de fichier .npmignore
, prepare
sera semble cassé .
Si vous corrigez files
pour inclure uniquement les fichiers construits ou ajoutez un .npmignore
Vide, vous êtes tous ensemble.