如何使用 webpack-4 解析 sass 文件中的背景图像 URL?

Posted

技术标签:

【中文标题】如何使用 webpack-4 解析 sass 文件中的背景图像 URL?【英文标题】:How can I resolve background image URL inside sass file using webpack-4? 【发布时间】:2019-12-20 07:56:20 【问题描述】:

这是我第一次在这里写作,所以请记住这一点。我是第一次在项目中使用 webpack,我遇到了一个问题,我试图在我的 sass 文件中使用背景 url() 函数设置背景图像,如下所示:

.img-container 
  background: url('../../img/homepage-login-prog.jpg') no-repeat center center fixed;
  background-size: cover;

我的文件夹结构是:

- css
  | app.css
- dist (this folder is created after building for production)
- img
  | some-image.jpg
- js
  | app.js (entry point for webpack output, 
            this is where I import main.scss file)
- js-vendor
  | vendor.js (third-party libraries like bootstrap, jquery)
- sass  (this is where I keep all my sass files which get compiled using 
         webpack loaders)
  | components
    | greetings-section.scss
    | navbar.scss
  | main.scss
  | variables.scss
- template.html
- webpack.common.js
- webpack.dev.js
- webpack.prod.js

因为我已经为开发和生产配置了 webpack,所以我为它们都有单独的文件,它们都扩展了通用(通用)配置文件。那个看起来像这样:

const path = require("path");

module.exports = 
  entry:
    main: "./js/app.js",
    vendor: "./js-vendor/vendor.js"
  ,
  module: 
    rules: [
      
        test: /\.html$/,
        use: ["html-loader"]
      ,
      
        test: /\.(svg|png|jp(e*)g|gif)$/,
        use: [
          loader: "file-loader",
          options: 
            name: "[name].[hash].[ext]",
            outputPath: "img",
          
        ]
      
    ]
  
;

我的 webpack 开发配置如下所示:

const common = require("./webpack.common");
const merge = require("webpack-merge");
const path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = merge(common, 
  mode: "development",
  output: 
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "dist")
  ,
  plugins: [
    new HtmlWebpackPlugin(
      template: "./template.html"
    ),
    new MiniCssExtractPlugin(
      filename: "[name].[contentHash].min.css"
    ),
  ],
  module: 
    rules: [
      
        test: /\.scss$/,
        use: [
          
            loader: MiniCssExtractPlugin.loader,
            options: 
              publicPath: "../../"
            
          ,
          "css-loader",
          "sass-loader"
        ]
      
    ]
  
);

所以,webpack-dev-server启动后,会弹出一个错误:

ERROR in ./sass/main.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/lib/loader.js!./sass/main.scss)
Module not found: Error: Can't resolve '../../img/homepage-login-prog.jpg' in 'C:\Users\...\...\...\sass'

如您所见,我尝试使用 mini-css-extract-plugin 中的 publicPath 选项设置相对路径,但它并没有为我解决问题。 我也一直在阅读其他人有类似的问题,但他们的解决方案都不适合我,所以我想问的是,有谁知道我如何配置 webpack 来识别我的 sass 中图像的 url文件,并正确绑定?

抱歉发了这么长的帖子,任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

这种图片是 webpack 的静态资源。所以你可以使用url-loader来加载。

要安装它:

npm install url-loader --save-dev

在你的 webpack 配置文件中使用加载器中的 url-loader


  test: /\.(png|jpg)$/,
  loader: 'url-loader'

【讨论】:

它仍然不起作用,我仍然得到同样的错误:/ 如果你错过了它,我正在使用文件加载器来解析所有类型的图像,但这只有在我已经有的情况下才有效我的 html 中带有 src 属性的图像。我需要一种从 sass 加载背景图片 url 的方法:/ 仍然感谢您的快速响应,希望其他人能提出解决方案。【参考方案2】:

遇到了类似的问题,对我有用的是将 main.scss 文件移动到我的 sass 文件夹中。之前,它位于 src 文件夹中。 main.scss 文件导入我所有的其他 .scss 文件。在作为入口点的 index.js 中,我导入 main.scss 文件。

我的文件结构与你的不同。

我有一个用于输出的 dist 文件夹和一个用于输入的 src 文件夹。

index.js:

import "./sass/main.scss";

main.scss:

@import "./footer";
@import "./header";
@import "./home";
@import "./navigation";
@import "./reset";
@import "./typography";
@import "./variables";

_header.scss:

  #hero 
  background-image: url("../assets/heroImage.jpg");
  background-size: cover;
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;

由于我的 scss 代码中的 background-image: url() 问题,我遇到了同样的错误。这个导入结构为我解决了这个问题。

对于我的 webpack,我有一个非常相似的配置,分为 3 个、common、dev 和 prod。我添加的唯一插件是 webpack.dev 中的“resolve-url-loader”。我已经尝试过 miniCssExtractPlugin 中的 publicpath 无济于事。

