1.0.1 • Published 12 months ago

@jameswilliamquinn2018/preact-lazy-load v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
12 months ago

To extract the code into an npm library that can be easily implemented in a new Preact app, you will need to structure your code as a reusable package. Here’s a step-by-step guide to creating an npm package for lazy loading in Preact:

Step-by-Step Guide

1. Set Up the NPM Package

  1. Create a new directory for your library:

    mkdir preact-lazy-load
    cd preact-lazy-load
  2. Initialize the npm package:

    npm init -y
  3. Install Preact as a dependency:

    npm install preact
  4. Create the required directory structure:

    mkdir src
    touch src/index.js src/LazyImage.js src/LazyIframe.js src/LazyBackgroundImage.js

2. Write the Library Code

src/index.js

This file will export all the components.

export { default as LazyImage } from './LazyImage';
export { default as LazyIframe } from './LazyIframe';
export { default as LazyBackgroundImage } from './LazyBackgroundImage';
src/LazyImage.js
import { h } from 'preact';
import { useRef, useEffect } from 'preact/hooks';

const LazyImage = ({ src, srcset, sizes, alt }) => {
  const imgRef = useRef(null);

  useEffect(() => {
    if ('loading' in HTMLImageElement.prototype) {
      imgRef.current.src = src;
      imgRef.current.srcset = srcset;
    } else {
      setupLazyLoadingFallback();
    }

    function setupLazyLoadingFallback() {
      if ('IntersectionObserver' in window) {
        const observer = new IntersectionObserver((entries, observer) => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              imgRef.current.src = src;
              imgRef.current.srcset = srcset;
              observer.unobserve(imgRef.current);
            }
          });
        }, { rootMargin: '0px 0px 50px 0px' });
        observer.observe(imgRef.current);
      } else {
        imgRef.current.src = src;
        imgRef.current.srcset = srcset;
      }
    }
  }, [src, srcset]);

  return (
    <img
      ref={imgRef}
      sizes={sizes}
      loading="lazy"
      alt={alt}
    />
  );
};

export default LazyImage;
src/LazyIframe.js
import { h } from 'preact';
import { useRef, useEffect } from 'preact/hooks';

const LazyIframe = ({ src, title }) => {
  const iframeRef = useRef(null);

  useEffect(() => {
    if ('loading' in HTMLIFrameElement.prototype) {
      iframeRef.current.src = src;
    } else {
      setupLazyLoadingFallback();
    }

    function setupLazyLoadingFallback() {
      if ('IntersectionObserver' in window) {
        const observer = new IntersectionObserver((entries, observer) => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              iframeRef.current.src = src;
              observer.unobserve(iframeRef.current);
            }
          });
        }, { rootMargin: '0px 0px 50px 0px' });
        observer.observe(iframeRef.current);
      } else {
        iframeRef.current.src = src;
      }
    }
  }, [src]);

  return (
    <iframe
      ref={iframeRef}
      loading="lazy"
      title={title}
    ></iframe>
  );
};

export default LazyIframe;
src/LazyBackgroundImage.js
import { h } from 'preact';
import { useRef, useEffect } from 'preact/hooks';

const LazyBackgroundImage = ({ src, children }) => {
  const divRef = useRef(null);

  useEffect(() => {
    if ('IntersectionObserver' in window) {
      const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            divRef.current.style.backgroundImage = `url(${src})`;
            divRef.current.setAttribute('data-loaded', 'true');
            observer.disconnect();
          }
        });
      }, { rootMargin: '0px 0px 50px 0px' });
      observer.observe(divRef.current);
    } else {
      // Fallback for older browsers
      divRef.current.style.backgroundImage = `url(${src})`;
      divRef.current.setAttribute('data-loaded', 'true');
    }
  }, [src]);

  return (
    <div ref={divRef} className="lazy-background">
      {children}
    </div>
  );
};

export default LazyBackgroundImage;

3. Add Styles

Since styles need to be included for the library to work correctly, create a style.css file and include it in the package.

Create src/style.css:

.lazy-background {
  opacity: 0;
  transition: opacity 0.3s;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}

.lazy-background[data-loaded] {
  opacity: 1;
}

Modify src/index.js to include the styles:

import './style.css';

export { default as LazyImage } from './LazyImage';
export { default as LazyIframe } from './LazyIframe';
export { default as LazyBackgroundImage } from './LazyBackgroundImage';

4. Bundle the Library

You will need to set up a bundler like Rollup to bundle your library. Here is an example configuration using Rollup.

  1. Install Rollup and necessary plugins:

    npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-babel @rollup/plugin-terser
  2. Create rollup.config.js:

    import resolve from '@rollup/plugin-node-resolve';
    import commonjs from '@rollup/plugin-commonjs';
    import babel from '@rollup/plugin-babel';
    import { terser } from '@rollup/plugin-terser';
    
    export default {
      input: 'src/index.js',
      output: {
        file: 'dist/index.js',
        format: 'esm',
        sourcemap: true,
      },
      plugins: [
        resolve(),
        commonjs(),
        babel({
          exclude: 'node_modules/**',
          presets: ['@babel/preset-env', '@babel/preset-react']
        }),
        terser(),
      ],
      external: ['preact']
    };
  3. Add build scripts to package.json:

    "scripts": {
      "build": "rollup -c"
    },

5. Build and Publish the Library

  1. Build the library:

    npm run build
  2. Publish the package:

    npm publish

6. Use the Library in a New Preact App

  1. Create a new Preact app:

    npx preact-cli create default my-new-preact-app
    cd my-new-preact-app
  2. Install the library:

    npm install preact-lazy-load
  3. Use the library in your Preact app:

src/index.js
import { h, render } from 'preact';
import App from './components/App';
import './style.css';

render(<App />, document.body);
src/components/App.js
import { h } from 'preact';
import { LazyImage, LazyIframe, LazyBackgroundImage } from 'preact-lazy-load';

const App = () => (
  <div>
    <h1>Native Lazy Loading in Preact</h1>
    
    <h2>Lazy Load Image</h2>
    <LazyImage 
      src="path/to/image.jpg" 
      srcset="path/to/image-320w.jpg 320w, path/to/image-480w.jpg 480w" 
      sizes="(max-width: 600px) 320px, 480px" 
      alt="Description of image"
    />
    
    <h2>Lazy Load Iframe</h2>
    <LazyIframe 
      src="https://www.youtube.com/embed/dQw4w9WgXcQ" 
      title="Sample Video"
    />
    
    <h2>Lazy Load Background Image</h2>
    <LazyBackgroundImage 
      src="path/to/background-image.jpg"
    >
      <p>Content overlaying the background image</p>
    </LazyBackgroundImage>
  </div>
);

export default App;

With this setup, you have created an npm library for lazy loading components in Preact that can be easily integrated into any Preact project.

1.0.1

12 months ago

1.0.0

12 months ago