Rozwiązywanie wymaga ścieżek za pomocą pakietu internetowego


164

Nadal nie wiem, jak rozwiązać ścieżki modułów za pomocą pakietu webpack. Teraz piszę:

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

ale chciałbym napisać

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

Pomyślałem, że solution.alias może pomóc, ponieważ widzę podobny przykład używający { xyz: "/some/dir" }aliasu, wtedy mogę require("xyz/file.js").

Ale jeśli ustawię alias na { mydir: '/absolute/path/mydir' }, require('mydir/myfile.js') nie zadziała.

Czuję się głupio, ponieważ czytałem dokumentację wiele razy i czuję, że czegoś mi brakuje. Jaki jest właściwy sposób uniknięcia zapisywania wszystkich potrzebnych krewnych za pomocą ../../itp.?


resolve.aliasdziała dokładnie tak, jak sugerowałeś. Zastanawiam się, czy to zawodziło z powodu czegoś innego w twojej resolvekonfiguracji. Używam alias{ mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )i require( 'mydir/myfile.js' )działa dobrze.
sethro

Odpowiedzi:


142

Pakiet WebPack> 2.0.0

Zobacz odpowiedź wtk .

Webpack 1.0

Prostszym sposobem na zrobienie tego byłoby użycie metody resell.root.

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

olve.root

Katalog (ścieżka bezwzględna) zawierający moduły. Może to być również tablica katalogów. To ustawienie powinno być używane do dodawania poszczególnych katalogów do ścieżki wyszukiwania.

W Twoim przypadku:

konfiguracja pakietu webpack

var path = require('path');

// ...

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

zużywający moduł

require('myfile')

lub

require('myfile.js')

zobacz także: http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories


1
Dzięki, próbowałem root, modulesDirectoriesi to mieszanka obu, ale to nie działa. Wygląda na to, że podmoduły (np. require("mydir/file")) Nie są akceptowane.
gpbl

Powinny być - czy możemy zobaczyć konfigurację twojego webpacka?
Jeff Ling,

1
Jeśli dobrze to rozumiem, użycie tej konfiguracji wymagałoby, aby nazwy plików były unikalne?
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 - Przywróć Monikę

1
„Webpack 2 usunął wszystko oprócz modułów jako sposób na rozwiązanie ścieżek. Oznacza to, że root nie będzie działał” stackoverflow.com/a/36574982/588759
rofrol

72

Na przyszłość, webpack 2 usunął wszystko, ale modulesjako sposób na rozwiązanie ścieżek. Oznacza to, rootże nie zadziała.

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

Przykładowa konfiguracja zaczyna się od:

