Webpack [url / file-loader]无法解析URL

时间:2016-12-23 19:18:44

标签: javascript reactjs webpack urlloader webpack-style-loader

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

我在工作区目录

中有2个单独的项目
  1. Project-A [使用Gulp捆绑]:稳定&工作
  2. Project-B [使用Webpack捆绑]:新项目
  3. 由于两个项目都使用相同的样式,所以我想将 项目A的SCSS文件[由标准变量,预定义布局,模态,类等组成]重用到项目B中

    enter image description here

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

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

    但是,由于Project-A的index.scss进一步引用了来自相应Relative-Path的背景图像,因此webpack构建引发错误

      

    '在XYZ / Project-B / Source / Stylesheets'中找不到文件/目录。

    确切的错误阻止:

       ./src/assets/stylesheets/index.scss中的错误   模块构建失败:ModuleNotFoundError:找不到模块:错误:无法解析'file'或'diWorkSpace \ Project_B \ src \ assets \ stylesheets

    截图: **enter image description here**

    我无法理解,为什么Webpack无法解决Project-A内部资产的相对路径,仍然在“项目B”内部查看

    以下是模拟问题的Code-Repo网址: 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

3 个答案:

答案 0 :(得分:8)

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

结果是CSS加载器出现了问题,即它无法解析与当前文件相对应的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应始终使用加载器名称的长格式(即-loader后缀)。

还有另一个名为resolve-url的包,Webpack可以将其与resolve-url-loader混淆。

答案 1 :(得分:3)

似乎是 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的

答案 2 :(得分:2)

您需要将publicPath设置为获取文件加载器中相对路径的相对路径。