Giải quyết yêu cầu đường dẫn với webpack


164

Tôi vẫn bối rối làm thế nào để giải quyết các đường dẫn mô-đun với webpack. Bây giờ tôi viết:

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

nhưng tôi muốn viết

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

Tôi đã nghĩ rằng giải quyết.alias có thể giúp vì tôi thấy một ví dụ tương tự sử dụng { xyz: "/some/dir" }như bí danh thì tôi có thể require("xyz/file.js").

Nhưng nếu tôi đặt bí danh của mình { mydir: '/absolute/path/mydir' }, require('mydir/myfile.js') sẽ không hoạt động.

Tôi cảm thấy ngớ ngẩn vì tôi đã đọc tài liệu nhiều lần và tôi cảm thấy mình đang thiếu thứ gì đó. Cách đúng đắn để tránh viết tất cả những gì họ hàng yêu cầu với ../../vv?


resolve.aliashoạt động chính xác theo cách bạn đề xuất. Tôi tự hỏi nếu nó thất bại vì một cái gì đó khác trong resolvecấu hình của bạn . Tôi sử dụng alias{ mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )require( 'mydir/myfile.js' )hoạt động tốt.
sethro

Câu trả lời:


142

Gói web> 2.0

Xem câu trả lời của wtk .

Gói web 1.0

Một cách đơn giản hơn để làm điều này sẽ là sử dụng giải quyết.root.

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

giải quyết.root

Thư mục (đường dẫn tuyệt đối) có chứa các mô-đun của bạn. Cũng có thể là một mảng của các thư mục. Cài đặt này nên được sử dụng để thêm các thư mục riêng lẻ vào đường dẫn tìm kiếm.

Trong trường hợp của bạn:

cấu hình webpack

var path = require('path');

// ...

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

mô-đun tiêu thụ

require('myfile')

hoặc là

require('myfile.js')

xem thêm: http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories


1
Cảm ơn, tôi đã thử root, modulesDirectoriesvà kết hợp cả hai, nhưng nó không hoạt động. Có vẻ như các mô hình con (ví dụ require("mydir/file")) không được chấp nhận.
gpbl

Chúng phải là - chúng ta có thể xem cấu hình webpack của bạn không?
Jeff Ling

1
Nếu tôi hiểu chính xác điều này, sử dụng cấu hình này sẽ yêu cầu tên tệp phải là duy nhất?
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 - Tái lập Monica

1
"webpack 2 đã xóa tất cả mọi thứ trừ các mô-đun như một cách để giải quyết các đường dẫn. Điều này có nghĩa là root sẽ không hoạt động" stackoverflow.com/a/36574982/588759
rofrol

72

Để tham khảo trong tương lai, webpack 2 đã xóa mọi thứ nhưng modulesnhư một cách để giải quyết các đường dẫn. Điều này có nghĩa là rootsẽ không hoạt động.

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

Cấu hình ví dụ bắt đầu bằng:

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

4
Cảm ơn, điều này thực sự hữu ích. modulesDirectoriesvẫn được sử dụng bởi webpack-dev-server, ngay cả với webpack 2, điều này làm cho điều này rất khó hiểu.
Evan

63

resolve.alias nên hoạt động chính xác theo cách bạn mô tả, vì vậy tôi cung cấp đây là câu trả lời để giúp giảm thiểu bất kỳ sự nhầm lẫn nào có thể xảy ra do đề xuất trong câu hỏi ban đầu rằng nó không hoạt động.

một cấu hình giải quyết như bên dưới sẽ cho bạn kết quả mong muốn:

// 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' )sẽ làm việc như mong đợi. Nếu không, phải có một số vấn đề khác.

Nếu bạn có nhiều mô-đun mà bạn muốn thêm vào đường dẫn tìm kiếm, resolve.rootcó ý nghĩa, nhưng nếu bạn chỉ muốn có thể tham chiếu các thành phần trong mã ứng dụng của mình mà không có đường dẫn tương đối, aliasdường như là đơn giản và rõ ràng nhất.

Một lợi thế quan trọng của aliasnó là nó mang lại cho bạn cơ hội để không gian tên của bạn requirecó thể thêm sự rõ ràng vào mã của bạn; giống như dễ dàng nhận thấy từ các requiremô-đun khác đang được tham chiếu, aliascho phép bạn viết các mô tả requirelàm cho rõ ràng bạn đang yêu cầu các mô-đun bên trong, ví dụ require( 'my-project/component' ). resolve.rootchỉ đưa bạn vào thư mục mong muốn mà không cho bạn cơ hội để không gian tên tiếp tục.


46
Tôi thích bí danh dấu ngã:alias: {'~': path.resolve(__dirname)},
Daniel Buckmaster

Bất kỳ gợi ý làm thế nào để điều chỉnh giải pháp này để hỗ trợ nhập thư mục con mà không cần mở rộng tập tin? @sethro
Dima Feldman

@DimaFeldman, ý bạn là không có phần mở rộng nào trong đối số yêu cầu ( require('mydir/myfile'))? Điều đó thực sự nên làm việc. Bạn có thể có nhiều mục trong alias; Tôi sử dụng nó để nhập từ srcthư mục của tôi cho các mô-đun JavaScript và một cái khác để nhập từ stylesthư mục của tôi cho css. Hãy cho tôi biết nếu tôi hoàn toàn hiểu sai câu hỏi của bạn.
sethro

