Résoudre les chemins requis avec Webpack

164

Je ne sais toujours pas comment résoudre les chemins de module avec webpack. Maintenant j'écris:

myfile = require('../../mydir/myfile.js') 

mais j'aimerais écrire

myfile = require('mydir/myfile.js') 

Je pensais que résoudre.alias peut aider puisque je vois un exemple similaire utilisant { xyz: "/some/dir" }comme alias alors que je peux require("xyz/file.js").

Mais si je règle mon alias sur { mydir: '/absolute/path/mydir' }, require('mydir/myfile.js') cela ne fonctionnera pas.

Je me sens stupide parce que j'ai lu la doc plusieurs fois et j'ai l'impression de manquer quelque chose. Quelle est la bonne façon d'éviter d'écrire tout ce que le parent requiert avec ../../etc?

gpbl
la source
resolve.aliasfonctionne exactement comme vous l'avez suggéré. Je me demande s'il échouait à cause de quelque chose d'autre dans votre resolveconfiguration. J'utilise alias{ mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )et require( 'mydir/myfile.js' )fonctionne très bien.
sethro

Réponses:

142

Webpack> 2.0

Voir la réponse de wtk .

Webpack 1.0

Une manière plus simple de le faire serait d'utiliser resolver.root.

http://webpack.github.io/docs/configuration.html#resolve-root

résoudre.root

Le répertoire (chemin absolu) qui contient vos modules. Peut également être un tableau de répertoires. Ce paramètre doit être utilisé pour ajouter des répertoires individuels au chemin de recherche.

Dans ton cas:

configuration webpack

var path = require('path');

// ...

  resolve: {
    root: path.resolve('./mydir'),
    extensions: ['', '.js']
  }

module consommateur

require('myfile')

ou

require('myfile.js')

voir aussi: http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories

AndyCunningham
la source
1
Merci, j'ai essayé root, modulesDirectorieset un mélange des deux, mais cela n'a pas fonctionné. Il semble que les sous-modules (par exemple require("mydir/file")) ne soient pas acceptés.
gpbl
Ils devraient l'être - pouvons-nous voir votre configuration Webpack?
Jeff Ling
1
Si je comprends bien, l'utilisation de cette configuration nécessiterait que les noms de fichiers soient uniques?
Jonny
1
WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema. - configuration.resolve has an unknown property 'root'.
Tomáš Zato - Réintégrer Monica le
1
"Webpack 2 a supprimé tout sauf les modules pour résoudre les chemins. Cela signifie que root ne fonctionnera pas" stackoverflow.com/a/36574982/588759
rofrol
72

Pour référence future, webpack 2 a tout supprimé mais modulescomme un moyen de résoudre les chemins. Ce moyen rootne pas fonctionner.

https://gist.github.com/sokra/27b24881210b56bbaff7#resolving-options

L'exemple de configuration commence par:

{
  modules: [path.resolve(__dirname, "app"), "node_modules"]
  // (was split into `root`, `modulesDirectories` and `fallback` in the old options)
wtk
la source
4
Merci, c'est vraiment utile. modulesDirectoriesest toujours utilisé par webpack-dev-server, même avec webpack 2, ce qui rend cela très déroutant.
Evan
63

resolve.alias devrait fonctionner exactement comme vous l'avez décrit, donc je fournis ceci comme une réponse pour aider à atténuer toute confusion qui pourrait résulter de la suggestion dans la question originale que cela ne fonctionne pas.

une configuration de résolution comme celle ci-dessous vous donnera les résultats souhaités:

// used to resolve absolute path to project's root directory (where web pack.config.js should be located)
var path = require( 'path' );
...
{
  ...
  resolve: {
    // add alias for application code directory
    alias:{
      mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )
    },
    extensions: [ '', '.js' ]
  }
}

require( 'mydir/myfile.js' )fonctionnera comme prévu. Si ce n'est pas le cas, il doit y avoir un autre problème.

