Das Auflösen erfordert Pfade mit Webpack

164

Ich bin immer noch verwirrt, wie man Modulpfade mit Webpack auflöst. Jetzt schreibe ich:

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

aber ich würde gerne schreiben

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

Ich dachte, dass resolve.alias helfen könnte, da ich ein ähnliches Beispiel sehe, das { xyz: "/some/dir" }als Alias verwendet wird, als ich kann require("xyz/file.js").

Aber wenn ich meinen Alias ​​auf setze { mydir: '/absolute/path/mydir' }, require('mydir/myfile.js') funktioniert das nicht.

Ich fühle mich dumm, weil ich das Dokument oft gelesen habe und das Gefühl habe, etwas zu vermissen. Was ist der richtige Weg, um zu vermeiden, dass alle relativen Anforderungen mit ../../etc geschrieben werden?

gpbl
quelle
resolve.aliasfunktioniert genau so, wie Sie es vorgeschlagen haben. Ich frage mich, ob es an etwas anderem in Ihrer resolveKonfiguration fehlgeschlagen ist . Ich benutze alias{ mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )und require( 'mydir/myfile.js' )funktioniert gut.
Sethro

Antworten:

142

Webpack> 2.0

Siehe die Antwort von wtk .

Webpack 1.0

Ein einfacherer Weg, dies zu tun, wäre die Verwendung von resolve.root.

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

resolve.root

Das Verzeichnis (absoluter Pfad), das Ihre Module enthält. Kann auch eine Reihe von Verzeichnissen sein. Diese Einstellung sollte verwendet werden, um einzelne Verzeichnisse zum Suchpfad hinzuzufügen.

In deinem Fall:

Webpack-Konfiguration

var path = require('path');

// ...

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

Verbrauchsmodul

require('myfile')

oder

require('myfile.js')

Siehe auch: http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories

AndyCunningham
quelle
1
Danke, ich habe es versucht root, modulesDirectoriesund eine Mischung aus beiden, aber es hat nicht funktioniert. Es scheint, dass Submodule (z. B. require("mydir/file")) nicht akzeptiert werden.
GPBL
Sie sollten sein - können wir Ihre Webpack-Konfiguration sehen?
Jeff Ling
1
Wenn ich das richtig verstehe, würde die Verwendung dieser Konfiguration erfordern, dass die Dateinamen eindeutig sind?
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 - Wiedereinsetzung Monica
1
"Webpack 2 hat alles außer Modulen entfernt, um Pfade aufzulösen. Dies bedeutet, dass root nicht funktioniert." stackoverflow.com/a/36574982/588759
rofrol
72

Zum späteren Nachschlagen hat Webpack 2 alles entfernt modules, außer um Pfade aufzulösen. Dies bedeutet, dass rootes nicht funktioniert.

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

Die Beispielkonfiguration beginnt mit:

