当前位置: 首页 > Web前端 > JavaScript

前端开发:WebP自适应提升开发性能

时间:2023-03-27 00:27:46 JavaScript

WebP简介WebP是Google推出的一种图片格式,同时提供有损和无损两种压缩方式。优势体现在其出色的图像压缩算法,可以带来更小的图片尺寸,同时拥有更高的图像质量。根据官方说明,WebP在无损压缩的情况下可以比PNG减少26%的体积,在有损压缩的情况下可以比JPEG减少25%-34%的体积。从下图可以看出,与传统的图片格式相比,WebP格式存在浏览器兼容性问题。本文采用工程化手段实现WebP格式的自适应加载。传统上,为了在前端项目中使用WebP格式,并兼容不支持该格式的浏览器,通常的做法是判断浏览器支持,并引入WebP图片或其他常见格式的图片。对于HTML、JS、CSS,导入图片有三种处理方式:HTML利用了标签自适应加载的特性,如下,WebP格式放在标签中,常见的格式如因为使用了JPEG和PNG。做底线。<图片>JS通过JS判断浏览器是否支持WebP,支持则导入WebP格式的图片,不支持则导入JPEG、PNG等常用格式。有以下两种判断方式:canvas判断isSupportWebp=document.createElement("canvas").toDataURL("image/webp").indexOf("data:image/webp")===0;加载WebP图片判断函数isSupportWebp(callback){varimg=newImage();img.onload=function(){varresult=(img.width>0)&&(img.height>0);回调(结果);};img.onerror=function(){回调(假);};img.src='data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';}CSS首先需要判断浏览器是否支持WebP格式,如果支持则在HTML根节点NameID中添加一个类。document.documentElement.classList.add('webp')然后利用选择器的优先级实现WebP的自适应加载,对CSS中引入图片的方式做如下修改:.img{background-image:url('https://p3-imagex.byteimg.com/imagex-rc/preview.jpg~tplv-19tz3ytenx-147.jpeg')}.webp.img{background-image:url('https://p3-imagex.byteimg.com/imagex-rc/preview.jpg~tplv-19tz3ytenx-147.webp')}自动处理项目中导入大量本地图片时,手动处理方式比较繁琐,除了单独处理根据导入图像的方式。还需要事先将所有图像转换为WebP格式。考虑到大部分前端项目都是用Webpack构建的,尝试开发一个支持将项目中的图片转为WebP格式,支持图片格式适配的Webpack插件。方案设计首先需要将项目中的图片转为WebP格式。考虑到本地转换比较耗时,这一步更适合在云端完成。云端处理图片的服务比较成熟。大部分云服务商都是提供的,上传图片后打包后的产品体积可以明显缩小。上传图片第一步是将项目中的图片文件收集起来上传到云端。file-loader支持将import/require()引入的文件写入目标文件夹,并将文件解析成url,所以可以在file-loader的基础上使用方案为:获取loader匹配的图片文件,上传图片到云端,在云端生成WebP格式的图片;用图片服务生成的URL替换原来的图片文件;如果图片上传失败,将降级为文件-加载程序的处理流程将图像传输到输出文件夹。插入标记过程中有多个地方依赖浏览器与WebP的兼容性,因此需要全局标记。通过在标签中注入判断代码,如果浏览器支持WebP格式,则在根节点添加“webp”类名标识,这样就可以在页面渲染前获取浏览器对WebP格式的兼容性.前端项目通常使用html-webpack-plugin,它可以帮助创建HTML文件并自动导入Webpack生成的bundle。插件中有多个钩子,如下图所示。为确保head和body标签已经生成,可以选择在alterAssetTagGroup阶段注入相关判断代码。替换图片接下来根据全局标识将图片替换为对应的url。根据导入图片的位置,可以分为以下两种情况:JS中导入图片。将图片模块替换成一段JS代码,根据类名返回WebP或普通格式的图片url;图像是在CSS中导入的。如果在CSS模块中引入JS代码,一方面会出现执行错误,另一方面css-loader会在编译阶段执行这段代码,达不到判断WebP的目的浏览器端的兼容性,所以CSS部分需要单独处理。处理CSSCSS中引入了两种处理图像的选项:使用CSS选择器优先级。在css中图片引入的类后面插入一个带有webp类选择器的样式,原理与手动替换时处理css的方式相同。完全生成WebP版本的CSS。即文件中导入的图片均为WebP格式。链接样式文件时,判断根节点的类名,导入WebP版本CSS或原始CSS。第一种方案的缺点是改变了部分样式的优先级,可能会影响整体样式,所以采用第二种方案。方案实现本文方案选择火山引擎提供的veImageX图像服务来处理图像。veImageX是VolcanoEngine提供的图片整体解决方案,可以将图片转换为WebP、HEIF、AVIF等格式,支持从图片上传、存储、处理到分发的完整流程。图片上传到veImageX后,可以快速接入veImageX的各种云端处理能力,例如:裁剪、旋转、滤镜、橡皮擦、内容擦除等AI处理能力,并且可以轻松更改URL后缀在不同的地方获取图片格式。因此,以下方案基于veImageX实现展开。访问veImageX影像服务,获取accessKey、secretKey和服务ID。具体接入方式请参考文档;Webpack插件分为两个部分,在loader中上传和替换图片,在插件中生成webp类名标签和处理CSS导入的图片。通过Webpackloader获取项目中的图片文件,借助火山引擎提供的SDK将图片上传到veImageX,将图片模块替换为服务生成的url。根据veImageX改变URL后缀获取对应图片格式的特点,根据图片导入的位置进行不同的处理。如下,JS导入的图片根据浏览器兼容性判断,CSS导入的图片返回通用格式。结果=`varret='';if(typeofdocument==='object'){varformat='';document.documentElement.classList.forEach(item=>{if(item.match(/__(\w+)__/))format=(item.match(/__(\w+)__/))[1]})if(format){ret="//${formatDomain}${imagexUri}~${options.模板}${urlParams}。”+format;}else{ret="//${formatDomain}${imagexUri}~${options.template}${urlParams}.image";}}else{ret="//${formatDomain}${imagexUri}~${options.template}${urlParams}.image";}${esModule?'导出默认值':'module.exports='}ret`;这部分单独封装了veimagex-webpack-loader,支持将项目中的图片上传到veImageX,不需要WebP适配的可以直接使用这个loader。在html-webpack-plugin的alterAssetTagGroup钩子中插入浏览器WebP兼容性判断代码。这部分代码是在浏览器端执行的。如果浏览器支持WebP,则在根节点添加“__webp__”类名标识,如下:compiler.hooks.compilation.tap('ImagexWebpackPlugin',function(compilation){consthooks=self.htmlWebpackPlugin.getHooks(compilation);hooks.alterAssetTagGroups.tapAsync('ImagexWebpackPlugin',self.checkSupportWebp.bind(self));});ImagexWebpackPlugin.prototype.checkSupportFormat=function(htmlPluginData,callback){htmlPluginData.headTags.unshift({tagName:'script',closeTag:true,attributes:{type:'text/javascript'},innerHTML:`varisSupportFormat=!![].map&&document.createElement('canvas').toDataURL('image/${this.options.format}').indexOf('data:image/${this.options.format}')==0;如果(isSupportFormat)document.documentElement.classList.add('__${this.options.format}__');`});回调(空,htmlPluginData);};CSS文件的处理是生成全CSS方案的WebP版本,所以在alterAssetTagGrouphook还需要处理引入的CSS文件,将转换为