{
  modules: [path.resolve(__dirname, "app"), "node_modules"]
  // (was split into `root`, `modulesDirectories` and `fallback` in the old options)

4
Dzięki, to jest naprawdę pomocne. modulesDirectoriesjest nadal używany przez webpack-dev-server, nawet z pakietem webpack 2, co sprawia, że ​​jest to bardzo zagmatwane.
Evan

63

resolve.alias powinien działać dokładnie tak, jak opisałeś, więc podaję to jako odpowiedź, aby pomóc złagodzić wszelkie nieporozumienia, które mogą wynikać z sugestii w pierwotnym pytaniu, że nie działa.

konfiguracja rozwiązywania, taka jak ta poniżej, da pożądane wyniki:

// 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' )będzie działać zgodnie z oczekiwaniami. Jeśli tak się nie stanie, musi być inny problem.

Jeśli masz wiele modułów, które chcesz dodać do ścieżki wyszukiwania, resolve.rootma to sens, ale jeśli chcesz mieć możliwość odwoływania się do komponentów w kodzie aplikacji bez ścieżek względnych, aliaswydaje się , że jest to najbardziej proste i wyraźne.

Ważną zaletą programu aliasjest to, że daje on możliwość tworzenia przestrzeni nazw, requireco może zwiększyć przejrzystość kodu; tak jak z innych stron łatwo jest zobaczyć, do requirejakiego modułu się odwołujemy, aliaspozwala na pisanie opisowych, requirektóre jasno wskazują, że potrzebujesz modułów wewnętrznych, np require( 'my-project/component' ). resolve.rootpo prostu umieszcza cię w wybranym katalogu bez możliwości dalszego umieszczania go w przestrzeni nazw.


46
Lubię alias tyldy:alias: {'~': path.resolve(__dirname)},
Daniel Buckmaster

jakieś wskazówki, jak dostosować to rozwiązanie do obsługi importu podkatalogów bez rozszerzeń plików? @sethro
Dima Feldman

@DimaFeldman, masz na myśli brak rozszerzeń w wymaganym argumencie ( require('mydir/myfile'))? To powinno faktycznie zadziałać. Możesz mieć wiele wpisów w alias; Używam tego do importu z mojego srckatalogu dla modułów JavaScript i innego do importu z mojego styleskatalogu dla css. Daj mi znać, jeśli całkowicie źle zrozumiałem Twoje pytanie.
sethro

@sethro masz rację, pozwól mi przeformułować moje pytanie - chodziło mi o to, że mam katalog, powiedzmy Component1, a wewnątrz tego katalogu mam plik o nazwie Component1.js. przed użyciem aliasu mogłem zaimportować plik po prostu wywołując import './path/to/Component1';- po prostu bez wewnętrznej nazwy pliku i rozszerzenia w ścieżce. webpack w jakiś sposób zdołał wykryć, że plik wewnętrzny ma nazwę katalogu i właśnie go zaimportował. teraz chcę to zaimportować w ten sposób: import 'shared\Component1';kiedy „shared” jest aliasem. ale nie działa bez określenia wewnętrznej nazwy pliku. Dzięki!
Dima Feldman

1
@DimaFeldman Przepraszamy, nie znam zachowania, które opisujesz; więc będziesz musiał mi wybaczyć, jeśli po prostu nie znam jakiejś znanej funkcji (nie mogę znaleźć jej dokumentacji). Zastanawiam się, czy masz w swojej konfiguracji program ładujący, który zapewnia możliwość zaimportowania modułu tylko podając jego lokalizację (ale nie nazwę pliku)? Przepraszam, nie pomogę ... Najlepiej będzie zadać nowe pytanie z dołączonym plikiem konfiguracyjnym.
sethro

13

Na wypadek, gdyby ktoś inny napotkał ten problem, udało mi się to uruchomić w następujący sposób:

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

gdzie moja struktura katalogów to:

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

Następnie z dowolnego miejsca w srckatalogu mogę zadzwonić:

import MyComponent from 'components/MyComponent';

2
Nie jest dobrze rozwiązywać node_modules za pomocą path.resolve. Może to powodować problemy z zależnościami podrzędnymi. 'node_modules'Zamiast tego użyj ciągu . [ path.resolve(__dirname, 'src'), 'node_modules' ],
spencer.sm

@ spencer.sm co jeśli chcę, aby tylko moduły z bieżącego projektu zostały rozwiązane? Mam kilka projektów, które importują się od siebie. Jeśli projekt A importuje plikA z projektuB, a plikA importuje lodash, chcę lodashrozwiązać TYLKO z projectA/node_modules. Do tego resolve.modules: [path.resolve(__dirname, 'node_modules')]się przydaje. Jednak mam problemy z pod-zależnościami, jak powiedziałeś. Czy istnieje sposób, aby nakazać pakietowi Webpack, aby znalazł również zależności podrzędne, oprócz ograniczenia rozdzielczości node_modules do projectA/node_modules?
Eric Guan

@ spencer.sm dzięki! po wielu zmaganiach w końcu twoje rozwiązanie rozwiązało moje problemy z sub-zależnością: D
Saad Abdullah

5

Moim największym bólem głowy była praca bez ścieżki z przestrzenią nazw. Coś takiego:

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

Zanim ustawiłem moje środowisko, aby to zrobić:

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

O wiele wygodniej jest unikać ukrytej srcścieżki, która ukrywa ważne informacje kontekstowe.

Moim celem jest takie wymaganie:

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

Jak widać, cały mój kod aplikacji znajduje się w obowiązkowej przestrzeni nazw ścieżki. To wyjaśnia, które wywołanie wymaga biblioteki, kodu aplikacji lub pliku testowego.

W tym celu upewniam się, że moje ścieżki rozpoznawania są tylko node_modulesi bieżącym folderem aplikacji, chyba że przestrzeń nazw aplikacji zostanie umieszczona w folderze źródłowym, na przykładsrc/my_app

To jest moje domyślne ustawienie w pakiecie webpack

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

Byłoby jeszcze lepiej, gdybyś ustawił zmienną środowiska NODE_PATHna bieżący plik projektu. Jest to rozwiązanie bardziej uniwersalne i pomoże, jeśli będziesz chciał korzystać z innych narzędzi bez webpacka: testowanie, lintowanie ...


3

Rozwiązałem to za pomocą Webpack 2 w następujący sposób:

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

Możesz dodać więcej katalogów do tablicy ...


Uważaj, ścieżki bezwzględne i względne nie są jednakowo przetwarzane! Może wpływać na czas kompilacji webpack.js.org/configuration/resolve/#resolve-modules
TeChn4K

1
Będzie działać w obu przypadkach, ale kompilacje (mogą) zająć więcej czasu ze ścieżkami względnymi.
TeChn4K

3

Rozwiązałem to za pomocą Webpack 2:

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


1

Ten wątek jest stary, ale ponieważ nikt nie pisał o require.context wspomnę o tym:

Możesz użyć require.context, aby ustawić wygląd folderu w następujący sposób:

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

return req('./myfile.js')

0

Nie rozumiem, dlaczego ktokolwiek zasugerował włączenie katalogu nadrzędnego myDir do modulesDirectories w pakiecie internetowym, co powinno łatwo załatwić sprawę:

resolve: {
    modulesDirectories: [
      'parentDir',
      'node_modules',
    ],
    extensions: ['', '.js', '.jsx']
  },

0

Po prostu użyj babel-plugin-module-resolver :

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

Następnie utwórz .babelrcplik w katalogu głównym, jeśli jeszcze go nie masz:

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

I wszystko w katalogu głównym będzie traktowane jako import absolutny:

import { Layout } from 'components'

Informacje na temat obsługi VSCode / Eslint można znaleźć tutaj .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.