使用rollup打包图片懒加载插件

前言

众所周知,图片的加载是前端页面加载性能的优化之一。如果一个页面在加载的时候全部加载当前页面的图片,当图片资源比较多且比较大(质量)的时候会严重影响页面的加载。特别是SPA应用,先加载jsbundle资源,再去加载图片资源,这样就会更加影响页面的加载性能。
一般我们优化页面加载的时候通常有一下几种方案:

  1. CSS文件放在页面顶部,而javascript文件放在底部
  2. 去掉不必要的js脚本插件
  3. 利用浏览器缓存
  4. 使用 CSS Sprites 整合图像
  5. 压缩CSSjavascript脚本
  6. 启用gzip压缩
  7. 优化图像
  8. 减少DNS查询
  9. 最小化重定向

本文编写的插件主要是从在加载页面的时候减少图片的请求来优化页面加载性能。下面分享一下使用rollup打包的懒加载图片插件。下面手把手教你撸一个图片懒加载插件,开始上车了...

这里小编推荐一个福利,更多精彩内容请点击链接,点击这里

初始化项目

创建img-lazyload目录,执行下边命令

cd img-lazyload
npm init -y 

安装配置rollup

rollup教程请查看官方文档

安装插件
npm install -D @babel/core @babel/preset-env 
npm install -D  rollup rollup-plugin-babel rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-uglify
  • @babel/core

babel的核心插件必不可少

  • @babel/preset-env

es6转化es5的插件,因为代码使用了es6新特性,需要配置babel

  • rollup

rollup核心包必不可少

  • rollup-plugin-babel

如果使用了babel,需要这个插件

  • rollup-plugin-commonjs

    node_modules中的包大部分都是commonjs格式的,要在rollup中使用必须先转为ES6语法,所以需要安装插件 但是本项目代码没有使用其它插件,这个包可以不安装,也可以不用添加commonjs的配置

  • rollup-plugin-node-resolve

rollup无法识别node_modules中的包,需要插件告诉 Rollup 如何搜寻外部依赖,但是本项目代码没有使用其它插件,这个包可以不安装,也可以不用添加resolve配置

  • rollup-plugin-uglify

压缩打包js代码

配置rollup打包js代码

build/rollup.config.jssrc/index.js文件

src/index.js这里编写代码,先添加下边代码

console.log("hello world");

build/rollup.config.js配置代码如下
这里只写了简单的配置

import { uglify } from 'rollup-plugin-uglify'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs' // commonjs规范的代码转化es6
import babel from 'rollup-plugin-babel'

export default {
    input: 'src/index.js', // 打包入口
    output: {
        file: 'dist/index.min.js', // 输出文件
        format: 'umd', // 打包格式,支持浏览器,也支持commonjs
        name:"ImgLazyLoad", // 编译浏览器环境的包时需要指定name属性   
    },
    plugins:[
        babel({
            exclude: ['node_modules/**']
        }), // 支持babel
        resolve(), // 查找包路径
        commonjs(), // 支持commonjs的插件
        uglify(), // 压缩代码的插件
    ],
}

到这里简单的配置已经完成,下边我们检查配置是否成功
添加打包命令在package.json

"build": "rollup --config build/rollup.config.js"

我们执行npm run build,会看到生成一个dist/index.js文件,下边这个就是我们打包生成的最终代码

QQ截图20200314113944.png

然后编写demo进行测试打包是否成功
新建example/index.html
编写代码如下

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,viewport-fit=cover">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="renderer" content="webkit|ie-comp|ie-stand">
  <meta http-equiv="x-dns-prefetch-control" content="on">
  <title>图片懒加载测试</title>
</head>
<body>
  <div id="app">
  </div>
  <script src="./../dist/index.min.js"></script>
</body>
</html>

这是主要是需要把打包的代码在html中进行加载<script src="./../dist/index.js"></script>

打开静态html,调出控制台。console.log("hello world")正常执行。说明rollup的配置可以打包

现在我们初始化项目完成,下边编写图片懒加载代码

图片懒加载源码

删除src/index.js的测试代码,编写如下代码

/*
 * 图片懒加载对象
 *  */
function ImgLazyLoad(className) {

    if (!this instanceof ImgLazyLoad) {
        console.warn('ImageLazy is a constructor and should be called with the `new` keyword')
        return;
    }

    // 判断类名是否为null
    if(!className) return;

    // 获取className的Node节点
    this.imageList = [...document.querySelectorAll(className)];


    if(this.imageList && this.imageList.length >0){
        // 初始化的时候需要先去执行一下滚动监听方法,需要首屏图片加载出来
        this.pageScroll();
        this.initScrollEvent();
    }
}

