webpack多页应用架构系列(六):听说webpack连图片和字体也能打包?

本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006907701
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang

前言

上一篇《听说webpack连less/css也能打包?》说到使用loader来加载CSS,这一篇来讲讲如何笼统地加载其它类型的资源。为什么强调是“笼统”呢?这是因为本文介绍的方法并不针对任何类型的资源,这意味着,什么类型的资源都能用,但效果也都只是有限的。

用的什么loader呢?

本文介绍俩loader:file-loader和url-loader。

file-loader

file-loader的主要功能是:把源文件迁移到指定的目录(可以简单理解为从源文件目录迁移到build目录),并返回新文件的路径(简单拼接而成)。

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了。

url-loader

url-loader的主要功能是:将源文件转换成DataUrl(声明文件mimetype的base64编码)。据我所知,在前端范畴里,图片和字体文件的DataUrl都是可以被浏览器所识别的,因此可以把图片和字体都转化成DataUrl收纳在HTML/CSS/JS文件里,以减少HTTP连接数。

url-loader主要接受以下参数:

  • 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来加载各类资源。

图片

这一块我是直接在webpack配置文件里设置的:

        {
          // 图片加载器,雷同file-loader,更适合图片,可以将较小的图片转成base64,减少http请求
          // 如下配置,将小于8192byte的图片转成base64码
          test: /\.(png|jpg|gif)$/,
          loader: 'url-loader?limit=8192&name=./static/img/[hash].[ext]',
        },

由于使用了[hash],因此即便是不同页面引用了相同名字但实际内容不同的图片,也不会造成“覆盖”的情况出现;进一步讲,如果不同页面引用了在不同位置但实际内容相同的图片,这还可以归并成一张图片,方便浏览器缓存呢。

字体文件

这一块我也还是直接在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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容