使用 webpack 解析需要路径

Posted

技术标签:

【中文标题】使用 webpack 解析需要路径【英文标题】:Resolving require paths with webpack 【发布时间】:2015-02-14 15:28:29 【问题描述】:

我仍然对如何使用 webpack 解析模块路径感到困惑。现在我写:

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

但我想写

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

我在想resolve.alias 可能会有所帮助,因为我看到一个使用 xyz: "/some/dir" 作为别名的类似示例,然后我可以require("xyz/file.js")

但如果我将别名设置为 mydir: '/absolute/path/mydir' require('mydir/myfile.js') 将不起作用。

我觉得自己很笨,因为我已经多次阅读文档,但我觉得我错过了一些东西。 避免使用../../ 等编写所有相关要求的正确方法是什么?

【问题讨论】:

resolve.alias 完全按照您的建议工作。我想知道它是否因为您的 resolve 配置中的其他原因而失败。我使用alias mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )require( 'mydir/myfile.js' ) 效果很好。 【参考方案1】:

Webpack >2.0

见wtk's answer。

Webpack 1.0

更直接的方法是使用 resolve.root。

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

resolve.root

包含您的模块的目录(绝对路径)。也可能是一个目录数组。此设置应用于将单个目录添加到搜索路径。

在你的情况下:

webpack 配置

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

【讨论】:

谢谢,我尝试了rootmodulesDirectories 以及两者的混合,但没有奏效。似乎不接受子模块(例如require("mydir/file"))。 他们应该是 - 我们可以看到你的 webpack 配置吗? 如果我理解正确的话,使用这个配置需要文件名是唯一的吗? 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'. "webpack 2 删除了除模块之外的所有内容,作为解析路径的一种方式。这意味着 root 将无法工作"***.com/a/36574982/588759【参考方案2】:

为了将来参考,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)

【讨论】:

谢谢,这真的很有帮助。 modulesDirectories 仍然被 webpack-dev-server 使用,即使使用 webpack 2,这使得这很混乱。【参考方案3】:

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 的一个重要优势是它让您有机会为您的requires 命名,这可以使您的代码更加清晰;就像从其他 requires 很容易看到正在引用的模块一样,alias 允许您编写描述性 requires 以明确您需要内部模块,例如require( 'my-project/component' )resolve.root 只是将您放入所需的目录,而没有给您进一步命名它的机会。

【讨论】:

我喜欢给波浪号起别名:alias: '~': path.resolve(__dirname), 任何提示如何调整此解决方案以支持没有文件扩展名的子目录导入? @sethro @DimaFeldman,您的意思是 require 参数中没有扩展名 (require('mydir/myfile'))?那应该确实有效。 alias可以有多个条目;我使用它从我的 src 目录导入 javascript 模块,另一个从我的 styles 目录导入 css。如果我完全误解了你的问题,请告诉我。 @sethro 你是对的,让我重新表述我的问题 - 我的意思是:我有一个目录,比如 Component1,在这个目录中我有一个名为 Component1.js 的文件。在使用别名之前,我可以通过调用import './path/to/Component1'; 来导入文件 - 只需在路径中没有内部文件名和扩展名。 webpack 以某种方式设法检测到内部文件具有目录的名称,然后将其导入。现在我想做的是像这样导入它:import 'shared\Component1'; 当'shared'是别名时。但如果不指定内部文件名,它就不起作用。谢谢! @DimaFeldman 抱歉,我不熟悉您所描述的行为;因此,如果我对某些已知功能一无所知,您将不得不原谅我(我找不到它的文档)。我想知道您的配置中是否有一些加载器,它提供了通过仅指定其位置(而不是其文件名)来导入模块的能力?抱歉,我帮不上忙……最好在包含配置文件的情况下提出一个新问题。【参考方案4】:

万一其他人遇到这个问题,我可以让它像这样工作:

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';

【讨论】:

使用 path.resolve 解析 node_modules 不好。这可能会导致子依赖项出现问题。请改用字符串'node_modules'[ path.resolve(__dirname, 'src'), 'node_modules' ], @spencer.sm 如果我只想从当前项目中解析模块怎么办?我有一些相互导入的项目。如果 projectA 从 projectB 导入 fileA,并且 fileA 导入 lodash,我希望仅从 projectA/node_modules 解析 lodash。这就是resolve.modules: [path.resolve(__dirname, 'node_modules')] 的用途。但是,就像您说的那样,我遇到了子依赖项的问题。除了将 node_modules 解析限制为 projectA/node_modules 之外,有没有办法告诉 webpack 也找到子依赖项? @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')

如您所见,我所有的应用程序代码都位于强制路径命名空间中。这很清楚哪个 require 调用需要一个库、应用程序代码或测试文件。

为此,我确保我的解析路径只是 node_modules 和当前的应用程序文件夹,除非您在源文件夹中命名您的应用程序,例如 src/my_app

这是我在 webpack 中的默认设置

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

如果将环境变量NODE_PATH 设置为当前项目文件会更好。这是一个更通用的解决方案,如果您想在没有 webpack 的情况下使用其他工具,它会有所帮助:测试、linting...

【讨论】:

【参考方案6】:

我已经用 Webpack 2 解决了这个问题:

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

您可以向数组中添加更多目录...

【讨论】:

小心,绝对路径和相对路径的处理不一样!会影响构建时间webpack.js.org/configuration/resolve/#resolve-modules 在这两种情况下都可以使用,但是相对路径构建(可能)需要更长的时间。【参考方案7】:

如果您使用的是 create-react-app,您可以简单地添加一个 .env 文件,其中包含

NODE_PATH=src/

来源:https://medium.com/@ktruong008/absolute-imports-with-create-react-app-4338fbca7e3d

【讨论】:

【参考方案8】:

使用 Webpack 2 解决了这个问题:

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

【讨论】:

【参考方案9】:

这个帖子很老了,但是因为没有人发布过 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')

【讨论】:

【参考方案10】:

只需使用babel-plugin-module-resolver:

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

如果你还没有,那么在根目录下创建一个.babelrc 文件:


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

并且根目录下的所有内容都将被视为绝对导入:

import  Layout  from 'components'

有关 VSCode/Eslint 支持,请参阅here。

【讨论】:

【参考方案11】:

我不明白为什么有人建议将 myDir 的父目录包含在 webpack 的 modulesDirectories 中,这应该很容易做到:

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

【讨论】:

以上是关于使用 webpack 解析需要路径的主要内容,如果未能解决你的问题,请参考以下文章

使用 webpack 时解析 scss 文件中的字体路径

webpack中的eslint导入:无法解析模块的路径

使用 css-loader 解析 Webpack url() 路径

使用 Webpack 解析从 node_modules 到 Dist 文件夹的相对路径

使用 Webpack 2 和 awesome-typescript-loader 的 baseUrl 和路径解析

Webpack - resolve-url-loader 无法正确解析路径