• Stars
    star
    1,187
  • Rank 39,407 (Top 0.8 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 6 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Lazy Hydration of Server-Side Rendered Vue.js Components

vue-lazy-hydration

Patreon Donate Build Status GitHub stars

Lazy Hydration of Server-Side Rendered Vue.js Components

ko-fi

vue-lazy-hydration is a renderless Vue.js component to improve Estimated Input Latency and Time to Interactive of server-side rendered Vue.js applications. This can be achieved by using lazy hydration to delay the hydration of pre-rendered HTML.

Install

npm install vue-lazy-hydration
import LazyHydrate from 'vue-lazy-hydration';
// ...

export default {
  // ...
  components: {
    LazyHydrate,
    // ...
  },
  // ...
};

Basic example

In the example below you can see the four hydration modes in action.

<template>
  <div class="ArticlePage">
    <LazyHydrate when-idle>
      <ImageSlider/>
    </LazyHydrate>

    <LazyHydrate never>
      <ArticleContent :content="article.content"/>
    </LazyHydrate>

    <LazyHydrate when-visible>
      <AdSlider/>
    </LazyHydrate>

    <!-- `on-interaction` listens for a `focus` event by default ... -->
    <LazyHydrate on-interaction>
      <CommentForm :article-id="article.id"/>
    </LazyHydrate>
    <!-- ... but you can listen for any event you want ... -->
    <LazyHydrate on-interaction="click">
      <CommentForm :article-id="article.id"/>
    </LazyHydrate>
    <!-- ... or even multiple events. -->
    <LazyHydrate :on-interaction="['click', 'touchstart']">
      <CommentForm :article-id="article.id"/>
    </LazyHydrate>
  </div>
</template>

<script>
import LazyHydrate from 'vue-lazy-hydration';

export default {
  components: {
    LazyHydrate,
    AdSlider: () => import('./AdSlider.vue'),
    ArticleContent: () => import('./ArticleContent.vue'),
    CommentForm: () => import('./CommentForm.vue'),
    ImageSlider: () => import('./ImageSlider.vue'),
  },
  // ...
};
</script>
  1. Because it is at the very top of the page, the ImageSlider should be hydrated eventually, but we can wait until the browser is idle.
  2. The ArticleContent component is never hydrated on the client, which also means it will never be interactive (static content only).
  3. Next we can see the AdSlider beneath the article content, this component will most likely not be visible initially so we can delay hydration until the point it becomes visible.
  4. At the very bottom of the page we want to render a CommentForm but because most people only read the article and don't leave a comment, we can save resources by only hydrating the component whenever it actually receives focus.

Advanced

Manually trigger hydration

Sometimes you might want to prevent a component from loading initially but you want to activate it on demand if a certain action is triggered. You can do this by manually triggering the component to hydrate like you can see in the following example.

<template>
  <div class="MyComponent">
    <button @click="editModeActive = true">
      Activate edit mode
    </button>
    <LazyHydrate never :trigger-hydration="editModeActive">
      <UserSettingsForm/>
    </LazyHydrate>
  </div>
</template>

<script>
import LazyHydrate from 'vue-lazy-hydration';

export default {
  components: {
    LazyHydrate,
    UserSettingsForm: () => import('./UserSettingsForm.vue'),
  },
  data() {
    return {
      editModeActive: false,
    };
  },
  // ...
};
</script>

Multiple root nodes

Because of how this package works, it is not possible to nest multiple root nodes inside of a single <LazyHydrate>. But you can wrap multiple components with a <div>.

<template>
  <div class="MyComponent">
    <LazyHydrate never>
      <div>
        <ArticleHeader/>
        <ArticleContent/>
        <ArticleMetaInfo/>
        <ArticleFooter/>
      </div>
    </LazyHydrate>
  </div>
</template>

Intersection Observer options

Internally the Intersection Observer API is used to determine if a component is visible or not. You can provide Intersection Observer options to the when-visible property to configure the Intersection Observer.

<template>
  <div class="MyComponent">
    <LazyHydrate :when-visible="{ rootMargin: '100px' }">
      <ArticleFooter/>
    </LazyHydrate>
  </div>
</template>

For a list of possible options please take a look at the Intersection Observer API documentation on MDN.

Import Wrappers

Additionally to the <LazyHydrate> wrapper component you can also use Import Wrappers to lazy load and hydrate certain components.

<template>
  <div class="ArticlePage">
    <ImageSlider/>
    <ArticleContent :content="article.content"/>
    <AdSlider/>
    <CommentForm :article-id="article.id"/>
  </div>
</template>

<script>
import {
  hydrateOnInteraction,
  hydrateNever,
  hydrateWhenIdle,
  hydrateWhenVisible,
} from 'vue-lazy-hydration';

export default {
  components: {
    AdSlider: hydrateWhenVisible(
      () => import('./AdSlider.vue'),
      // Optional.
      { observerOptions: { rootMargin: '100px' } },
    ),
    ArticleContent: hydrateNever(() => import('./ArticleContent.vue')),
    CommentForm: hydrateOnInteraction(
      () => import('./CommentForm.vue'),
      // `focus` is the default event.
      { event: 'focus' },
    ),
    ImageSlider: hydrateWhenIdle(() => import('./ImageSlider.vue')),
  },
  // ...
};
</script>

Benchmarks

Without lazy hydration

Without lazy hydration.

With lazy hydration

With lazy hydration.

Caveats

This plugin will not work as advertised if you're not using it in combination with SSR. Although it should work with every pre-rendering approach (like Prerender SPA Plugin, Gridsome, ...) I've only tested it with Nuxt.js so far.

Upgrade v1.x to v2.x

Breaking changes:

  • ssr-only was renamed to never (as in "Hydrate this? Never!").
-<LazyHydrate ssr-only>
+<LazyHydrate never>
   <ArticleContent/>
 </LazyHydrate>
  • Specyfing ignored-props on Import Wrappers is not necessary anymore.
 components: {
-  ArticleContent: hydrateNever(() => import('./ArticleContent.vue'), { ignoredProps: ['content'] }),
+  ArticleContent: hydrateNever(() => import('./ArticleContent.vue')),
 }

Articles

Credits

The code of the v1 version of this package was based on a similar package created by Rahul Kadyan.

Testing

Because the core functionality of vue-lazy-hydration heavily relies on browser APIs like IntersectionObserver and requestIdleCallback(), it is tough to write meaningful unit tests without having to write numerous mocks. Because of that, we mostly use integration tests and some performance benchmarks to test the functionality of this package.

Integration tests

Execute the following commands to run the integration tests:

npm run test:integration:build
npm run test:integration

Performance tests

Execute the following commands to run the performance benchmark:

npm run test:perf:build
npm run test:perf

About

Author

Markus Oberlehner
Website: https://markus.oberlehner.net
Twitter: https://twitter.com/MaOberlehner
PayPal.me: https://paypal.me/maoberlehner
Patreon: https://www.patreon.com/maoberlehner

License

MIT

More Repositories

1

vuex-map-fields

Enable two-way data binding for form fields saved in a Vuex store
JavaScript
1,415
star
2

node-sass-magic-importer

Custom node-sass importer for selector specific imports, module importing, globbing support and importing files only once.
TypeScript
293
star
3

how-to-structure-a-complex-vuex-store

This is an example project for the following article: https://markus.oberlehner.net/blog/how-to-structure-a-complex-vuex-store/
Vue
187
star
4

perfundo

a pure CSS lightbox (now with JavaScript).
JavaScript
183
star
5

transition-to-height-auto-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/transition-to-height-auto-with-vue/
Vue
105
star
6

goodbye-webpack-building-vue-applications-without-webpack

This is an example project for the following article: https://markus.oberlehner.net/blog/goodbye-webpack-building-vue-applications-without-webpack/
JavaScript
77
star
7

distributed-vue-applications-loading-components-via-http

This is an example project for the following article: https://markus.oberlehner.net/blog/distributed-vue-applications-loading-components-via-http/
JavaScript
49
star
8

dynamic-vue-layout-components

This is an example project for the following article: https://markus.oberlehner.net/blog/dynamic-vue-layout-components/
Vue
43
star
9

eleventy-preact

Build progressively enhanced websites wit Eleventy and Preact
JavaScript
42
star
10

advanced-vue-component-composition-with-container-components

This is an example project for the following article: https://markus.oberlehner.net/blog/advanced-vue-component-composition-with-container-components/
JavaScript
42
star
11

vue-router-page-transitions

This is an example project for the following article: https://markus.oberlehner.net/blog/vue-router-page-transitions/
Vue
34
star
12

setting-up-a-vue-project-with-webpack-4-and-babel-7

This is an example project for the following article: https://markus.oberlehner.net/blog/setting-up-a-vue-project-with-webpack-4-and-babel-7/
Vue
33
star
13

building-a-modal-dialog-with-vue-and-vuex

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-modal-dialog-with-vue-and-vuex/
Vue
30
star
14

storyblok-migrate

Storyblok schema migrations
JavaScript
30
star
15

building-renderless-components-to-handle-crud-operations-in-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-renderless-components-to-handle-crud-operations-in-vue/
Vue
29
star
16

how-to-pre-render-vue-powered-websites-with-webpack

This is an example project for the following article: https://markus.oberlehner.net/blog/how-to-pre-render-vue-powered-websites-with-webpack/
JavaScript
25
star
17

skeleton-loading-animation-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/skeleton-loading-animation-with-vue/
Vue
24
star
18

using-the-google-maps-api-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/using-the-google-maps-api-with-vue/
JavaScript
23
star
19

well-composed-frontend

This is an example app to show how to build a flexible and modular frontend. The main technologies used are Vue together with Vuex and Nuxt.js in combination with the node-sass-magic-importer.
JavaScript
22
star
20

vue-application-structure-and-css-architecture

This is an example project for the following article: https://markus.oberlehner.net/blog/vue-application-structure-and-css-architecture/
Vue
21
star
21

collectorium

pure CSS tabs.
JavaScript
21
star
22

talk-vitest-cypress

TypeScript
21
star
23

combining-graphql-and-vuex

This is an example project for the following article: https://markus.oberlehner.net/blog/combining-graphql-and-vuex/
JavaScript
19
star
24

implementing-a-simple-middleware-with-vue-router

This is an example project for the following article: https://markus.oberlehner.net/blog/implementing-a-simple-middleware-with-vue-router/
JavaScript
19
star
25

building-a-date-input-component-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-date-input-component-with-vue/
JavaScript
18
star
26

how-to-drastically-reduce-estimated-input-latency-and-time-to-interactive-of-ssr-vue-applications

This is an example project for the following article: https://markus.oberlehner.net/blog/how-to-drastically-reduce-estimated-input-latency-and-time-to-interactive-of-ssr-vue-applications/
Vue
18
star
27

replicating-the-twitter-tweet-box-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/replicating-the-twitter-tweet-box-with-vue/
Vue
17
star
28

talk-good-tests

TypeScript
16
star
29

book-good-tests-app

TypeScript
16
star
30

lazy-load-vue-components-when-they-become-visible

This is an example project for the following article: https://markus.oberlehner.net/blog/lazy-load-vue-components-when-they-become-visible/
Vue
16
star
31

distributed-vue-applications-pushing-content-and-component-updates-to-the-client

This is an example project for the following article: https://markus.oberlehner.net/blog/distributed-vue-applications-pushing-content-and-component-updates-to-the-client/
Vue
13
star
32

visual-regression-tests-for-vue-applications-with-jest-and-puppeteer

This is an example project for the following article: https://markus.oberlehner.net/blog/visual-regression-tests-for-vue-applications-with-jest-and-puppeteer/
JavaScript
12
star
33

setting-up-tailwind-css-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/setting-up-tailwind-css-with-vue/
JavaScript
12
star
34

css-selector-extract

Extract certain CSS selectors form (S)CSS code.
JavaScript
11
star
35

building-a-simple-content-slider-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-simple-content-slider-with-vue/
Vue
11
star
36

node-sass-package-importer

Custom importer for node-sass to import packages from the `node_modules` directory.
JavaScript
11
star
37

implementing-an-authentication-flow-with-passport-and-netlify-functions

This is an example project for the following article: https://markus.oberlehner.net/blog/implementing-an-authentication-flow-with-passport-and-netlify-functions/
JavaScript
10
star
38

building-a-parallax-scrolling-effect-component-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-parallax-scrolling-effect-component-with-vue/
Vue
10
star
39

using-location-data-with-vue-and-open-street-map

This is an example project for the following article: https://markus.oberlehner.net/blog/using-location-data-with-vue-and-open-street-map/
Vue
9
star
40

vue-3-composition-api-data-fetching-composable

Vue
9
star
41

building-custom-multi-option-form-components-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-custom-multi-option-form-components-with-vue/
Vue
9
star
42

lazy-loading-responsive-images-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/lazy-loading-responsive-images-with-vue/
Vue
9
star
43

testing-vuex-powered-vue-components-with-jest

This is an example project for the following article: https://markus.oberlehner.net/blog/testing-vuex-powered-vue-components-with-jest/
JavaScript
8
star
44

reusable-functional-vue-components-with-tailwind-css

This is an example project for the following article: https://markus.oberlehner.net/blog/reusable-functional-vue-components-with-tailwind-css/
Vue
8
star
45

building-a-pre-rendered-website-with-nuxt-and-storyblok

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-pre-rendered-website-with-nuxt-and-storyblok/
Vue
7
star
46

storyblok-meta-image

A Storyblok field-type plugin which provides an image field with meta data like width, height, alt and title texts and the images dominant color attached to it
Vue
6
star
47

storyblok-cloudinary-assets

Storyblok Cloudinary Assets is a Storyblok field-type plugin which makes it possible to use Cloudinary for managing assets in the headless CMS Storyblok
Vue
6
star
48

vue-form-validation-with-vuelidate

This is an example project for the following article: https://markus.oberlehner.net/blog/vue-form-validation-with-vuelidate/
JavaScript
6
star
49

building-a-website-with-vue-the-storyblok-visual-editor-and-netlify

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-website-with-vue-the-storyblok-visual-editor-and-netlify/
Vue
6
star
50

building-landing-pages-with-vue-and-a-headless-cms

This is an example project for the following article: https://markus.oberlehner.net/blog/building-landing-pages-with-vue-and-a-headless-cms/
Vue
6
star
51

vue-single-file-component-factory

JavaScript
5
star
52

loading-comparison

Compare the loading performance of two or more websites or website variations.
JavaScript
5
star
53

building-a-simple-ken-burns-slider-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-simple-ken-burns-slider-with-vue/
Vue
5
star
54

abomination-a-concept-for-a-static-html-dynamic-javascript-hybrid-application

This is an example project for the following article: https://markus.oberlehner.net/blog/abomination-a-concept-for-a-static-html-dynamic-javascript-hybrid-application/
Vue
5
star
55

vue-functional-css-module-components

This is an example project for the following article: https://markus.oberlehner.net/blog/vue-functional-base-components-powered-by-css-modules/
JavaScript
5
star
56

runtime-bundler

Runtime Bundling of JavaScript Assets
JavaScript
4
star
57

talk-git-master-class

This is an example repository for my talk Git Master Class
4
star
58

building-a-static-site-with-storyblok-and-gridsome

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-static-site-with-storyblok-and-gridsome/
Vue
4
star
59

automatic-spa-ftp-deploys-with-circleci

This is an example project for the following article: https://markus.oberlehner.net/blog/automatic-spa-ftp-deploys-with-circleci/
Vue
4
star
60

route-model-binding-with-vue-and-vuex

This is an example repository created for the following blog article: https://markus.oberlehner.net/blog/route-model-binding-with-vue-and-vuex
JavaScript
4
star
61

typescript-database-abstraction

This is an example repository created for the following blog article: https://markus.oberlehner.net/blog/2017/03/building-a-simple-database-abstraction-with-typescript/
TypeScript
4
star
62

acceptance-testing-with-nightwatch-cucumber-and-browserstack

This is an example repository created for the following blog article: https://markus.oberlehner.net/blog/acceptance-testing-with-nightwatch-and-cucumber-setup/
JavaScript
4
star
63

article-testing-dsl

JavaScript
4
star
64

node-sass-glob-importer

Custom node-sass importer to allow you to use glob syntax in imports.
JavaScript
3
star
65

building-a-store-finder-with-storyblok-and-vue

Vue
3
star
66

vue-xstate-experiments

JavaScript
3
star
67

node-sass-filter-importer

Filter certain elements from SCSS code.
JavaScript
3
star
68

building-a-renderless-recaptcha-v3-form-component-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-renderless-recaptcha-v3-form-component-with-vue/
JavaScript
3
star
69

how-to-use-graphql-with-vue-apollo-components-and-netlify-functions

This is an example project for the following article: https://markus.oberlehner.net/blog/how-to-use-graphql-with-vue-apollo-components-and-netlify-functions/
JavaScript
3
star
70

crazy-powerful-nightwatch-cucumber-step-definitions

This is an example project for the following article: https://markus.oberlehner.net/blog/crazy-powerful-nightwatch-cucumber-step-definitions/
JavaScript
3
star
71

creating-pdf-invoices-with-airtable-vue-and-puppeteer

This is an example project for the following article: https://markus.oberlehner.net/blog/creating-pdf-invoices-with-airtable-vue-and-puppeteer/
Vue
3
star
72

building-a-serverless-comment-system-with-netlify-functions-storyblok-and-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-a-serverless-comment-system-with-netlify-functions-storyblok-and-vue/
JavaScript
3
star
73

storyblok-augmented-image

Vue
3
star
74

storyblok-list

Vue
2
star
75

visual-regression-testing-with-nightwatch-and-cucumber

JavaScript
2
star
76

node-sass-selector-importer

Import only certain CSS selectors form a file.
JavaScript
2
star
77

talk-npm-scripts

Warum npm scripts (manchmal) voll OK sind.
HTML
2
star
78

building-a-custom-storyblok-field-type-plugin-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/building-custom-storyblok-field-type-plugins-with-vue/
Vue
2
star
79

mindstorms-nxt-node

This is an example project for the following article: https://markus.oberlehner.net/blog/controlling-the-lego-mindstorms-nxt-with-nodejs-its-alive/
JavaScript
2
star
80

article-nuxt-sqlite-vector

TypeScript
2
star
81

headless-cms-nuxt

This is an example project for exploring how to build headless CMS powered websites with Nuxt.js.
JavaScript
1
star
82

unit-testing-vue-components-with-ava

This is an example repository created for the following blog article: https://markus.oberlehner.net/blog/unit-testing-vue-single-file-components-with-ava/
JavaScript
1
star
83

dynamically-loading-svg-icons-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/dynamically-loading-svg-icons-with-vue/
JavaScript
1
star
84

good-vue-tests-q-and-a

1
star
85

vue-style-provider

Vue
1
star
86

network-stubs-and-timers-with-nightwatch-and-cucumber

This is an example project for the following article: https://markus.oberlehner.net/blog/network-stubs-and-timers-with-nightwatch-and-cucumber
JavaScript
1
star
87

implementing-a-gdpr-consent-workflow-with-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/implementing-a-gdpr-consent-workflow-with-vue/
Vue
1
star
88

vue-nested-default-props

Vue
1
star
89

automated-acceptance-testing-with-cypress-and-vue

This is an example project for the following article: https://markus.oberlehner.net/blog/automated-acceptance-testing-with-cypress-and-vue-setup
JavaScript
1
star