灵活使用url-loader将部分资源转化为base64

738 阅读3分钟

起因

公司项目的某个业务场景如下:下载订单时,提供四个可选的背景图片;客户点击其中一个,则可以实时预览订单效果,点击下载按钮即保存到本地。

前辈写的一行代码如下,功能是在页面加载时即读取几张图片资源的base64。

const img = require('!!url-loader?limit=100000!@/assets/images/xxx.png');

可以看到,使用了webpack中的url-loader,但是这个loader并没有出现在项目的vue.config.js中。使用这种写法的目的是什么呢?我开始了探究:

webpack-loader的inline引入

最新的webpack 5.x文档中已经找不到这种写法,但是我搜到webpack 2.2文档 -- url-loader中提到了这种使用方式:

url 加载器的功能类似 file 加载器,但是在文件大小低于指定的限制时(单位 bytes)可以返回一个 Data Url。

大小限制可以通过传递查询参数来指定。(默认为无限制)

如果文件大小大于限制,将转为使用 file-loader,所有的查询参数也会透传过去。

require("url-loader?limit=10000!./file.png");
// => 如果 "file.png" 大小小于 10kb 将返回 DataUrl

require("url-loader?mimetype=image/png!./file.png");
// => 指定文件的 mimetype(否则会用文件后缀推测)

require("url-loader?prefix=img/!./file.png");
// => file-loader 的参数也有效,如果被使用它们将被传递给 file-loader

这里有一个实际应用的例子,仅将选中的部分资源转换为base64格式。

同时,facebook的react教程出于随时可能弃用webpack的考虑,不建议用户在代码中使用inline写法;而eslint/no-webpack-loader-syntax这一eslint规范也提到,即使webpack支持inline语法,但更推荐用户通过配置文件的形式来使用loader:

Webpack allows specifying the loaders to use in the import source string using a special syntax ......

This syntax is non-standard, so it couples the code to Webpack. The recommended way to specify Webpack loader configuration is in a Webpack configuration file.

双感叹号写法

可以注意到,上方参数中使用了双感叹号写法。!!是一种js语法,但在此处是一种webpack-loader的语法:

  • -! 禁用前置和正常 loader
  • ! 禁用普通 loader
  • !! 禁用前置后置以及正常 loader

公司项目中,虽然vue.config.js中没有显示进行url-loader的配置,但是使用vue inspect 导出的完整配置中,还是能看到相关的代码。这是因为公司的脚手架中,将url-loader作为其默认加载器。这样一来,!!语法的禁用就显得很重要了。

语句末尾的!则代表着loader分隔符,用来将依次使用的多个loder分开。此处是为了分割loader和实际图片资源的地址。

其他实现方式

上文提到,webpack官网文档已经删除了这种inline写法,并且大公司也不推荐使用这种方式。那我们有没有其他方式实现按需转换呢?

有的,老老实实写正则表达式吧hhh

几篇讲loader的参考文章:

www.dazhuanlan.com/yitumoon/to…

fengmiaosen.github.io/2017/01/07/…

blog.51cto.com/u_14115828/…

segmentfault.com/a/119000000…