• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

webpack:sass-loader, scss使用url加载图片报NotFound的三个解决方法

武飞扬头像
尧九之阳
帮助3

问题描述:

使用vue-cli搭建好vue项目结构后,我在Home.scss中使用background-image: url('../../images/home_banner.jpeg');加载一个背景图片,没想到报错:

This relative module was not found:

* ../../images/home_banner.jpeg in ./node_modules/_css-loader@0.28.11@css-loader?{"sourceM
ap":false}!./node_modules/_vue-loader@13.7.3@vue-loader/lib/style-compiler?{"vue":true,"id
":"data-v-5a90ec03","scoped":false,"hasInlineConfig":false}!./node_modules/_sass-loader@7.
1.0@sass-loader/lib/loader.js?{"sourceMap":false}!./node_modules/_vue-loader@13.7.3@vue-lo
ader/lib/selector.js?type=styles&index=0!./src/pages/Home.vue

那这是为什么呢?虽然这是sass-loader的一个已知的问题,还是要把解决过程记录下来,丰富自己也造福后来人。

版本描述:

"sass-loader": "^7.1.0",
"vue": "^2.5.2",
"webpack": "^3.6.0"

代码结构:

Home.vue

<template>
  <div class="home">
    <PageHeader></PageHeader>
    <div class="img-wrap">
      <img src="../assets/images/home_banner.jpeg">
    </div>
  </div>
</template>

<script>
import PageHeader from '../components/PageHeader'

export default {
  data () {
    return {}
  },
  components: {
    'PageHeader': PageHeader
  }
}
</script>

<style lang="scss" scoped>
@import "../assets/scss/pages/Home.scss"
</style>

Home.scss

div.img-wrap{
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url('../../images/home_banner.jpeg');
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center 75%;
}

src/

.
├── App.vue
├── assets
│   ├── images
│   │   ├── home_banner.jpeg
│   │   └── user_default_grey.png
│   └── scss
│       ├── components
│       │   └── PageHeader.scss
│       ├── pages
│       │   └── Home.scss
│       └── _variables.scss
├── components
│   ├── PageFooter.vue
│   └── PageHeader.vue
├── main.js
├── pages
│   ├── Admin.vue
│   └── Home.vue
├── router
│   └── index.js

思考思路:

1. 一开始走错了方向,总是觉得自己的路径写的有问题;是因为我己对webpack怎么处理静态资源不清楚,见参考1;

2. 由于我在Home.vue中,直接在img 的src使用相对路径引用图片,也没问题;所以,我就想应该是在scss中使用url有啥问题,最后各种搜索,发现这是个已知的问题,sass-loader的url问题,在官方文档中有描述,见参考2;

解决方法:

1. 逃避型:

不使用单独的scss文件,scss的内容写在Home.vue的style中,验证可用;

<style lang="scss" scoped>
div.img-wrap{
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url('../assets/images/home_banner.jpeg');
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center 75%;
}
</style>

2. 间接型:

不在scss文件中设置background-image,而是在vue中设置,方法如下:

<template>
  <div class="home">
    <PageHeader></PageHeader>
    <div class="img-wrap" :style="{backgroundImage: 'url(' imageUrl ')'}"> 
    </div>
  </div>
</template>

<script>
import PageHeader from '../components/PageHeader'

export default {
  data () {
    return {
      imageUrl: require('../assets/images/home_banner.jpeg')
    }
  },
  components: {
    'PageHeader': PageHeader
  }
}
</script>

3. 解决型

使用官方文档中推荐的方法,使用resolve-url-loader来解决sass-loader缺少url rewriting的功能。

设置如下:(注意sourceMap需要设置为true)

//将resolve-url-loader置于css-loader与sass-loader之间
//resolve-url-loader之前的loader都需要source-maps
//source-maps required for loaders preceding resolve-url-loader (regardless of devtool).
rules: [
  {
    test: /\.scss$/,
    use: [
      ...
      {
        loader: 'css-loader',
        options: {...}
      }, {
        loader: 'resolve-url-loader',
        options: {...}
      }, {
        loader: 'sass-loader',
        options: {
          sourceMap: true,
          sourceMapContents: false
        }
      }
    ]
  },
  ...
]

参照上述设置,在vue工程中的修改如下:

/config/index.js
dev中
cssSourceMap设置为true

/build/utils.js
// generate loader string to be used with extract text plugin
  function generateLoaders (loader, loaderOptions) {
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

    if (loader === 'sass') {//增加resolve-url-loader
      loaders.push({
        loader: 'resolve-url-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    if (loader) {
      loaders.push({
        loader: loader   '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

这样以后,我们就可以愉快的在scss文件中使用url了。

参考:

1. webpack处理静态资源

2. sass-loader的url问题

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhegakjh
系列文章
更多 icon
同类精品
更多 icon
继续加载