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

16

这是我第一次在这里写作,请谅解。我第一次在项目中使用webpack,并且遇到了一个问题,我试图在我的sass文件中使用background 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并正确绑定它吗?

很抱歉发了一篇长帖子,非常感谢任何帮助。

8个回答

6
遇到了类似的问题,解决方法是将我的main.scss文件移动到sass文件夹中。之前它在src文件夹中。main.scss文件导入了所有其他的.scss文件。在我的入口点index.js中,我导入了main.scss文件。
然而,我的文件结构与你的不同。

file structure

我有一个用于输出的“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与你的几乎完全相同,除了entrypoint。我的是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"
          }
        ]
      }
    ]
  }
});

在无数个小时之后,这个方法解决了我的问题。如果这对你有帮助,请告诉我。干杯。


背景图片: url("./assets/heroImage.jpg"); - Tanvir Islam Streame

5
问题不在于Webpack,而是在于背景URL路径。由于你已经将所有CSS导入到一个单独的main.scss中,因此需要在背景URL中执行以下操作:
.img-container {
      background: url('./../img/homepage-login-prog.jpg') no-repeat center center fixed;
      background-size: cover;
 }

3

最佳解决方案

我也遇到了这个问题,唯一的解决方案是使用~来引用根目录,并从那里访问公共文件夹。

background-image: url("~/public/images/icon.png");

这对我来说很好用 :)

或者另一种选择是将图片移动到src目录中,这不会成为问题,因为webpack会将它们打包成名为static/media的文件夹中的静态文件。


1

您还可以尝试使用resolve.modules来处理相对路径和绝对路径。 只需在配置文件中添加:

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

然后,您可以通过以下方式从Sass文件中访问您的图像:

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

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


0

从:
background-image: url('../../image/section1image.jpg');
到:
background-image: url('~../../image/section1image.jpg');

在url开头添加~(这对我有效)。希望有所帮助。


-1

尝试给出高度和宽度

.img-container {
     background: url('../../img/homepage-login-prog.jpg');
     background-size: cover;
     width: 100px;
     height: 100px;
}

或者添加一些填充

.img-container {
    background: url('../../img/homepage-login-prog.jpg');
    background-size: cover;
    padding: 100px;
}

或者在具有.img-container类的HTML标签中添加一些内容。


-1
npm install url-loader --save-dev

并且

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

这对我来说是个解决方案,谢谢!


-1

这种类型的图片是webpack的静态资源。因此,您可以使用url-loader进行加载。

安装方法如下:

npm install url-loader --save-dev

在你的webpack配置文件中使用loaders加载器来处理url-loader。
{
  test: /\.(png|jpg)$/,
  loader: 'url-loader'
}

它仍然不起作用,我仍然得到相同的错误 :/ 以防你错过了,我正在使用file-loader来解决所有类型的图像,但这仅在我已经在HTML中具有src属性的图像上有效。我需要一种从Sass加载背景图像的URL的方法 :/ 还是谢谢您的快速响应,希望其他人能提出解决方案。 - dedZombie

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