除了入口点之外,我的 common 和你的几乎完全相同。我的是 src 文件夹中的 index.js 而不是 app.js。

webpack.dev.js

const path = require("path");
const common = require("./webpack.common");
const merge = require("webpack-merge");
var HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = merge(common, 
  mode: "development",
  output: 
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "dist")
  ,
  plugins: [
    new HtmlWebpackPlugin(
      template: "./src/template.html"
    )
  ],
  module: 
    rules: [
      
        test: /\.scss$/,
        use: [
          
            loader: "style-loader"
          ,
          
            loader: "css-loader"
          ,
          
            loader: "resolve-url-loader"
          ,
          
            loader: "sass-loader"
          
        ]
      
    ]
  
);

这在无数小时后为我解决了这个问题。让我知道这是否对您有任何帮助。干杯。

【讨论】:

这应该可以工作 - background-image: url("./assets/heroImage.jpg");【参考方案3】:

问题不在 webpack 中。您的问题出在后台 url 路径中。由于您已将所有 css 导入到单个 main.scss 中,因此您需要在背景 url 中执行以下操作 -

.img-container 
      background: url('./../img/homepage-login-prog.jpg') no-repeat center center fixed;
      background-size: cover;
 

【讨论】:

【参考方案4】:

您也可以尝试使用resolve.modules 来获取相对路径和绝对路径。 通过添加到您的配置文件:

module.exports = 
  ...,
  resolve: 
    modules: [
      path.resolve(__dirname, "img"),
      "node_modules"
    ],
  ,
  ...

然后你可以从你的 sass 文件中访问你的图片:

background-image: url("~homepage-login-prog.jpg");

或者用相对路径替换波浪号。

【讨论】:

【参考方案5】:
npm install url-loader --save-dev


  test: /\.(png|jpg)$/,
  loader: 'url-loader'

这是我的解决方案,谢谢!

【讨论】:

【参考方案6】:

如果这不是 SASS 样式问题。那么为什么会出现这个错误呢?

图片位置正确,我检查了。你可以看到这个截图。

图片位置:

NPM 错误详情:

ERROR in ./resources/sass/app.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/css-loader/dist/cjs.js):
Error: Can't resolve '../images/icon-sprite.png' in 'C:\laragon\www\bhalokisu\resources\sass'
    at finishWithoutResolve (C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:293:18)
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:362:15
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:410:5
    at eval (eval at create (C:\laragon\www\bhalokisu\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1)
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:410:5
    at eval (eval at create (C:\laragon\www\bhalokisu\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:27:1)
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\DescriptionFilePlugin.js:87:43
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:410:5
    at eval (eval at create (C:\laragon\www\bhalokisu\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:410:5
    at eval (eval at create (C:\laragon\www\bhalokisu\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1)
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:410:5
    at eval (eval at create (C:\laragon\www\bhalokisu\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:27:1)
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\DescriptionFilePlugin.js:87:43
    at C:\laragon\www\bhalokisu\node_modules\enhanced-resolve\lib\Resolver.js:410:5
    at eval (eval at create (C:\laragon\www\bhalokisu\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1)
    at processResult (C:\laragon\www\bhalokisu\node_modules\webpack\lib\NormalModule.js:743:19)
    at C:\laragon\www\bhalokisu\node_modules\webpack\lib\NormalModule.js:844:5
    at C:\laragon\www\bhalokisu\node_modules\loader-runner\lib\LoaderRunner.js:399:11
    at C:\laragon\www\bhalokisu\node_modules\loader-runner\lib\LoaderRunner.js:251:18
    at context.callback (C:\laragon\www\bhalokisu\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
    at Object.loader (C:\laragon\www\bhalokisu\node_modules\css-loader\dist\index.js:155:5)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

1 ERROR in child compilations (Use 'stats.children: true' resp. '--stats-children' for more details)
webpack compiled with 2 errors

图片错误:

更新: 我正在使用 Laravel 项目。我发现问题出在目录相关。我是在公共目录中为我的图像创建的。在resources/images/imageName.png创建目录后,问题就消失了。如果有人不明白,我可以帮助你。

【讨论】:

这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review

以上是关于如何使用 webpack-4 解析 sass 文件中的背景图像 URL?的主要内容,如果未能解决你的问题,请参考以下文章

webpack 4.X 与 Vue 2.X结合

webpack 4 sass-loader 不生成 scss 源映射

Webpack 4 - 如何解析不同的 img URL

webpack 4:创建多个主题 css 文件

使用 Angular 7 构建的 Webpack 4 在尝试访问 node_modules 时会出现 sass-loader 问题

带有 sass-loader 和 resolve-url-loader 的 Webpack 4 - 找不到图像路径