背景说明

某个国际化项目。前端用的技术栈是vue全家桶,使用nuxt-ssr渲染。

项目遇到的问题

项目中用到了大量的产品图片和比较大的banner图片。因为服务器在国外,也没有对静态服务器有相应的配置cdn服务,所以用户在第一次访问的时候,由于没有缓存所以导致图片渲染非常的慢,导致我们网站的体验非常大。

解决问题的想法

优化千万条,图片第一条。加载特别慢,用户两行泪。

好吧,我们这次要解决主要就是图片加载慢的问题。有几个客观因素我们暂时无法避免

  1. 服务器在国外
  2. 没有专门的cdn供本项目的使用

既然没有办法从硬件方便入手,那么只能从另外两方面入手

  1. 图片加载前能否优雅的告诉用户我们正在加载,您不要走,稍等一下
  2. 能否加载一些图片质量又高,体积又小的图片来加快图片下载速度

优雅的加载

我们怎么才能在图片下载前,告诉用户我们正在加载呢?

  1. 可以放一个骨架屏
  2. 可以放一个默认图片
  3. 可以放个进度条

这些看起来都不错,但是都有一个问题,用户无法感知这个图片的大致内容,或者说这些东西都和原图跳跃性太大。

所以我们选择的是第四种方案:放一个体积在1kb左右特别模糊的小图,然后放大展示。

webp

加载的问题解决了,那么有质量又高,体积又小的图片格式是什么,没错是webp。

关于这个格式的来龙去脉网上有很多介绍,我就不搬砖了(详情见下面两个链接)

https://www.zhihu.com/question/27201061

https://aotu.io/notes/2016/06/23/explore-something-of-webp/index.html

根据这些资料,我们可以总结一下webp的特点:

  1. 同样质量的图片webp格式比jpg格式小50%以上
  2. 同样质量的图片webp格式比png格式小45%以上
  3. webkit内核浏览器早就可以支持webp格式图片了
  4. 还有个别浏览器(IE:"看我干吗?")对webp支持依然不够友好

所以优化图片的格式就选择了webp。

技术调研

有了上面的思考,我们的想法应该是,不能怂,就是干。

我们来仔细的分析一下上面的这个需求,大致我拆分大两点

  1. webp格式图片和小图怎么来的
  2. 我怎么把这个功能做的通用一点

图片是怎么来的

我不想知道我是怎么没的, 我就想知道我是怎么来的

缺图片?找设计。好吧,如果我们去找设计要这种图片,设计拒绝了我们并且给了一段鄙视语。情理之中,毕竟重复工作谁都不愿意做。

那我们就让机器去做。

具体的想法是,我们能不能在项目打包的时候,顺便把需要的图片都生成出来。那肯定可以,这样的需求看起来有一个东西特别适合来做,webpack的plugin钩子(为什么不用loader?)。简单讲就是,当我们使用本项目的图片的时候比如require('image/bg.jpg')的时候。webpack会触发compiler.hooks的部分声明周期,当我们在打包前生成资源的时候,获取到源图片,然后进行一系列的图片转换,再把转换后的webp和min图片挂载到打包的过程上。这样图片也就被我们造出来了。

功能是怎么被组件化的

要做就要做一个脱离业务的组件出来,也就是造个能跑的轮子。

按照正常的逻辑可以先理解一下步骤

对于上面的总结,我们列出个步骤

  1. 需要三张图片
  2. 原图
  3. 原图生成的webp格式
  4. 原图缩小的min图片
  5. 浏览器加载小图片
  6. 判断浏览器是否支持webp
  7. 如果支持webp,就加载webp图片
  8. 如果不支持就加载原图片
  9. 将小图片逐渐消失

说明:上面的三张图片我们采用了一个规定:

  1. 原图片可以是(jpg|jpeg|png)等。
  2. 但是webp的图片,就是将原图只是换一个后缀。
  3. 缩小的图片则是在原图片的名字后面加入-min

