美文网首页让前端飞Web前端之路技术干货
使用rollup打包编写图片懒加载插件

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

作者: 小猿_Luck_Boy | 来源:发表于2020-03-14 14:56 被阅读0次

    前言

    众所周知,图片的加载是前端页面加载性能的优化之一。如果一个页面在加载的时候全部加载当前页面的图片,当图片资源比较多且比较大(质量)的时候会严重影响页面的加载。特别是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项目中,只能在单独组件使用(而且必须在组件的加载完成生命周期方法之后),不能一次创建永久使用

    谢谢!

    相关文章

      网友评论

        本文标题:使用rollup打包编写图片懒加载插件

        本文链接:https://www.haomeiwen.com/subject/bxkmshtx.html