45 votes

Comment gérer l'aliasing des chemins relatifs dans plusieurs paquets grunt-browserify ?

C'est un peu long mais j'ai besoin de l'exemple de code pour illustrer ma confusion. Après quoi, je suis intéressé par la réponse à la question suivante :

  1. Comment puis-je utiliser require('module') au lieu de require('../../src/module') o require('./module') ?
  2. Comment puis-je réutiliser ./index.js sur spec/specs.js sans dupliquer le travail ? (Et en évitant src/app.js de fonctionner car c'est un module d'entrée).

J'ai déjà lancé plusieurs projets basés sur le navigateur et j'adore browserify et grogner. Mais chaque projet meurt au même point dans ma courbe de développement/apprentissage. Une fois que j'ajoute les tests au mélange et que je dois gérer deux browserify faisceaux ( app.js y spec/specs.js ), tout le système s'écroule. Je vais vous expliquer :

Yo uso grunt-browserify et définir 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
  1. Utilise un fichier d'entrée ( src/app.js ) et fait une marche de code pour regrouper tous les requis modules.
  2. Utilise browserify-shim pour alias jquery .
  3. est juste un alias de jquery-ui sans cale (nécessaire après avoir var $ = require('jquery') ).
  4. Utilise tous les fichiers d'aide et de spécification dans le fichier spec/src comme modules d'entrée.

Je vais passer en revue ma configuration :

browserify: {
  dist: {
    files: {
      'index.js': ['src/app.js']
    }
  }
}

// in app.js
var MyModule = require('./module'); // <-- relative path required?!

Joyeux

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');

Joyeux

Maintenant, ajoutez les 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...

  1. Utilisez require('module') au lieu de require('../../src/module') o require('./module') ?
  2. réutiliser ./index.js sur spec/specs.js sans dupliquer le travail ? (Et en évitant src/app.js de fonctionner car c'est un module d'entrée).

30voto

Sebastien Lorber Points 9682

Réponse simple :

Le plus simple est d'utiliser le paths option de browserify. Je l'utilise depuis quelques mois avec beaucoup de succès. J'ai même réalisé 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']});

paths - tableau de chemins require.paths à utiliser si rien n'est trouvé dans le tableau normal. node_modules recursive walk

Si vous avez un fichier dans src/js/modulePath/myModule.js cela ne vous permet pas d'écrire require("myModule") partout, mais plutôt require("modulePath/myModule") à partir de n'importe lequel de vos autres fichiers sources.

Option dépréciée ?

Il n'en est rien !

L'algorithme de résolution des modules de Browserify reflète l'algorithme de résolution des modules de Browserify. algorithme de résolution en NodeJS . Le site paths de Browserify est donc le miroir de l'option NODE_PATH Comportement des variables env pour NodeJS. L'auteur de Browserify (substack) affirme dans ce sujet SO que la variable NODE_PATH est dépréciée dans NodeJS et donc elle est aussi dépréciée dans Browserify et pourrait être supprimée dans les prochaines versions.

Je ne suis pas d'accord avec cette affirmation.

Voir le NODE_PATH documentation. Il n'est pas mentionné que l'option est dépréciée. Cependant, il y a encore une mention intéressante qui va dans le sens de la revendication de substack :

Nous vous encourageons vivement à placer vos dépendances localement dans le répertoire dossiers node_modules. Elles seront chargées plus rapidement et de manière plus fiable.

Et cette question a été publié 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 de NodeJS, je ne pense pas qu'il sera supprimé de sitôt de Browserify :)

Conclusion

Vous pouvez soit utiliser paths ou mettez votre code dans node_modules comme la documentation officielle et L'auteur de Browserify recommande .

Personnellement, je n'aime pas l'idée de mettre mon propre code dans node_modules car je garde simplement ce dossier entier en dehors de mon contrôle de source. J'utilise le paths depuis quelques mois maintenant et je n'ai eu aucun problème, et ma vitesse de construction est plutôt bonne.

La solution de substack qui consiste à mettre un lien symbolique à l'intérieur de node_modules pourrait être pratique mais malheureusement nous avons des développeurs qui travaillent avec Windows ici...

Je pense qu'il y a cependant un cas où vous ne voulez pas utiliser l'option paths option Il s'agit du cas où vous développez une bibliothèque publiée sur un dépôt NPM qui sera requise par d'autres applications. Vous ne voulez vraiment pas que les clients de cette bibliothèque aient à configurer un build spécial juste parce que vous avez voulu éviter l'enfer des chemins relatifs dans votre librairie.

Une autre option possible est d'utiliser remapifier

7voto

substack Points 1496

Toutes les réponses ici sur les alias et opts.paths / $NODE_PATH ne sont pas excellentes car cette approche est une partie dépréciée du système de modules dans node et browserify, et peut donc cesser de fonctionner à tout moment.

Vous devriez apprendre comment fonctionne l'algorithme node_modules afin que vous puissiez organiser efficacement votre code de manière à ce qu'il soit compatible avec les éléments imbriqués. node_modules les répertoires.

Il y a une section dans le manuel de browserify qui couvre en évitant ../../../../../../ problèmes de chemins relatifs. On peut le résumer ainsi :

  • Mettez votre code interne modulaire dans node_modules/ o node_modules/app afin que vous puissiez require('yourmodule') o require('app/yourmodule') selon ce que vous préférez.
  • Vous pouvez utiliser un lien symbolique si vous développez pour des plateformes non-Windows et que c'est ce que vous préférez.

N'utilisez pas opts.path / $NODE_PATH . Il rend votre projet :

  • dépendent implicitement d'une configuration ou d'un paramètre de l'environnement non évident
  • plus difficile à faire fonctionner à la fois dans node et dans le navigateur
  • vulnérable aux changements dans le système de modules puisque les chemins des tableaux sont dépréciés dans node et browserify

4voto

Joni Bekenstein Points 68

Ces réponses dépendent de la façon dont le reste de votre projet est configuré, mais c'est peut-être un bon point de départ. En outre, vous devrez utiliser la version actuelle v2 beta 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é, déplaçons tous vos modules vers src/modules/ . Ensuite, la configuration de l'aliasMapping pourrait être quelque chose comme ceci :

options: {
  aliasMappings: {
    cwd: 'src',
    src: ['modules/**/*.js']
  }
}

Supposons que vous ayez un module dans src/modules/magic/stuff.js alors vous pouvez l'exiger comme ceci, indépendamment de l'endroit où se trouve le fichier .js qui fait l'exigence :

var magicStuff = require('modules/magic/stuff.js');

2.

Je ne suis pas sûr pour celui-ci. La structure de votre projet montre un spec/index.js mais vous mentionnez spec/specs.js . Sont-ils censés être le même fichier ?

De toute façon, de quel travail en double parlez-vous ? Parce que ./index.js a un fichier d'entrée différent de celui de spec/index.js . Si vous cherchez un moyen d'inclure ./index.js sur specs/ alors vous pouvez peut-être le copier avant d'exécuter les tests au lieu de le construire à partir de zéro.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X