注:当然要支持远程的图片啦,所以还要提供一个修改webp图和mini图片路径的入口,并且增加是否加载这两种图片的判断。

Vue技术栈

好吧,不吐槽vue了,都挺好。我们的技术栈是vue,所以这次组件的设计也是基于vue了。

我们的想法应该对组件有几种用法

<LazyBackgroundclass="test":src = "require('./images/logo.jpg')"
>测试地址11123
</LazyBackground>// 或者
<LazyBackgroundcssStyle={style.container}className={appStyle.box}src={require('./assets/bg.jpg')}
>使用全部功能的组件
</LazyBackground>
<LazyBackgroundcssStyle={style.container}className={[appStyle.box]}miniOptions={false}src={require('./assets/bg.jpg')}
>不需要加载小图的组
</LazyBackground>
<LazyBackgroundcssStyle={style.container}webpOptions={false}src={require('./assets/bg.jpg')}
>不需要加载webp的组件
</LazyBackground>
<LazyBackgroundcssStyle={style.container}miniOptions={{src: src => src}}webpOptions={{src: src => src}}src={require('./assets/bg.jpg')}
>分别设置小图和webp图片的路径
</LazyBackground>

对于上面的参数目前有几个要求

{cssStyle //接受一个style对象,添加到外层的div上className // 接受一个字符串或者数组,添加到外层的div上src // 默认图片路径miniOptions // 配置小图路径,默认接受一个含有src的对象,src是一个函数,接受处理过的url地址,默认小图的名称是原图后加 -minwebpOptions // 和上面一样,默认webp的图片名称是将后缀修改为 .webp
}
// (miniOptions和webpOptions)上面两个参数,如果不需要则直接设置成false,这样组件就不会加载对应图片,防止404出现

Webpack打包方案

webpack是个极其优秀的打包方案,其中loader可以让这个平台直接加载和优化各种后缀的问题,而plugin更是让海量的想法提供了落地的可能。(webpack如果不熟的一定要好好学一下)

我们相拥webpack做一个这样的plugin

new webpackPluginImageTransformWebpAndMini({name: '[name]-[hash:8].[ext]',logger: true,webpOptions: {src: src => src.replace(/(?:.w+)(?|$)/, '.webp$1')},miniOptions: {src: src => src.replace(/.(w+?)(?[sS]+)?$/,'-min.$1$2'),resize: {width: 100}},paths: {dir: path.resolve(__dirname, './src/assets'),include: ['bg']}
})

其中有几个参数要说明一下

