Webpack [url/file-loader] 未解析 URL 的相对路径

Webpack [url/file-loader] is not resolving the Relative Path of URL

我在 Webpack 中遇到了一个关于相对路径的问题。 让我试着解释一下这个场景:

我在 Workspace 目录 中有 2 个单独的项目:

  1. Project-A [使用 Gulp 捆绑]:稳定且工作
  2. 项目-B [使用 Webpack 捆绑]:新建项目

因为两个项目都使用相同的样式,所以我想重用 [=43= 的 SCSS 文件 [由标准变量、预定义布局、模态、类 等组成] ]项目 A 到项目 B

现在,如果我尝试将项目 A index.scss 导入项目 B index.scss 作为另一个部分 [ 注释掉背景图像 URL 依赖],webpack 能够生成所需的 CSS 输出文件。

// Import Project A SCSS [Common Varibles, Classes, Styling etc] 
@import "../../../../Project_A/assets/stylesheets/index";

但是由于 Project-A 的 index.scss 进一步从各自的相对路径引用背景图像,webpack 构建会抛出错误

'File / dir not found in XYZ/Project-B/Source/Stylesheets'.

确切错误块:

ERROR in ./src/assets/stylesheets/index.scss Module build failed: ModuleNotFoundError: Module not found: Error: Cannot resolve 'file' or 'diWorkSpace\Project_B\src\assets\stylesheets

截图:

我无法理解,为什么 Webpack 无法解析 Project-A 中资产的相对路径并仍在内部查找 'Project B'.

这是模拟问题的代码库 URL: https://github.com/raviroshan/webpack-build-issue/tree/master/WorkSpace

重现步骤。

  1. 下载回购协议。
  2. 浏览 Project_B 文件夹,然后执行 NPM 安装。
  3. 运行'webpack'。它会正确构建为相对图像 URL 代码被注释掉了。
  4. 现在放回注释的代码行:https://github.com/raviroshan/webpack-build-issue/blob/master/WorkSpace/Project_A/assets/stylesheets/index.scss#L27

需要将publicPath设置为相对路径,才能获取file-loader中的相对路径。

它似乎是 css-loader 的错误以及它在 @importurl() 中解析路径的方式。它会尝试解析相对于主 CSS 文件的所有路径——甚至是那些来自导入样式表的路径——在你的例子中是 /Project_B/src/assets/stylesheets/index.scss.

别哭!有解决办法!

也许它并不完美,但它是我迄今为止最好的。

创建一个全局变量 $assetsPath 保存资产路径 相对于当前样式表 。然后将此变量添加到所有 url() 值之前。

在你的 /Project_A/assets/stylesheets/index.scss 你会写:

/*/ Using !default we can override this variable even before the following line: /*/
$assetsPath: '../' !default;

.container {
    /*/ ... /*/
    .content-wrapper {
        /*/ ... /*/
        background-image: url($assetsPath + "images/content-bg.jpg");
    }
}

在你的 /Project_B/src/assets/stylesheets/index.scss 你会写:

/*/ The following variable will override $assetsPath defined in the imported file: /*/
$assetsPath: '../../../../Project_A/assets/';

/*/ Import Project A SCSS [Common Varibles, Classes, Styling etc] /*/
@import "../../../../Project_A/assets/stylesheets/index";

后果

如果您将 Project-A 与 Gulp 捆绑在一起,它将看到 Project-A 的代码为:

        /*/ ... /*/
        background-image: url("../images/content-bg.jpg");

尽管如此,当您将 Project-B 与 Webpack 捆绑在一起时,它会看到 Project-A 的代码为:

        /*/ ... /*/
        background-image: url("../../../../Project_A/assets/images/content-bg.jpg");

因此,你得救了。

我肯定会仔细研究这个问题。如果 url-loader 尊重 @import 语句中的路径并将其相应地应用于引用的资产,那么所有这一切都可以避免。要么我遗漏了什么,要么应该将其视为错误。

希望你今天过得愉快!
~Wiktor

所以,经过这么多的努力,终于得到了一个合适的解决方案

原来是 CSS-loader 的问题,即它无法解析与当前文件相关的 URL。

使用resolve-url-loader解决了这个问题。 https://www.npmjs.com/package/resolve-url-loader

 // Old Loader Config in Webpack-entry
 loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!sass-loader?sourceMap')

 // New [Fixed] Loader Config in Webpack-entry
 loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!resolve-url-loader!sass-loader?sourceMap')

此处已更新 Code-Repo 解决方案:https://github.com/raviroshan/webpack-build-issue

注意 : 不要省略 -loader 您的 Webpack.config.js 应始终使用加载程序名称的 long-form(即 -loader 后缀)。

还有一个名为 resolve-url 的包,Webpack 可能会与 resolve-url-loader 混淆。