npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

next-lazy-hydration-on-scroll

v1.2.0

Published

Hydrate components dynamically as the user scrolls.

Downloads

3,081

Readme

next-lazy-hydration-on-scroll

⚠️ Pages Directory Only - For Next.js App Directory better use built-in streaming.

Optimize Next.js app performance by lazy loading and hydrating components when they enter the viewport.

  • ⚡️ Lower Total Blocking Time (TBT)
  • 📦 Smaller Bundle Size
  • 🚀 Improved Performance

Installation

npm install next-lazy-hydration-on-scroll
# or
yarn add next-lazy-hydration-on-scroll
# or
pnpm add next-lazy-hydration-on-scroll

Usage

import { lazyHydrate } from 'next-lazy-hydration-on-scroll'

const LazyComponent = lazyHydrate(() => import('./components/HeavyComponent'), {
  LoadingComponent: () => <div>Loading...</div>, // Optional
  wrapperElement: 'div', // Optional, defaults to 'section'
})

export default function Page() {
  return (
    <div>
      <header>Always hydrated</header>
      <LazyComponent wrapperProps={{ className: 'my-wrapper', id: 'lazy-component' }} /> {/* Hydrates when scrolled into view */}
    </div>
  )
}

Options

| Option | Type | Default | Description | | ------------------ | ----------------------------- | ------------- | ------------------------------------------------------- | | rootMargin | string | '0px 250px' | Margin around the root element for IntersectionObserver | | LoadingComponent | ComponentType | undefined | Component to show while loading | | wrapperElement | keyof JSX.IntrinsicElements | 'section' | HTML element to wrap the component |

Component Props

| Prop | Type | Description | | -------------- | --------------------- | ------------------------------------ | | wrapperProps | Record<string, any> | Props to pass to the wrapper element |

How It Works

  1. Server renders full HTML content
  2. Components remain static until scrolled into view
  3. When component enters viewport:
    • JavaScript is loaded
    • Component is hydrated
    • Interactivity is enabled

Implementation Requirements

  • Keep components in separate files
  • Avoid barrel files (index.ts that re-exports components)
  • Import components directly:
// ✅ Correct
import { ComponentA } from './components/ComponentA'

// ❌ Avoid
// components/index.ts with re-exports

Browser Support

Works in all modern browsers supporting IntersectionObserver (IE11+ with polyfill).

Notes

  • SEO friendly - content is pre-rendered
  • Components are wrapped in customizable elements (default: <section>) for stable viewport detection
  • Works with Next.js 12 and above

FAQ

Q: Does it affect SEO?

A: No - all content is pre-rendered and visible to search engines.

Q: What's the browser support?

A: All modern browsers (IE11+ with polyfill).

Q: Why are components wrapped in an element?

A: For two reasons: to provide a stable element for IntersectionObserver tracking, and to handle hydration mismatches with suppressHydrationWarning.

Q: Can I customize the wrapper element?

A: Yes - use the wrapperElement option to specify any valid HTML element (e.g., 'div', 'article') and pass props to it using the wrapperProps prop.

Q: Why is dangerouslySetInnerHTML used?

A: It prevents React from hydrating down the component tree, allowing to preserve server-rendered content while controlling when hydration occurs.

View Demo | GitHub Repository