- name 非必填项,主要和图片的file-loader或者url-loader采用的规则一样默认是'[name]-[hash:8].[ext]'(是因为vue-cli生成出来的配置是这样的)
- paths 必填项,会根据用户所填的路径进行转换(可递归)- 字符串:只是将此路径下的图片进行转换- 对象:{dir: 路径include: 字符串数组,只是在该路径下指定的文件进行转换exclude: 字符串数组,只是在该路径下除去指定的文件进行转换}
- logger 是否打印日志,默认是false
- webpOptions,对生成的webp的路径进行配置,接受一个函数,参数是图片名称,需要返回一个字符串作为图片的名称。默认只是将图片的后缀修改为wepb{src: src => src}
- miniOptions,对生成的小图进行配置,{src: src => src     // 和上面的功能一样,默认把图片的名称后面加入-min后缀resize: {   // 要压缩的图片大小,如果只写一个,那么默认进行比例,默认width为100width: xxxheight: xxx}}

工程化

有了上面的plugin,我们就可以根据原图片生成对应的小图与webp格式图片。有了这个组件,我们就可以直接使用生成后的图片来完成想要的效果。

下面简单实现一些上面的代码

解决方案

根据上面的使用方案,我们简单实现一些,为了提高一些逼格,下面的代码都是用的ts和tsx来完成的。

组件化延迟背景图方案

组件的都是使用tsx来写的。详细代码就不介绍了,有兴趣的可以看一下ropo。

插件化处理图片生成

上面是简单的目录结构

简单介绍一下:

index.ts

插件入口问题,处理默认的参数,定义apply方法挂载相应的钩子

core.ts

插件核心方法:

  1. 递归目录
  2. 生成mini图片
  3. 生成webp图片
  4. 判断include和exclude

utils.ts

提供工具方法:判断类型

logger.ts

打印方法

interface.ts

项目中接口规则

各种配置

各种配置提供了ts的简单配置和node端打包的简单配置。

示例

简单的看下图片对比加载过程

vue-dome

头部的简单的效果,贴一下代码

上面就是一个简单的目录,图片就是个背景

vue.config.js

const webpackPluginImageTransformWebpAndMini = require('webpack-plugin-image-transform-webp-and-mini')
const path = require('path')
module.exports = {configureWebpack: {plugins: [new webpackPluginImageTransformWebpAndMini({paths: {dir: path.resolve(__dirname, './src/assets'),include: ['bg']}})]}
}

main.js

import Vue from 'vue'
import App from './App.vue'
import LazyBackground from 'vue-lazy-background-component'
Vue.use(LazyBackground)Vue.config.productionTip = falsenew Vue({render: h => h(App),
}).$mount('#app')

App.vue

<template><div id="app"><LazyBackgroundclass="test":src = "require('./assets/bg.jpg')">测试地址11123</LazyBackground><img class="test" alt="Vue logo" src="./assets/bg.jpg"></div>
</template><script>
export default {name: 'app'
}
</script><style>
#app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;color: #2c3e50;margin-top: 60px;
}
.test {width: 540px;height: 300px;background-size: cover;
}
</style>

运行npm run serve,即可看到头图效果。

运行npm run build,可以看到图片都已经自动生成出来

npm

两个包目前都已经推倒了npm上了,需要的可以上去试试,可以直接用vue-cli生成的项目进行试验

https://www.npmjs.com/package/webpack-plugin-image-transform-webp-and-mini

https://www.npmjs.com/package/vue-lazy-background-component

github

如果想看源码的可以在github上,源码都是用ts写的,因此无论是配置还是代码,都是建议看一看

https://github.com/wuyxp/webpack-plugin-image-transform-webp-and-mini

https://github.com/wuyxp/vue-lazy-background-component

总结

写了这两个东西,学到了很多东西,尤其是webpack。深刻的认识到了,webpack是个后置技能,我们只是在配置文件上简单的配置几项内容而webpack在背后要做很多大量的工作去完成。所以要想学好前端工程,webpack及webpack背后的思想是一定要学习的。

还有一件事:996.icu很无聊。

