webpack多頁應用架構系列(六):據說webpack連圖片和字體也能打包?

本文首發於 Array_Huang的技術博客—— 實用至上,非經做者贊成,請勿轉載。
原文地址: https://segmentfault.com/a/1190000006907701
若是您對本系列文章感興趣,歡迎關注訂閱這裏: https://segmentfault.com/blog/array_huang

前言

上一篇《據說webpack連less/css也能打包?》說到使用loader來加載CSS,這一篇來說講如何籠統地加載其它類型的資源。爲何強調是「籠統」呢?這是由於本文介紹的方法並不針對任何類型的資源,這意味着,什麼類型的資源都能用,但效果也都只是有限的。javascript

用的什麼loader呢?

本文介紹倆loader:file-loader和url-loader。css

file-loader

file-loader的主要功能是:把源文件遷移到指定的目錄(能夠簡單理解爲從源文件目錄遷移到build目錄),並返回新文件的路徑(簡單拼接而成)。html

file-loader須要傳入name參數,該參數接受如下變量(如下討論的前提是:源文件src/public-resource/imgs/login-bg.jpg;在根目錄內執行webpack命令,也就是當前的上下文環境與src目錄同級):前端

  • [ext]:文件的後綴名,示例爲'jpg'。
  • [name]:文件名自己,示例爲'login-bg'。
  • [path]:相對於當前執行webpack命令的目錄的相對路徑(不含文件名自己),示例爲'src/public-resource/imgs/'。這個參數我感受用處不大,除非你想把遷移後的文件放回源文件的目錄或其子目錄裏。
  • [hash]:源文件內容的hash,用於緩存解決方案

個人作法是,require('!file-loader?name=static/images/[name].[ext]!../imgs/login-bg.jpg'),這樣login-bg.jpg的路徑就變成static/images/login-bg.jpg了,注意這還不是完整的路徑,最終仍是要拼上webpack配置中的output.publicPath參數的;好比說個人output.publicPath參數是../../../../build/,那麼最終從require()裏得到的完整路徑就會是../../../../build/static/images/login-bg.jpg了。html5

url-loader

url-loader的主要功能是:將源文件轉換成DataUrl(聲明文件mimetype的base64編碼)。據我所知,在前端範疇裏,圖片和字體文件的DataUrl都是能夠被瀏覽器所識別的,所以能夠把圖片和字體都轉化成DataUrl收納在HTML/CSS/JS文件裏,以減小HTTP鏈接數。java

url-loader主要接受如下參數:webpack

  • limit參數,數據類型爲整型,表示目標文件的體積大於多少字節就換用file-loader來處理了,不填則永遠不會交給file-loader處理。例如require("url?limit=10000!./file.png");,表示若是目標文件大於10000字節,就交給file-loader處理了。
  • mimetype參數,前面說了,DataUrl是須要聲明文件的mimetype的,所以咱們能夠經過這個參數來強行設置mimetype,不填寫的話則默認從目標文件的後綴名進行判斷。例如require("url?mimetype=image/png!./file.jpg");,強行把jpg當png使哈。
  • 一切file-loader的參數,這些參數會在啓用file-loader時傳參給file-loader,好比最重要的name參數。

實操演示

接下來仍是用個人腳手架項目webpack-seed來介紹如何利用url-loader和file-loader來加載各種資源。git

圖片

這一塊我是直接在webpack配置文件裏設置的:github

{
          // 圖片加載器,雷同file-loader,更適合圖片,能夠將較小的圖片轉成base64,減小http請求
          // 以下配置,將小於8192byte的圖片轉成base64碼
          test: /\.(png|jpg|gif)$/,
          loader: 'url-loader?limit=8192&name=./static/img/[hash].[ext]',
        },

因爲使用了[hash],所以即使是不一樣頁面引用了相同名字但實際內容不一樣的圖片,也不會形成「覆蓋」的狀況出現;進一步講,若是不一樣頁面引用了在不一樣位置但實際內容相同的圖片,這還能夠歸併成一張圖片,方便瀏覽器緩存呢。web

字體文件

這一塊我也仍是直接在webpack配置裏配置的:

{
          // 專供iconfont方案使用的,後面會帶一串時間戳,須要特別匹配到
          test: /\.(woff|woff2|svg|eot|ttf)\??.*$/,
          loader: 'file?name=./static/fonts/[name].[ext]',
        },

須要聲明的是,因爲我使用的是阿里媽媽的iconfont方案,此方案加載字體文件的方式有一點點特殊,因此正則匹配的時候要注意一點,iconfont的CSS是這樣的,大家看看就明白了:

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

其它資源

也許你會問,咱們爲何還須要轉移其它資源呢?直接引用不就能夠了嗎?

我以前也是這麼作的,直接引用源文件目錄src裏的資源,好比說webuploader用到的swf文件,好比說用來兼容IE而又不須要打包的js文件。可是後來我發現,這樣作的話,就致使部署上線的時候要把build目錄和src目錄同時放上去了;並且因爲build目錄和src目錄同級,我就只能用build目錄和src目錄的上一級目錄做爲網站的根目錄了(由於若是把build目錄設爲網站,用戶就讀取不到src目錄了),反正就是各類的不方便。

那麼,我是怎麼作的呢?

我建了一個config文件,名爲build-file.config.js,內容以下:

module.exports = {
  js: {
    xdomain: require('!file-loader?name=static/js/[name].[ext]!../../../vendor/ie-fix/xdomain.all.js'),
    html5shiv: require('!file-loader?name=static/js/[name].[ext]!../../../vendor/ie-fix/html5shiv.min.js'),
    respond: require('!file-loader?name=static/js/[name].[ext]!../../../vendor/ie-fix/respond.min.js'),
  },
  images: {
    'login-bg': require('!file-loader?name=static/images/[name].[ext]!../imgs/login-bg.jpg'),
  },
};

這個config文件起到兩個做用:

  1. 每次加載到這個config文件的時候,會執行那些require()語句,對目標文件進行轉移(從src目錄到build目錄)。
  2. 調用目標文件的代碼段,能夠從這個config文件取出目標文件轉移後的完整路徑,例如我在src/public-resource/components/header/html.ejs裏是這麼用的:
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title><% if (pageTitle) { %> <%= pageTitle %> - <% } %> XXXX後臺</title>
  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" /> 
  <meta name="renderer" content="webkit" />

  <!--[if lt IE 10]>
    <script src="<%= BUILD_FILE.js.xdomain %>" slave="<%= SERVER_API_URL %>cors-proxy.html"></script>
    <script src="<%= BUILD_FILE.js.html5shiv %>"></script>
  <![endif]-->
</head>
<body>
  <!--[if lt IE 9]>
    <script src="<%= BUILD_FILE.js.respond %>"></script>
  <![endif]-->

恩,你可能會好奇這HTML裏怎麼能直接引用js的值,哈哈哈,超綱了超綱了,這是我後面要講到的內容了。

示例代碼

諸位看本系列文章,搭配我在Github上的腳手架項目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)

附系列文章目錄(同步更新)

本文首發於 Array_Huang的技術博客—— 實用至上,非經做者贊成,請勿轉載。
原文地址: https://segmentfault.com/a/1190000006907701
若是您對本系列文章感興趣,歡迎關注訂閱這裏: https://segmentfault.com/blog/array_huang
相關文章
相關標籤/搜索