使用vue-cli搭建好vue項目結構後,我在Home.scss中使用background-image: url('../../images/home_banner.jpeg');加載一個背景圖片,沒想到報錯:javascript
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的一個已知的問題,仍是要把解決過程記錄下來,豐富本身也造福後來人。css
"sass-loader": "^7.1.0",
"vue": "^2.5.2",
"webpack": "^3.6.0"複製代碼
Home.vuehtml
<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
vue
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/java
.
├── 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;node
2. 因爲我在Home.vue中,直接在img 的src使用相對路徑引用圖片,也沒問題;因此,我就想應該是在scss中使用url有啥問題,最後各類搜索,發現這是個已知的問題,sass-loader的url問題,在官方文檔中有描述,見參考2;webpack
不使用單獨的scss文件,scss的內容寫在Home.vue的style中,驗證可用;git
<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>
複製代碼
不在scss文件中設置background-image,而是在vue中設置,方法以下:github
<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>
複製代碼
使用官方文檔中推薦的方法,使用resolve-url-loader來解決sass-loader缺乏url rewriting的功能。web
設置以下:(注意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了。