国外方案 组件化_网页webp解决方案相关推荐

  1. webp的js插件_网页webp解决方案

    背景说明 某个国际化项目.前端用的技术栈是vue全家桶,使用nuxt-ssr渲染. 项目遇到的问题 项目中用到了大量的产品图片和比较大的banner图片.因为服务器在国外,也没有对静态服务器有相应的配 ...

  2. android 组件化_你曾遇到的某大厂奇葩问题:Android组件化开发,组件间的Activity页面跳转...

    组件化开发有什么好处? 1.当项目越来越大时,app的业务越来越复杂,会出现业务功能复杂混乱,各功能块.页面相互依赖,相互调用太多导致耦合度高,而采用组件化开发,我们就可以将功能模块合理的划分,降低功 ...

  3. swift 组件化_打造完备的iOS组件化方案:如何面向接口进行模块解耦?

    作者 | 黑超熊猫zuik,一个修行中的 iOS 开发,喜欢搞点别人没搞过的东西,钻研过逆向工程.VIPER 架构和组件化. 关于组件化的探讨已经有不少了,在之前的文章 iOS VIPER架构实践(三 ...

  4. android pod 组件化_使用 Pod 实现私有模块化管理(组件化 Pods 实现方案)

    概况 众所周知组件化是个好东西,它把项目拆分成多个模块,让每个模块能够独立出来解除各个模块之间的耦合性,作为每个独立的模块不仅仅能够使用组合的方式去组建各个不同的功能组合(前提是各个组件划分的颗粒度只 ...

  5. swift 组件化_京东商城订单模块基于 Swift 的改造方案与实践

    ABI Stability & Module Stability 以及Swift优势 2019年Swift 5发布,标志这门语言迎来了一个重大的里程碑.与之前的版本相比除了一些基础语法的改变, ...

  6. 爱奇艺开源的组件化跨进程通信解决方案

    /   今日科技快讯   / 近日,特斯拉首席执行官埃隆·马斯克来到中国上海,亲自向客户交付中国制造的Model 3,并透露了有关Model Y的更多信息,特斯拉股价继续保持着近三个月来的飙涨势头,目 ...

  7. mysql组件化_组件化开发和模块化开发概念辨析

    网上有许多讲组件化开发.模块化开发的文章,但大家一般都是将这两个概念混为一谈的,并没有加以区分.而且实际上许多人对于组件.模块的区别也不甚明了,甚至于许多博客文章专门解说这几个概念都有些谬误. 想分清 ...

  8. openfalcon 组件监控_开源监控解决方案OpenFalcon系列(一)

    OpenFalcon是由小米的运维团队开源的一款企业级.高可用.可扩展的开源监控解决方案,,在众多开源爱好者的支持下,功能越来越丰富,文档更加的完善,OpenFalcon 已经成为国内最流行的监控系统 ...

  9. java 组件化_(原创)搭建一个组件化的监控平台

    最近看到一位同事正在开发一个监控软件,要求就是通过针对服务器现有的一些接口,通过这些接口返回的数据进行分析,如果监控的值到达预先设定的范围则通过短信的方式发送给管理员. 从整个开发的功能上来看是一个比 ...

最新文章

  1. 十字相乘法c语言,十字相乘法的运算方法
  2. 高铁订票系统css,高铁订票系统-数据库系统设计.pptx
  3. 利用MySQL创建一个简单的employee员工表并修改表
  4. [Servlet]深入掌握Servlet
  5. 做到这4点,才是真正的持续交付| 研发效能提升36计
  6. WMI服务故障,VBS脚本无法运行错误
  7. 虚函数指针(vptr)与虚函数表(vptb)
  8. places365_Google Places API网络服务示例
  9. Linux学习技巧分享
  10. 关于数据元、元数据、主数据、交易数据、主题数据、数据资源、大数据、数据湖等数据相关概念理解和总结
  11. Android开发好用的依赖库
  12. (计算机组成原理)第七章输入和输出系统-第三节3:I/O方式之DMA方式
  13. 「Mpvue」记录我遇到的天坑
  14. 【无标题】c语言指针2333
  15. geany配置python_python使用Geany编辑器配置方法
  16. 小荷尖 - 发现更优质的企业服务
  17. html css样式绘制向下或者向上箭头
  18. 正确涂CPU硅脂的方法要这样
  19. 6.[dubbo源码解析]-属性配置
  20. 细品以太坊的“四棵树”——Merkle Patricia Trie

热门文章

  1. Arduino--DS3231实时时钟模块
  2. linux增加电子档案空间,Linux 建立 SWAP 档案空间
  3. 文章采集伪原创工具_卓尔博通|如何把伪原创文章变成原创
  4. python调用linux软键盘_在Linux中使用Python模拟键盘按键
  5. python -- 环境搭建
  6. Codeforces #1063C Dwarves, Hats and Extrasensory Abilities
  7. 蓝桥杯 能量项链 (区间dp)
  8. linux如何在shell中自动生成1到100的数组
  9. Ubuntu16.04删除客人会话
  10. 【转帖】.Net中C#的DllImport的用法