Решение требует пути с помощью веб-пакета


164

Я все еще не понимаю, как разрешить пути модулей с помощью веб-пакета. Теперь я пишу:

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

но я хотел бы написать

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

Я думал, что resol.alias может помочь, так как я вижу похожий пример, использующий в { xyz: "/some/dir" }качестве псевдонима, тогда я могу require("xyz/file.js").

Но если я установлю свой псевдоним { mydir: '/absolute/path/mydir' }, require('mydir/myfile.js') не будет работать.

Я чувствую себя глупо, потому что много раз читал документ и чувствую, что что-то упустил. Как правильно избегать записи всех относительных требований с помощью ../../etc?


resolve.aliasработает именно так, как вы предложили. Интересно, не получилось ли это из-за чего-то еще в вашей resolveконфигурации. Я пользуюсь alias{ mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )и require( 'mydir/myfile.js' )работает просто отлично.
августа

Ответы:


142

Webpack> 2.0

Смотри ответ wtk .

Webpack 1.0

Более простой способ сделать это - использовать resol.root.

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

resolve.root

Каталог (абсолютный путь), содержащий ваши модули. Также может быть массив каталогов. Этот параметр следует использовать для добавления отдельных каталогов в путь поиска.

В твоем случае:

Конфигурация веб-пакета

var path = require('path');

// ...

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

модуль потребления

require('myfile')

или

require('myfile.js')

см. также: http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories


1
Спасибо, я пытался root, modulesDirectoriesи смесь обоих, но это не сработало. Кажется, что субмодули (например require("mydir/file")) не принимаются.
gpbl

Они должны быть - мы можем увидеть ваш конфиг веб-пакета?
Джефф Лин

1
Если я правильно понимаю, использование этой конфигурации потребует, чтобы имена файлов были уникальными?
Джонни

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'.
Томаш Зато - Восстановить Монику

1
«Webpack 2 удалил все, кроме модулей, в качестве способа разрешения путей. Это означает, что root не будет работать» stackoverflow.com/a/36574982/588759
rofrol

72

Для дальнейшего использования, webpack 2 удалил все, кроме modulesкак для разрешения путей. Это значит root, не будет работать.

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

Пример конфигурации начинается с:

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

4
Спасибо, это действительно полезно. modulesDirectoriesвсе еще используется webpack-dev-server, даже с webpack 2, что делает это очень запутанным.
Эван

63

resolve.alias должно работать точно так, как вы описали, поэтому я привожу это в качестве ответа, чтобы смягчить любую путаницу, которая может возникнуть в результате предположения в исходном вопросе, что оно не работает.

Конфигурация разрешения, подобная приведенной ниже, даст вам желаемые результаты:

// 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' )будет работать как положено. Если это не так, должна быть другая проблема.

Если у вас есть несколько модулей, которые вы хотите добавить в путь поиска, это resolve.rootимеет смысл, но если вы просто хотите иметь возможность ссылаться на компоненты в коде приложения без относительных путей, это aliasкажется наиболее прямым и явным.

Важным преимуществом aliasявляется то, что он дает вам возможность использовать пространство имен, requireчто может внести ясность в ваш код; точно так же, как легко увидеть из других requires, на какой модуль ссылаются, он aliasпозволяет вам писать описательные requires, которые делают очевидным, что вам нужны внутренние модули, например require( 'my-project/component' ). resolve.rootпросто помещает вас в нужный каталог, не давая вам возможности продолжить пространство имен.


46
Мне нравится псевдоним тильды:alias: {'~': path.resolve(__dirname)},
Даниэль Buckmaster

какие-либо советы, как настроить это решение для поддержки импорта подкаталогов без расширений файлов? @sethro
Дима Фельдман

@DimaFeldman, вы имеете в виду отсутствие расширений в аргументе require ( require('mydir/myfile'))? Это на самом деле должно работать. Вы можете иметь несколько записей в alias; Я использую это для импорта из моего srcкаталога для модулей JavaScript, а другой - для импорта из моего stylesкаталога для CSS. Дайте мне знать, если я полностью не понял ваш вопрос.
Sethro

