首页 文章

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

提问于
浏览
9

我在Webpack中遇到了关于Relative Path的问题 . 让我试着解释一下这个场景:

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

  • Project-A [使用Gulp捆绑]: Stable & Working

  • Project-B [使用Webpack捆绑]: New project

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

enter image description here

现在,如果我尝试将Project-A 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

我无法理解, why Webpack is not able to resolve the Relative path of assets inside Project-A and still looking inside 'Project B' .

以下是模拟问题的Code-Repo URL:https://github.com/raviroshan/webpack-build-issue/tree/master/WorkSpace

Steps to reproduce.

3 回答

  • 8

    所以,经过这么多的斗争,最终得到了一个合适的 SOLUTION .

    结果是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

    Note :不要省略-loader你的Webpack.config.js应该总是使用加载器名称的长格式(即-loader后缀) .

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

  • 3

    它似乎是 css-loader 错误以及它在 @importurl() 中解析路径的方式 . 它尝试解析所有路径 - 甚至是导入样式表中的路径 - 相对于主CSS文件 - 在您的情况下是 /Project_B/src/assets/stylesheets/index.scss .

    别哭!有一个解决方案!

    也许它并不完美,但它是迄今为止我带来的最好的一个 .

    创建一个全局变量 $assetsPath ,其中包含资产的路径 relative to the current stylesheet . 然后将此变量添加到所有 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

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

相关问题