/*
 * 初始化监听滚动事件
 *  */
ImgLazyLoad.prototype.initScrollEvent = function(){
    window.addEventListener('scroll',()=>{
        this.imageList.length && this.pageScroll();                  
    })
}

/*
 * 监听滚动的回调方法
 *  */
ImgLazyLoad.prototype.pageScroll = function(){
    let imgs = this.imageList;
    const replacedIndexList = [];
    for(let i = 0;i < imgs.length;i++){
        // 判断当前图片是否在屏幕当前显示区域(这里做了一个小技巧,当图片的头部离屏幕底部60px开始加载图片的地址,防止图片过大且滑动过快的时候显示空白区域)
        if(imgs[i].getBoundingClientRect().top - 60 <= window.innerHeight){
            this.replaceImgSrc(imgs[i]);
            replacedIndexList.push(i);
        }
    }
    const array = [];
    // 把加载过的图片从数组中移除
    for(let i = 0;i < imgs.length;i++){
        if(replacedIndexList.indexOf(i) <= -1){
            array.push(imgs[i])
        }
        this.imageList = array;
    }
    
}

/*
 * 替换属性,正式加载图片
 *  */
ImgLazyLoad.prototype.replaceImgSrc = function(el){
    if(el){
        // 将图片替换为真实地址,加载图片
        let src = el.getAttribute('original-src');
        el.src = src;
    }
}
export default ImgLazyLoad;

运行npm run build构建源代码发现编译报错

QQ截图20200314133248.png

经过排查发现时babel没有配置
在项目根目录新建babel.config.js文件,代码如下:

module.exports = {
    presets: ['@babel/preset-env']
};

重新执行npm run build构建源代码发现无报错

完善Demo
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,viewport-fit=cover">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="renderer" content="webkit|ie-comp|ie-stand">
  <meta http-equiv="x-dns-prefetch-control" content="on">
  <title>图片懒加载测试</title>
  <style>
    html , body {
        margin: 0;
        padding: 0;
    }
    img {
        width: 100%;
    }
    .one {
        width: 359px;
        height: 538px;
    }
    .two {
        width: 359px;
        height: 385px;
    }
    .three {
        width: 359px;
        height: 638px;
    }
    </style>
</head>
<body>
  <div id="app">
    <div>
        <h3>第一张图片</h3>
        <img original-src="http://t7.baidu.com/it/u=3616242789,1098670747&fm=79&app=86&f=JPEG?w=900&h=1350" src="" class="lazy one" alt=""/>
    </div>
    
    <h2>这是占用文字测试demo</h2>
    <h2>这是占用文字测试demo</h2>
    <h2>这是占用文字测试demo</h2>
    <h2>这是占用文字测试demo</h2>

    <div>
        <h3>第二张图片</h3>
        <img src="" original-src="http://t8.baidu.com/it/u=3571592872,3353494284&fm=79&app=86&f=JPEG?w=1200&h=1290" class="lazy two" alt=""/>
    </div>

    <h2>这是占用文字测试demo</h2>
    <h2>这是占用文字测试demo</h2>
    <h2>这是占用文字测试demo</h2>
    <h2>这是占用文字测试demo</h2>
    <h2>这是占用文字测试demo</h2>

    <div>
        <h3>第三张图片</h3>
        <img src="" original-src="http://img1.imgtn.bdimg.com/it/u=3527822447,3068369850&fm=26&gp=0.jpg" class="lazy three" alt=""/>
    </div>
  </div>
  <script src="./../dist/index.min.js"></script>
  <script>
      new ImgLazyLoad(".lazy") //必须使用new创建,而且只能在dom加载完毕才可以实现这个功能
  </script>
</body>
</html>

打开静态src/index.html,调出控制台,查看元素。如下图

QQ截图20200314134823.png

发现加载页面的时候,第二,三张图片没有加载。上拉页面的时候,当图片快要出现在屏幕的时候,图片src被替换成了真实的图片地址,这时候才真正加载图片。

这里到此结束,这个项目还有不足之处。

用在spa项目中,只能在单独组件使用(而且必须在组件的加载完成生命周期方法之后),不能一次创建永久使用

谢谢!

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

推荐阅读更多精彩内容