@sethro bạn nói đúng, hãy để tôi nói lại câu hỏi của tôi - ý tôi là: Tôi có một thư mục, nói là Thành phần 1, và bên trong thư mục này tôi có một tệp có tên là Element1.js. trước khi sử dụng bí danh, tôi có thể nhập tệp chỉ bằng cách gọi import './path/to/Component1';- đơn giản là không có tên tệp & phần mở rộng bên trong đường dẫn. webpack bằng cách nào đó quản lý để phát hiện ra rằng tập tin bên trong có tên của thư mục và chỉ cần nhập nó. bây giờ điều tôi muốn làm là nhập nó như thế: import 'shared\Component1';khi 'chia sẻ' là bí danh. nhưng nó không hoạt động mà không chỉ định tên tệp bên trong. Cảm ơn!
Dima Feldman

1
@DimaFeldman Xin lỗi, tôi không quen với hành vi bạn đang mô tả; vì vậy bạn sẽ phải tha thứ cho tôi nếu tôi không biết gì về một số tính năng đã biết (tôi không thể tìm thấy tài liệu cho nó). Tôi tự hỏi nếu bạn có một số trình tải trong cấu hình của bạn, nó cung cấp khả năng nhập mô-đun bằng cách chỉ định vị trí của nó (chứ không phải tên tệp của nó)? Xin lỗi, tôi không giúp được gì ... Có thể tốt nhất là hỏi một câu hỏi mới với tệp cấu hình của bạn đi kèm.
sethro

13

Trong trường hợp có ai khác gặp phải vấn đề này, tôi đã có thể khiến nó hoạt động như thế này:

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

cấu trúc thư mục của tôi là:

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

Sau đó, từ bất cứ nơi nào trong srcthư mục tôi có thể gọi:

import MyComponent from 'components/MyComponent';

2
Sẽ không tốt khi giải quyết node_modules bằng path.resolve. Điều này có thể gây ra vấn đề với các phụ thuộc phụ. Sử dụng chuỗi 'node_modules'thay thế. [ path.resolve(__dirname, 'src'), 'node_modules' ],
spencer.sm

@ spencer.sm nếu tôi chỉ muốn các mô-đun được giải quyết từ dự án hiện tại thì sao? Tôi có một vài dự án nhập khẩu lẫn nhau. Nếu projectA nhập tệpA từ projectB và nhập tệpA lodash, tôi muốn lodashđược giải quyết CHỈ từ projectA/node_modules. Đây là những gì resolve.modules: [path.resolve(__dirname, 'node_modules')]hữu ích cho. Tuy nhiên, tôi đang gặp vấn đề với các phụ thuộc như bạn nói. Có cách nào để bảo webpack cũng tìm thấy các phụ thuộc phụ ngoài việc hạn chế độ phân giải của node_modules projectA/node_moduleskhông?
Eric Guan

@ spencer.sm cảm ơn bạn! Sau rất nhiều cuộc đấu tranh, cuối cùng giải pháp của bạn đã giải quyết được vấn đề phụ thuộc của tôi: D
Saad Abdullah

5

Đau đầu nhất của tôi là làm việc mà không có một con đường được đặt tên. Một cái gì đó như thế này:

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

Trước khi tôi sử dụng để thiết lập môi trường của mình để làm điều này:

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

Tôi thấy thuận tiện hơn nhiều để tránh một ẩn src con đường , trong đó ẩn thông tin bối cảnh quan trọng.

Mục tiêu của tôi là yêu cầu như thế này:

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

Như bạn thấy, tất cả mã ứng dụng của tôi nằm trong một không gian tên đường dẫn bắt buộc. Điều này làm cho khá rõ ràng yêu cầu cuộc gọi cần một thư viện, mã ứng dụng hoặc tệp thử nghiệm.

Đối với điều này, tôi đảm bảo rằng các đường dẫn giải quyết của tôi chỉ là node_modulesvà thư mục ứng dụng hiện tại, trừ khi bạn đặt tên cho ứng dụng của mình trong thư mục nguồn nhưsrc/my_app

Đây là mặc định của tôi với webpack

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

Sẽ tốt hơn nữa nếu bạn đặt var môi trường NODE_PATHcho tệp dự án hiện tại của bạn. Đây là một giải pháp phổ quát hơn và nó sẽ hữu ích nếu bạn muốn sử dụng các công cụ khác mà không cần webpack: thử nghiệm, linting ...


3

Tôi đã giải quyết nó với Webpack 2 như thế này:

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

Bạn có thể thêm nhiều thư mục vào mảng ...


Hãy cẩn thận, đường dẫn tuyệt đối và tương đối không được xử lý như nhau! Có thể ảnh hưởng đến thời gian xây dựng webpack.js.org/configuration/resolve/#resolve-modules
TeChn4K

1
Nó sẽ hoạt động trong cả hai trường hợp, nhưng các bản dựng (có thể) mất nhiều thời gian hơn với các đường dẫn tương đối.
TeChn4K

3

Đã giải quyết vấn đề này bằng Webpack 2:

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


1

Chủ đề này đã cũ nhưng vì không có ai đăng về request.context tôi sẽ đề cập đến nó:

Bạn có thể sử dụng allow.context để đặt thư mục xem qua như thế này:

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

Tôi không hiểu tại sao bất cứ ai đề nghị đưa thư mục mẹ của myDir vào mô-đunDirectories trong gói web, điều đó sẽ giúp thực hiện thủ thuật một cách dễ dàng:

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

0

Đơn giản chỉ cần sử dụng babel-plugin-module-decver :

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

Sau đó tạo .babelrctệp dưới gốc nếu bạn chưa có tệp:

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

Và mọi thứ dưới gốc sẽ được coi là nhập tuyệt đối:

import { Layout } from 'components'

Để được hỗ trợ VSCode / Eslint, xem tại đây .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.