@ sethro вы правы, позвольте мне перефразировать мой вопрос - я имел в виду следующее: у меня есть каталог, скажем, Component1, и внутри этого каталога у меня есть файл с именем Component1.js. перед использованием псевдонима я мог импортировать файл, просто вызвав его import './path/to/Component1';- просто без внутреннего имени файла и расширения в пути. Веб-пакет каким-то образом удалось обнаружить, что Внутренний файл имеет имя каталога, и просто импортировал его. Теперь, что я хочу сделать, это импортировать это так: import 'shared\Component1';когда «общий» это псевдоним. но это не работает без указания внутреннего имени файла. Спасибо!
Дима Фельдман

1
@DimaFeldman Извините, я не знаком с поведением, которое вы описываете; так что вам придется простить меня, если я просто не знаю какой-то известной функции (я не могу найти документацию для нее). Интересно, есть ли в вашей конфигурации какой-либо загрузчик, который предоставляет возможность импортировать модуль, указав только его местоположение (но не имя файла)? Извините, я не помогу ... Может быть, лучше задать новый вопрос с вашим файлом конфигурации.
Sethro

13

В случае, если кто-то столкнется с этой проблемой, я смог заставить ее работать так:

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

где моя структура каталогов:

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

Тогда из любого места в srcкаталоге я могу позвонить:

import MyComponent from 'components/MyComponent';

2
Не очень хорошо разрешать node_modules, используя path.resolve. Это может вызвать проблемы с зависимостями. Используйте строку 'node_modules'вместо. [ path.resolve(__dirname, 'src'), 'node_modules' ],
spencer.sm

@ spencer.sm, что делать, если я хочу разрешить только модули из текущего проекта? У меня есть несколько проектов, которые импортируют друг от друга. Если projectA импортирует fileA из projectB, а fileA импортирует lodash, я хочу lodashполучить разрешение ТОЛЬКО из projectA/node_modules. Это то, что resolve.modules: [path.resolve(__dirname, 'node_modules')]полезно. Однако я сталкиваюсь с проблемами с зависимостями, как вы сказали. Есть ли способ сказать webpack, чтобы он также находил подзависимости в дополнение к ограничению разрешения node_modules projectA/node_modules?
Эрик Гуан,

@ spencer.sm спасибо тебе! после долгой борьбы, наконец, ваше решение решило мои проблемы с зависимостями: D
Саад Абдулла

5

Моя самая большая головная боль работала без пути в пространстве имен. Что-то вроде этого:

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

До того, как я установил свою среду для этого:

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

Я нашел гораздо более удобным избегать неявного srcпути, который скрывает важную контекстную информацию.

Моя цель - потребовать вот так:

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

Как видите, весь код моего приложения находится в пространстве имен обязательного пути. Это ясно дает понять, какие вызовы требуют библиотеки, кода приложения или тестового файла.

Для этого я должен убедиться, что мои пути разрешения node_modulesи текущая папка приложения, если вы не поместите свое приложение в папку с исходным кодом, какsrc/my_app

Это мой по умолчанию с веб-пак

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

Было бы еще лучше, если вы установите переменную окружения NODE_PATHв файл текущего проекта. Это более универсальное решение, и оно поможет, если вы захотите использовать другие инструменты без веб-пакета: тестирование, линтинг ...


3

Я решил это с Webpack 2 следующим образом:

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

Вы можете добавить больше каталогов в массив ...


Будьте осторожны, абсолютные и относительные пути не обрабатываются одинаково! Может влиять на время сборки webpack.js.org/configuration/resolve/#resolve-modules
TeChn4K

1
Это будет работать в обоих случаях, но сборка (может) займет больше времени с относительными путями.
TeChn4K

3

Решил это с помощью Webpack 2:

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


1

Эта ветка старая, но поскольку никто не писал о require.context, я собираюсь упомянуть об этом:

Вы можете использовать require.context, чтобы настроить просмотр папки следующим образом:

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

Я не понял, почему кто-то предложил включить родительский каталог myDir в modulesDirectories в веб-пакете, что должно легко сработать:

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

0

Просто используйте babel-plugin-module-resolver :

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

Затем создайте .babelrcфайл под root, если у вас его еще нет:

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

И все под root будет восприниматься как абсолютный импорт:

import { Layout } from 'components'

Для поддержки VSCode / Eslint, смотрите здесь .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.