Si vous avez plusieurs modules que vous souhaitez ajouter au chemin de recherche, resolve.rootcela a du sens, mais si vous souhaitez simplement pouvoir référencer des composants dans le code de votre application sans chemins relatifs, cela aliassemble être le plus simple et le plus explicite.

Un avantage important de aliasest qu'il vous donne la possibilité d'espacer vos noms, requirece qui peut ajouter de la clarté à votre code; tout comme il est facile de voir à partir d'autres requires quel module est référencé, aliasvous permet d'écrire des descriptifs requirequi montrent clairement que vous avez besoin de modules internes, par exemple require( 'my-project/component' ). resolve.rootvous place simplement dans le répertoire souhaité sans vous donner la possibilité de l'espace de noms plus loin.

Sethro
la source
46
J'aime alias le tilde:alias: {'~': path.resolve(__dirname)},
Daniel Buckmaster
des astuces pour ajuster cette solution pour prendre en charge les importations de sous-répertoires sans extensions de fichier? @sethro
Dima Feldman
@DimaFeldman, vous voulez dire aucune extension dans l'argument require ( require('mydir/myfile'))? Cela devrait fonctionner. Vous pouvez avoir plusieurs entrées dans alias; J'utilise cela pour importer de mon srcrépertoire pour les modules JavaScript et un autre pour importer de mon stylesrépertoire pour css. Faites-moi savoir si j'ai complètement mal compris votre question.
sethro le
@sethro vous avez raison, laissez-moi reformuler ma question - ce que je voulais dire, c'est: j'ai un répertoire, disons Component1, et à l'intérieur de ce répertoire, j'ai un fichier nommé Component1.js. avant d'utiliser l'alias, je pouvais importer le fichier simplement en appelant import './path/to/Component1';- simplement sans le nom de fichier interne et l'extension dans le chemin. webpack a réussi à détecter que le fichier Inner porte le nom du répertoire et l'a simplement importé. maintenant ce que je veux faire, c'est l'importer comme ça: import 'shared\Component1';quand 'shared' est l'alias. mais cela ne fonctionne pas sans spécifier le nom du fichier interne. Merci!
Dima Feldman
1
@DimaFeldman Désolé, je ne connais pas le comportement que vous décrivez; vous devrez donc me pardonner si je suis simplement ignorant de certaines fonctionnalités connues (je ne trouve pas de documentation pour cela). Je me demande si vous avez un chargeur dans votre configuration qui offre la possibilité d'importer un module en spécifiant uniquement son emplacement (mais pas son nom de fichier)? Désolé, je ne suis pas d'aide ... Peut-être mieux de poser une nouvelle question avec votre fichier de configuration inclus.
sethro
13

Au cas où quelqu'un d'autre rencontrerait ce problème, j'ai pu le faire fonctionner comme ceci:

var path = require('path');
// ...
resolve: {
  root: [path.resolve(__dirname, 'src'), path.resolve(__dirname, 'node_modules')],
  extensions: ['', '.js']
};

où ma structure de répertoires est:

.
├── dist
├── node_modules
├── package.json
├── README.md
├── src
   ├── components
   ├── index.html
   ├── main.js
   └── styles
├── webpack.config.js

Puis de n'importe où dans l' srcannuaire, je peux appeler:

import MyComponent from 'components/MyComponent';
Alex Klibisz
la source
2
Il n'est pas bon de résoudre node_modules à l'aide de path.resolve. Cela peut entraîner des problèmes avec les sous-dépendances. Utilisez 'node_modules'plutôt la chaîne . [ path.resolve(__dirname, 'src'), 'node_modules' ],
spencer.sm
@ spencer.sm Que faire si je veux uniquement que les modules soient résolus à partir du projet actuel? J'ai quelques projets qui importent les uns des autres. Si projectA importe fileA depuis projectB et fileA importe lodash, je veux lodashêtre résolu UNIQUEMENT à partir de projectA/node_modules. C'est ce qui resolve.modules: [path.resolve(__dirname, 'node_modules')]est utile. Cependant, je rencontre des problèmes avec les sous-dépendances comme vous l'avez dit. Existe-t-il un moyen de dire à Webpack de rechercher également des sous-dépendances en plus de restreindre la résolution node_modules à projectA/node_modules?
Eric Guan
@ spencer.sm merci! après beaucoup de lutte, enfin votre solution a résolu mes problèmes de sous-dépendance: D
Saad Abdullah
5

