webpack sass-loader 如何正確加載 font字體

出現的問題

使用webpack一般會用到sass-loader,固然這不是重點。問題是引用font字體文件時會出現以下錯誤:css

xx路徑引用不正確,致使資源找不到

再看看目錄結構和引用方式:
圖片描述webpack

@font-face {font-family: "iconfont";
    src: url('../../assets/fonts/iconfont.eot?t=1540697325659'); /* IE9*/
    src: url('../../assets/fonts/iconfont.eot?t=1540697325659#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('../../assets/fonts/iconfont.woff?t=1540697325659') format('woff'),
    url('../../assets/fonts/iconfont.ttf?t=1540697325659') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
    url('../../assets/fonts/iconfont.svg?t=1540697325659#iconfont') format('svg'); /* iOS 4.1- */
  }

而然文件引用層級和目錄的結構又是正確的,爲何加載字體文件的時候會出問題?git

官方解釋

https://github.com/webpack-contrib/sass-loader#problems-with-urlgithub

圖片描述

簡單講就是 sass-loader 這個加載器沒有提供 url重寫的功能,因此致使即便你文件路徑是「正確的」,其實仍是引用不到。
再畫個重點:其實經過 background之類用到url,仍是加載不到資源的,只是咱們可能一般會把font文件經過抽取到公共目錄下,致使 url rewriting 的問題會被暴露出來。web

拿background舉2個例子:chrome

index.scss //沒有報錯。引用和資源路徑對象,其實只是誤打誤撞而已bootstrap

@import "./common/testSass.scss";
.image{
    width: 100px;
    height: 100px;
    border:1px solid green;
    background: url('../assets/images/logo.png') 100% 100%;
}

testSass.scss //報錯。看似引用正確,其實和font的問題一致sass

.image{
    width: 100px;
    height: 100px;
    border:1px solid green;
    background: url('../../assets/images/logo.png') 100% 100%;
}

如何解決

理解上面問題出現的緣由,給出「能夠」解決問題的方法:ide

把../../ 改爲 ../svg

testSass.scss // success

.image{
    width: 100px;
    height: 100px;
    border:1px solid green;
    background: url('../assets/images/logo.png') 100% 100%;
}

iconfont.scss // success

@font-face {font-family: "iconfont";
    src: url('../assets/fonts/iconfont.eot?t=1540697325659'); /* IE9*/
    src: url('../assets/fonts/iconfont.eot?t=1540697325659#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('../assets/fonts/iconfont.woff?t=1540697325659') format('woff'),
    url('../assets/fonts/iconfont.ttf?t=1540697325659') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
    url('../assets/fonts/iconfont.svg?t=1540697325659#iconfont') format('svg'); /* iOS 4.1- */
  }

由於上面 出問題 的引用都是經過 css-loader ,因此根據上面的問題描述,得出:即便是子目錄的文件仍是根據入口文件來作引用(即index.scss的位置)。

官方其實給出了2個方案:

  • Add the missing url rewriting using the resolve-url-loader. Place it before the sass-loader in the loader chain.
  • Library authors usually provide a variable to modify the asset path. bootstrap-sass for example has an $icon-font-path. Check out this working bootstrap example.

具體什麼含義,能夠參考webpack中文社區的解釋。https://webpack.docschina.org/loaders/sass-loader/

最終方案

安裝 relative-url-loader

module: {
        rules: [
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                        fallback: "style-loader",
                        use: ['css-loader', 'resolve-url-loader', 'sass-loader?sourceMap=true']
                        // use: ['css-loader', 'sass-loader']
                    })
            }

sass中的資源文件,按照「正確」的引用定義

@font-face {font-family: "iconfont";
    src: url('../../assets/fonts/iconfont.eot?t=1540697325659'); /* IE9*/
    src: url('../../assets/fonts/iconfont.eot?t=1540697325659#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('../../assets/fonts/iconfont.woff?t=1540697325659') format('woff'),
    url('../../assets/fonts/iconfont.ttf?t=1540697325659') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
    url('../../assets/fonts/iconfont.svg?t=1540697325659#iconfont') format('svg'); /* iOS 4.1- */
  }
.image{
    width: 100px;
    height: 100px;
    border:1px solid green;
    background: url('../../assets/images/logo.png') 100% 100%;
}

總結

這問題其實看到正確的文檔內容,很快速可以解決,但願能幫到各位。

相關文章
相關標籤/搜索