{
  modules: [path.resolve(__dirname, "app"), "node_modules"]
  // (was split into `root`, `modulesDirectories` and `fallback` in the old options)
wtk
quelle
4
Danke, das ist wirklich hilfreich. modulesDirectorieswird immer noch von webpack-dev-server verwendet, auch mit webpack 2, was dies sehr verwirrend macht.
Evan
63

resolve.alias sollte genau so funktionieren, wie Sie es beschrieben haben, daher gebe ich dies als Antwort, um Verwirrung zu vermeiden, die sich aus dem Vorschlag in der ursprünglichen Frage ergeben könnte, dass es nicht funktioniert.

Eine Auflösungskonfiguration wie die folgende führt zu den gewünschten Ergebnissen:

// 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' )wird wie erwartet funktionieren. Wenn dies nicht der Fall ist, muss ein anderes Problem vorliegen.

Wenn Sie mehrere Module haben, die Sie dem Suchpfad hinzufügen möchten, resolve.root ist dies sinnvoll. Wenn Sie jedoch nur Komponenten in Ihrem Anwendungscode ohne relative Pfade referenzieren möchten,alias scheint dies am einfachsten und explizitesten zu sein.

Ein wichtiger Vorteil von aliasist, dass Sie die Möglichkeit haben, Ihre requires zu benennen, wodurch Ihr Code klarer wird. Genauso wie es aus anderen leicht zu erkennen requireist, auf welches Modul verwiesen wird, aliaskönnen Sie beschreibende requires schreiben , die deutlich machen, dass Sie interne Module benötigen, z require( 'my-project/component' ). resolve.rootSie werden einfach in das gewünschte Verzeichnis verschoben, ohne dass Sie die Möglichkeit haben, es weiter zu benennen.

Sethro
quelle
46
Ich möchte die Tilde alias:alias: {'~': path.resolve(__dirname)},
Daniel Buckmaster
Gibt es Hinweise, wie Sie diese Lösung anpassen können, um Unterverzeichnisimporte ohne Dateierweiterungen zu unterstützen? @ Sethro
Dima Feldman
@DimaFeldman, meinst du keine Erweiterungen im require-Argument ( require('mydir/myfile'))? Das sollte eigentlich funktionieren. Sie können mehrere Einträge in haben alias; Ich verwende das zum Importieren aus meinem srcVerzeichnis für JavaScript-Module und ein anderes zum Importieren aus meinem stylesVerzeichnis für CSS. Lassen Sie mich wissen, wenn ich Ihre Frage völlig falsch verstanden habe.
Sethro
@sethro Sie haben Recht, lassen Sie mich meine Frage umformulieren - ich meinte: Ich habe ein Verzeichnis, sagen wir Component1, und in diesem Verzeichnis habe ich eine Datei mit dem Namen Component1.js. Bevor ich Alias ​​verwendete, konnte ich die Datei einfach durch Aufrufen importieren import './path/to/Component1';- einfach ohne den inneren Dateinamen und die Erweiterung im Pfad. Webpack hat es irgendwie geschafft zu erkennen, dass die innere Datei den Namen des Verzeichnisses hat, und es einfach importiert. Jetzt möchte ich es so importieren: import 'shared\Component1';Wenn 'shared' der Alias ​​ist. Es funktioniert jedoch nicht ohne Angabe des inneren Dateinamens. Vielen Dank!
Dima Feldman
1
@DimaFeldman Entschuldigung, ich bin mit dem von Ihnen beschriebenen Verhalten nicht vertraut. Sie müssen mir also vergeben, wenn ich eine bekannte Funktion nicht kenne (ich kann keine Dokumentation dafür finden). Ich frage mich, ob Sie einen Loader in Ihrer Konfiguration haben, der die Möglichkeit bietet, ein Modul zu importieren, indem Sie nur seinen Speicherort (aber nicht seinen Dateinamen) angeben. Entschuldigung, ich bin keine Hilfe ... Am besten stellen Sie eine neue Frage mit Ihrer Konfigurationsdatei.
Sethro
13

Falls jemand anderes auf dieses Problem stößt, konnte ich es so zum Laufen bringen:

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

wo meine Verzeichnisstruktur ist:

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

Dann kann srcich von überall im Verzeichnis anrufen:

import MyComponent from 'components/MyComponent';
Alex Klibisz
quelle
2
Es ist nicht gut, node_modules mit path.resolve aufzulösen. Dies kann Probleme mit Unterabhängigkeiten verursachen. Verwenden Sie 'node_modules'stattdessen die Zeichenfolge . [ path.resolve(__dirname, 'src'), 'node_modules' ],
spencer.sm
@ spencer.sm Was ist, wenn ich nur möchte, dass Module aus dem aktuellen Projekt aufgelöst werden? Ich habe ein paar Projekte, die voneinander importieren. Wenn projectA fileA aus projectB importiert und fileA importiert lodash, möchte ich lodashNUR von aufgelöst werden projectA/node_modules. Dafür ist resolve.modules: [path.resolve(__dirname, 'node_modules')]es nützlich. Ich habe jedoch Probleme mit Unterabhängigkeiten, wie Sie sagten. Gibt es eine Möglichkeit, Webpack anzuweisen, neben der Einschränkung der Auflösung von node_modules auch Unterabhängigkeiten zu finden projectA/node_modules?
Eric Guan
@ spencer.sm danke! Nach vielen Kämpfen löste Ihre Lösung endlich meine Probleme
Saad Abdullah
5

Meine größten Kopfschmerzen waren das Arbeiten ohne einen Pfad mit Namensraum. Etwas wie das:

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

Bevor ich meine Umgebung so eingestellt habe:

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

Ich fand es weitaus bequemer, einen impliziten srcPfad zu vermeiden , der wichtige Kontextinformationen verbirgt.

Mein Ziel ist es, Folgendes zu fordern:

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

Wie Sie sehen, befindet sich mein gesamter App-Code in einem obligatorischen Pfad-Namespace. Dies macht deutlich, für welche Aufrufe eine Bibliothek, ein App-Code oder eine Testdatei erforderlich ist.

Dafür stelle ich sicher, dass meine Auflösungspfade nur node_modulesund der aktuelle App-Ordner sind, es sei denn, Sie benennen Ihre App in Ihrem Quellordner wiesrc/my_app

Dies ist meine Standardeinstellung bei Webpack

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

Es wäre sogar noch besser, wenn Sie die Umgebungsvariable NODE_PATHauf Ihre aktuelle Projektdatei einstellen . Dies ist eine universellere Lösung und hilft, wenn Sie andere Tools ohne Webpack verwenden möchten: Testen, Flusen ...

SystematicFrank
quelle
3

Ich habe es mit Webpack 2 wie folgt gelöst:

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

Sie können dem Array weitere Verzeichnisse hinzufügen ...

Damjan Pavlica
quelle
Seien Sie vorsichtig, absolute und relative Pfade werden nicht gleich verarbeitet! Kann die Erstellungszeit beeinflussen webpack.js.org/configuration/resolve/#resolve-modules
TeChn4K
1
In beiden Fällen funktioniert dies, aber Builds (mit relativen Pfaden können länger dauern).
TeChn4K
3

Habe dies mit Webpack 2 gelöst:

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

Dieser Thread ist alt, aber da niemand über require.context gepostet hat, werde ich ihn erwähnen:

Mit require.context können Sie festlegen, dass der Ordner folgendermaßen durchsucht wird:

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
quelle
0

Ich habe nicht verstanden, warum jemand vorgeschlagen hat, das übergeordnete Verzeichnis von myDir in modulesDirectories im Webpack aufzunehmen, was den Trick leicht machen sollte:

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

Verwenden Sie einfach den Babel-Plugin-Modul-Resolver :

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

Erstellen Sie dann eine .babelrcDatei unter root, falls Sie noch keine haben:

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

Und alles unter root wird als absoluter Import behandelt:

import { Layout } from 'components'

Informationen zur VSCode / Eslint-Unterstützung finden Sie hier .

Lucia
quelle