Mon plus gros mal de tête fonctionnait sans un chemin d'espacement de noms. Quelque chose comme ça:

./src/app.js
./src/ui/menu.js
./node_modules/lodash/

Avant, j'avais l'habitude de configurer mon environnement pour faire cela:

require('app.js')
require('ui/menu')
require('lodash')

J'ai trouvé beaucoup plus pratique d'éviter un srcchemin implicite , qui cache des informations contextuelles importantes.

Mon objectif est d'exiger comme ceci:

require('src/app.js')
require('src/ui/menu')
require('test/helpers/auth')
require('lodash')

Comme vous le voyez, tout le code de mon application vit dans un espace de noms de chemin obligatoire. Cela montre clairement quel appel nécessite une bibliothèque, un code d'application ou un fichier de test.

Pour cela, je m'assure que mes chemins de résolution sont justes node_moduleset le dossier d'application actuel, à moins que vous n'espacez votre application dans votre dossier source commesrc/my_app

C'est ma valeur par défaut avec webpack

resolve: {
  extensions: ['', '.jsx', '.js', '.json'],
  root: path.resolve(__dirname),
  modulesDirectories: ['node_modules']
}

Ce serait encore mieux si vous définissez la variable d'environnement NODE_PATHsur votre fichier de projet actuel. C'est une solution plus universelle et cela vous aidera si vous souhaitez utiliser d'autres outils sans webpack: test, peluchage ...

SystématiqueFrank
la source
3

Je l'ai résolu avec Webpack 2 comme ceci:

module.exports = {
  resolve: {
    modules: ["mydir", "node_modules"]    
  }
}

Vous pouvez ajouter plus de répertoires au tableau ...

Damjan Pavlica
la source
Attention, les chemins absolus et relatifs ne sont pas traités de la même manière! Peut affecter le temps de construction webpack.js.org/configuration/resolve/#resolve-modules
TeChn4K
1
Cela fonctionnera dans les deux cas, mais les builds (peuvent) prendre plus de temps avec des chemins relatifs.
TeChn4K
3

J'ai résolu ce problème en utilisant Webpack 2:

   resolve: {
      extensions: ['', '.js'],
        modules: [__dirname , 'node_modules']
    }
Aaqib
la source
1

Ce fil de discussion est ancien mais comme personne n'a posté sur require.context, je vais le mentionner:

Vous pouvez utiliser require.context pour définir le dossier à parcourir comme ceci:

var req = require.context('../../mydir/', true)
// true here is for use subdirectories, you can also specify regex as third param

return req('./myfile.js')
altShiftDev
la source
0

Je n'ai pas compris pourquoi quelqu'un a suggéré d'inclure le répertoire parent de myDir dans les modulesDirectories du webpack, cela devrait faciliter le truc:

resolve: {
    modulesDirectories: [
      'parentDir',
      'node_modules',
    ],
    extensions: ['', '.js', '.jsx']
  },
Daniele Bertella
la source
0

Utilisez simplement babel-plugin-module-resolver :

$ npm i babel-plugin-module-resolver --save-dev

Créez ensuite un .babelrcfichier sous root si vous n'en avez pas déjà:

{
    "plugins": [
        [
            "module-resolver",
            {
                "root": ["./"]
            }
        ]
    ]
}

Et tout ce qui se trouve sous root sera traité comme une importation absolue:

import { Layout } from 'components'

Pour la prise en charge de VSCode / Eslint, cliquez ici .

Lucie
la source