zoukankan      html  css  js  c++  java
  • webpack生成的css文件background-image url图片无法加载

    之前在使用webpack3构建基于less预处理的项目时,在对指定的元素使用background-image: url(xxx)来设置背景图片时,本地开发是ok的,但是在项目编译产出后背景图片就找不到;目前用webpack4开发项目时,同样遇到类似的问题;所以就借此机会探讨一下产生问题的原因。

    问题产生原因

    webpack3项目场景复现

    项目webpack有关css的配置伪码如下:

    output: { // 项目编译输出路径
     path: path.resolve(__dirname, 'dist')
    }
    // 图片的loader的配置如下:
    { 
      test: /.(gif|png|jpe?g)(?S*)?$/,
      loader: 'url-loader',
      options: {
        limit: 3000,
        name: path.join('static', env === 'development' ? 'img/[name].[ext]' : 'img/[name]_[hash:7].[ext]')
       }
    }
    
    // 样式文件打包产出的文件配置如下:
    if (env === 'produdtion') {
    webpackCfg.plugins.push(
     new ExtractTextPlugin({
       filename: 'static/index_[contenthash:7].css',
       disable: false,
       allChunks: true
     })
    )
    }
    
    

    上面配置的css在生产环境用extract-text-webpack-plugin来产出css样式文件,开发环境通过style-loader将css内容内联到html文档中;而图片是大于指定的limit大小就打包输出文件。

    此时在我们的index.less文件中设置body的背景图片如下:

    body {
     background-image: url('./img/bg.png');
    }
    

    此时本地开发可以看到背景图片,而编译产出css的文件,背景图片地址不能正确加载,通过测试发现是图片路径出现问题,如下图:

    从产出的css文件内容来看,body元素的background-image的图片url相对地址是webpack配置产出图片路径,但是页面实际展示时却发现图片路径为:/xx/../dist/static/static/img/bg_ebdbe98.png

    为什么会背景图片路径会多了一个static前缀?查询资料发现:

    css文件中设置的background-image的url相对地址是相对于当前css文件目录来得到的

    因为,项目中设置css的产出路径为dist/static/index_[contenthash:7].css,而url中经webpack处理后的url相对地址为static/img/bg_[hash:7].png; 这样根据上述规则,图片实际加载地址为即dist/static/static/img/bg_[hash:7].png,导致会在图片路径前缀多加了个static目录。

    而为啥本地开发环境没有出现问题,这是因为本地开发环境产出的css样式内容通过style-loader内联到html文档中,这是背景图片的路径是相对于html文档目录,所以是正确的。

    webpack4项目场景复现

    webpack4项目与webpack3项目不同的地方是,webpack4项目中使用mini-css-extract-plugin插件来处理css样式产出,其改善extract-text-webpack-plugin中的一些问题,其中比较重要的一点是可以使用css的热加载功能。项目中有关css抽出的配置如下:

    plugins: [
      new MiniCssExtractPlugin({
        filename: env === 'production' ? 'static/index.[contenthash:7].css' : 'static/index.css'
      })
    ],
    module: {
     rules: [{
      test: /.less$/,
      use: [
        {loader: MiniCssExtractPlugin.loader}, 
        {loader: 'css-loader', options: {...} },
        {loader: 'less-loader', options: {...} }
     }]
    }
    

    webpack4项目在开发环境和生产环境都使用mini-css-extract-plugin插件,所以项目都会产出css文件,二者环境都会出现问题;

    解决方法

    在知道问题产生原因后,也就知道该如何解决问题了。最佳的解决方法如下:

    • webpack3在extract-text-webpack-plugin的extract方法中单独配置css文件的publicPath

    若没有在extract-text-webpack-plugin配置css的publicPath,则会使用webpack.output.publicPath中值;一旦配置值则css中路径就会相对于新配置的publicPath值。但是这个值配置也是需要注意的。例如,上面文件产出目录:

    dist
    │   index.html
    └───static
    │   │   index.js
    │   │   index.css
    │   └─img
    │       │   bg.png
    

    图片的地址为static/img/bg.png,而在index.css中引入了该图片地址,所以图片的相对地址是相对于该css文件的目录,及最终加载的图片地址为static/static/img/bg.png,从而导致错误。此时正确的配置extract-text-webpack-plugin如下:

    ExtractTextPlugin.extract({
      fallback: 'style-loader',
      use: loaders,
      publicPath: '../'
    });
    

    这样,publicPath: '../'配置则是从当前index.css文件的父目录来查找图片。最终url的路径变成 "../static/img/bg.png"。

    • webpack4在mini-css-extract-plugin的loader中配置publicPath

    webpack4也是配置publicPath,只不过配置方式稍有不同,如下:

    module: {
        rules: [
          {
            test: /.css$/,
            use: [
              {
                loader: MiniCssExtractPlugin.loader,
                options: {
                  publicPath: '../',
                  hmr: process.env.NODE_ENV === 'development',
                },
              },
              'css-loader',
            ],
          },
        ],
      },
    

    参考文献

  • 相关阅读:
    [OS] 修改屏幕分辨率(用Remote Desktop Connection 或者 用工具:Remote Desktop Connection Manager)
    英文单词通用缩写表
    [Selenium] 怎样判断是否适合自动化测试
    [Selenium] Java代码获取,设置屏幕分辨率
    [Selenium] Java代码获取屏幕分辨率
    [Selenium] 最大化或自定义浏览器的大小
    跟我一起玩Win32开发(7):多边形窗口
    跟我一起玩Win32开发(5):具有单选标记的菜单
    跟我一起玩Win32开发(6):创建右键菜单
    跟我一起玩Win32开发(4):创建菜单
  • 原文地址:https://www.cnblogs.com/wonyun/p/11038417.html
Copyright © 2011-2022 走看看