在Webpack中将绝对路径转换为相对于项目根目录的路径

33
我发现我需要经常输入../require()文件。我的目录结构包括这些:

I find that I need to type ../ a lot to require() files. My directory structure includes these:


js/
  components/
    ...
  actions/
    ...
从components文件夹中,我需要执行import foo from '../actions/fooAction'。是否可以将根目录设置为项目的根目录?也就是说,我希望执行import foo from '/actions/fooAction'。我尝试设置Webpack的resolve.root选项,但好像没有起作用。
6个回答

52

resolve.root选项不会修改如何解析文件模块

以“/”为前缀的所需模块是到文件的绝对路径。例如,require('/home/marco/foo.js')将加载/home/marco/foo.js中的文件。

/解析为您文件系统的根目录。

也许您想将您的js文件夹解析为模块目录

webpack.config.js

resolve: {
  root: path.resolve('./js')
}

将以下配置添加到您的配置文件中,将告诉webpack解析任何importrequire相对于您的js文件夹。然后,不再使用

import foo from '../actions/fooAction'

你将能够:

import foo from 'actions/fooAction`

请注意开头缺少/


31
似乎有数百个Stack Overflow问题基本上都在问同样的事情,还有数十个不同的Webpack文档页面,但是它们都没有像你刚才那样清晰地解释这个非常简单的概念。感谢你(并且诅咒Webpack的人让找到这个答案变得如此困难)! - machineghost
它是否可以简单地设置为'./',并使所有内容相对于项目根文件夹? - JoeTidee
2
@JoeTidee - 不,那是相对于当前文件的。 - toobulkeh
现在resolve['root']需要一个数组:https://github.com/webpack/docs/wiki/configuration#resolveroot - Kevin
14
似乎从2020年9月开始,webpack不再支持root选项,现在您需要将一个数组传递给resolve.modules选项——resolve: { modules: [path.resolve(__dirname, 'src'), 'node_modules'] } - Dmitry Sokurenko
@DmitrySokurenko 说句实话,webpack的root选项已被淘汰,取而代之的是roots(复数)选项,可以接受多个根目录rootsmodules的作用不同,它改变了如何解析_绝对_路径。 - zeptonaut

16

我将稍微以不使用resolve.root的方式回答这个问题。@dresyecat所说的一切都是正确的。然而,我刚刚经历了从相对路径到模块路径的移动过程。 这里是解释导入语句中可用的三种不同路径类型的文档。

你要求使用模块路径,我认为这是首选方式。

问题在于,默认情况下,模块路径只适用于通过npm导入的内容,因为resolve上的新的modules变量默认为["node_modules"]。这让您可以非常轻松地从npm导入第三方代码。但是,这意味着使用模块路径导入您的代码需要进行配置更改。顺便说一下,在以前的版本中,modules被称为moduleDirectories这里是有关resolve变量配置的文档。

好的,假设您的目录结构如下:

project/
    webpack.config.json
    js/
        components
        actions

您可以将模块目录设置为:

resolve: {
    extensions: [ '.ts', '.js', '*' ],
    modules: [ path.resolve(__dirname, "js"), "node_modules"]
}

重要提示:

  • 如果你使用npm引入第三方代码,请务必包含“node_modules”,否则你的引入可能会失败
  • 请确保在配置中导入path组件,以便定义path

    var path = require('path');

然后,你可以使用以下方式(不带前导/),使用模块路径形式导入你的组件:

import "actions/fooAction";

在2023年,这是唯一正确的答案。我曾经为一个旧项目使用过Angular(我知道,不得不这么做),还结合使用了Webpack。 - Bart Theeten

4

解析过程基本简单,区分三个变量:

绝对路径: require("/home/me/file")

相对路径: require("../src/file") 或 require("./file")

模块路径: require("module/lib/file")

前两个很明显,第三个值得更仔细地研究:

  1. 确实是指向您的文件系统

  2. 相对于当前文件(如果该文件位于 src/foo/barwebpack/config/subconfig 中,那么就是这样...)

  3. import 相比(处理 1+2 的方式基本相同,但会立即在 node_modules 中查找),路径 'module' 确实意味着没有必要解析路径的项目根目录,例如 webpack 配置中的 output.path... 并且:(关于解析)只有 3 受到 resolve.rootresolve.moduleDirectories 解析的影响,请参见 webpack 文档


1
有用的解释,谢谢!这应该在文档中。还有解决_目录_(请参阅https://webpack.js.org/configuration/resolve/#resolvemainfiles),但那可能是正交的,也可能适用于这三个同样的类别。 - Tyler Rick

4
另一个解决方案是使用resolve.alias像模块一样导入js(我并不是说它是一个模块,只是语法类似)。
resolve: {
  alias: {
    js: path.resolve(__dirname, './js'),
  },
}

你可以这样导入fooAction

import foo from 'js/actions/fooAction';

2

1

在 Webpack 5 中,您需要将以下行添加到webpack.config.js文件中:

resolve: {
   modules: [path.resolve(__dirname, 'src'), 'node_modules']
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接