C'est un peu long mais j'aurai besoin de l'exemple de code pour illustrer ma confusion. Après quoi je suis intéressé par la réponse pour ce qui suit:
require('module')
au lieu de require('../../src/module')
ou require('./module')
?./index.js
Dans spec/specs.js
Sans dupliquer le travail? (Et empêchant src/app.js
De fonctionner car c'est un module d'entrée).J'ai déjà commencé plusieurs projets basés sur un navigateur et j'adore browserify et grognement. Mais chaque projet meurt au même point dans ma courbe de développement/apprentissage. Une fois que j'ajoute des tests au mélange et que je dois gérer deux browserify bundles (app.js
Et spec/specs.js
), Tout le système s'effondre. Je vais t'expliquer:
J'utilise grunt-browserify et définit mon répertoire initial:
.
├── Gruntfile.js
├── index.js (generated via grunt-browserify) [1]
├── lib
│ ├── jquery
│ │ └── jquery.js [2]
│ └── jquery-ui
│ └── jquery-ui.js [3]
├── spec
│ ├── specs.js (generated via grunt-browserify) [4]
│ └── src
│ ├── spec_helper.js (entry)
│ └── module_spec.js (entry)
└── src
├── app.js (entry)
└── module.js
src/app.js
) Et fait un tour de code pour regrouper tous les modules requis.jquery
.jquery-ui
Sans cale (requis après votre var $ = require('jquery')
).spec/src
Comme modules d'entrée.Je vais parcourir ma configuration:
browserify: {
dist: {
files: {
'index.js': ['src/app.js']
}
}
}
// in app.js
var MyModule = require('./module'); // <-- relative path required?!
Heureux
Maintenant, ajoutez jquery:
browserify: {
options: {
shim: {
jquery: {
path: 'lib/jquery/jquery.js',
exports: '$'
}
},
noParse: ['lib/**/*.js'],
alias: [
'lib/jquery-ui/jquery-ui.js:jquery-ui'
]
},
dist: {
files: {
'index.js': ['src/app.js']
}
}
}
// in app.js
var $ = require('jquery');
require('jquery-ui');
var MyModule = require('./module');
Heureux
Ajoutez maintenant des spécifications:
options: {
shim: {
jquery: {
path: 'lib/jquery/jquery.js',
exports: '$'
}
},
noParse: ['lib/**/*.js'],
alias: [
'lib/jquery-ui/jquery-ui.js:jquery-ui'
]
},
dist: {
files: {
'app.js': 'src/app.js'
}
},
spec: {
files: {
'spec/specs.js': ['spec/src/**/*helper.js', 'spec/src/**/*spec.js']
}
}
// in app.js
var $ = require('jquery');
require('jquery-ui');
var MyModule = require('./module');
// in spec/src/module_spec.js
describe("MyModule", function() {
var MyModule = require('../../src/module'); // <-- This looks like butt!!!
});
Triste
Pour résumer: Comment puis-je ...
require('module')
au lieu de require('../../src/module')
ou require('./module')
?./index.js
dans spec/specs.js
sans dupliquer le travail? (Et empêchant src/app.js
De fonctionner car c'est un module d'entrée).Ces réponses dépendent de la configuration du reste de votre projet, mais c'est peut-être un bon point de départ. De plus, vous devrez utiliser la version bêta actuelle de grunt-browserify pour que cela fonctionne réellement (npm install grunt-browserify@2
).
1.
Vous pouvez utiliser aliasMapping pour créer des alias dynamiques pour vos modules. Pour plus de clarté, permet de déplacer tous vos modules vers src/modules/
. La configuration d'aliasMapping pourrait alors ressembler à ceci:
options: {
aliasMappings: {
cwd: 'src',
src: ['modules/**/*.js']
}
}
Supposons que vous ayez un module dans src/modules/magic/stuff.js
, vous pouvez alors l'exiger comme ceci, quel que soit l'emplacement du fichier .js qui effectue l'exigence:
var magicStuff = require('modules/magic/stuff.js');
2.
Pas sûr de celui-ci. La structure de votre projet affiche un spec/index.js
, mais vous mentionnez spec/specs.js
. Sont-ils censés être le même fichier?
Quoi qu'il en soit, de quel travail en double parlez-vous? Car ./index.js
a un fichier d'entrée différent de spec/index.js
. Si vous cherchez un moyen d'inclure ./index.js
dans specs/
, alors vous pouvez peut-être le copier avant d'exécuter les tests au lieu de le construire à partir de zéro.
Réponse simple:
Le plus simple est d'utiliser l'option paths
de browserify. Je l'utilise depuis quelques mois avec beaucoup de succès. J'ai même créé un kit de démarrage qui utilise cette fonctionnalité: https://github.com/stample/gulp-browserify-react-phonegap-starter
var b = browserify('./app', {paths: ['./node_modules','./src/js']});
chemins - tableau require.paths à utiliser si rien n'est trouvé sur la marche récursive normale de node_modules
Si vous avez un fichier dans src/js/modulePath/myModule.js
, Cela ne vous permettra pas d'écrire require("myModule")
partout, mais plutôt require("modulePath/myModule")
, à partir de n'importe lequel de vos autres fichiers source.
Option obsolète?
Cela ne semble pas ainsi!
L'algorithme de résolution du module Browserify reflète le algorithme de résolution dans NodeJS . L'option paths
de Browserify est donc le miroir du comportement de la variable env NODE_PATH
Pour NodeJS. L'auteur de Browserify (sous-pile) affirme dans cette rubrique SO que l'option NODE_PATH
Est déconseillée dans NodeJS et qu'elle est donc également déconseillée dans Browserify et pourrait être supprimée dans les prochaines versions.
Je ne suis pas d'accord avec cette affirmation.
Voir la documentation NODE_PATH . Il n'est pas mentionné que l'option est déconseillée. Cependant, il y a encore une mention intéressante qui va dans le sens de la revendication de substack:
Vous êtes fortement encouragé à placer vos dépendances localement dans les dossiers node_modules. Ils seront chargés plus rapidement et de manière plus fiable.
Et cette question a été publiée en 2012 sur la liste de diffusion.
Oliver Leics: is NODE_PATH deprecated?
Ben Noordhuis (ex core NodeJS contributor): No. Why do you ask?
Et si quelque chose n'est pas supprimé dans l'algorithme de résolution NodeJS, je ne pense pas qu'il sera supprimé de sitôt de Browserify :)
Conclusion
Vous pouvez utiliser l'option paths
ou mettre votre code dans node_modules
Comme la documentation officielle et l'auteur Browserify recommande .
Personnellement, je n'aime pas l'idée de mettre mon propre code dans node_modules
Car je garde tout ce dossier hors de mon contrôle de source. J'utilise l'option paths
depuis quelques mois maintenant et je n'ai eu aucun problème du tout, et ma vitesse de construction est plutôt bonne.
La solution de la sous-pile de mettre un lien symbolique à l'intérieur de node_modules
Pourrait être pratique mais malheureusement, nous avons des développeurs travaillant avec Windows ici ...
Je pense qu'il y a cependant un cas où vous ne voulez pas utiliser l'option paths
: lorsque vous développez une bibliothèque publiée sur un Référentiel NPM qui sera requis par d'autres applications. Vous ne voulez vraiment pas que ces clients de bibliothèque aient à configurer une configuration de construction spéciale simplement parce que vous vouliez éviter l'enfer de chemin relatif dans votre bibliothèque.
Une autre option possible consiste à utiliser remapify
Toutes les réponses ici sur les alias et opts.paths
/$NODE_PATH
Ne sont pas bonnes car cette approche est une partie obsolète du système de modules dans node et browserify, elle pourrait donc cesser de fonctionner à tout moment.
Vous devez apprendre comment fonctionne l'algorithme node_modules afin de pouvoir organiser efficacement votre code de manière à bien jouer avec les répertoires imbriqués node_modules
.
Il y a une section dans le manuel browserify qui couvre en évitant ../../../../../../.. les problèmes de chemin relatif. Il peut être résumé comme suit:
node_modules/
Ou node_modules/app
Afin que vous puissiez require('yourmodule')
ou require('app/yourmodule')
selon ce que vous préférez.N'utilisez pas opts.path
/$NODE_PATH
. Cela rend votre projet:
Je pense que la meilleure façon de procéder est, comme le note Sébastien Lorber, de définir le chemin dans votre appel de browserify à travers une pipe.
Mais avec la dernière version de browserify, (à partir de ce moment, c'est [email protected]
) la variable path stocke les chemins niquement que Browserify utilisera pour son processus. Donc, la définition de la variable des chemins exclura, disons ... vos dossiers globaux pour le nœud, pour autant que je sache. En conséquence, vous aurez besoin d'une tâche Gulp qui ressemble un peu à ceci:
gulp.task('reactBuild', function() {
return gulp.src(newThemeJSX)
.pipe(browserify({
debug: true,
extensions: ['.jsx', '.js', '.json'],
transform: [reactify],
paths: ['../base_folder/node_modules', '/usr/lib/node_modules']
}))
.pipe(gulp.dest(newThemeBuilt))
.on('error', function(error) {
console.log(error);
});
});