diff --git a/404.html b/404.html index 838b56f2d8..735b9e43a2 100644 --- a/404.html +++ b/404.html @@ -16,7 +16,7 @@
- + \ No newline at end of file diff --git a/assets/components_weak-hardware-overlay.md.OARp2jlg.js b/assets/components_weak-hardware-overlay.md.DS4AzeXN.js similarity index 97% rename from assets/components_weak-hardware-overlay.md.OARp2jlg.js rename to assets/components_weak-hardware-overlay.md.DS4AzeXN.js index f2621761c6..abec2d38eb 100644 --- a/assets/components_weak-hardware-overlay.md.OARp2jlg.js +++ b/assets/components_weak-hardware-overlay.md.DS4AzeXN.js @@ -1,4 +1,4 @@ -import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"WeakHardwareOverlay","description":"","frontmatter":{"title":"WeakHardwareOverlay"},"headers":[],"relativePath":"components/weak-hardware-overlay.md","filePath":"components/weak-hardware-overlay.md"}'),k={name:"components/weak-hardware-overlay.md"},r={id:"frontmatter-title",tabindex:"-1"};function E(a,s,d,o,g,c){return h(),t("div",null,[i("h1",r,[e(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

The WeakHardwareOverlay is used in components that are affected by the BoosterLayer event Weak Hardware. (Example: Component requires the execution of mounted for functionality.)

INFO

The performance issue event occurs when initialization determines that the client is overloaded with execution and the user has confirmed the .nuxt-booster-button-init-reduced-view button in the BoosterLayer.

Learn more about BoosterLayer interactions)

Basically, the overlay is used to make content visible when the Weak Hardware has occurred, if this does not occur, the overlay is not visible.

It is recommended to include an interaction element in the overlay that allows the user to switch to the normal state. For this the interaction element must get the Style Class .nuxt-booster-button-init-app and reacts on click with the initialization of the app.

Example

Example of defining a custom WeakHardwareOverlay component and placing it in a target component that is affected by the Weak Hardware event.

Customize Overlay

vue
<template>
+import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"WeakHardwareOverlay","description":"","frontmatter":{"title":"WeakHardwareOverlay"},"headers":[],"relativePath":"components/weak-hardware-overlay.md","filePath":"components/weak-hardware-overlay.md"}'),k={name:"components/weak-hardware-overlay.md"},r={id:"frontmatter-title",tabindex:"-1"};function E(a,s,d,o,c,y){return h(),t("div",null,[i("h1",r,[e(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

The WeakHardwareOverlay is used in components that are affected by the BoosterLayer event Weak Hardware. (Example: Component requires the execution of mounted for functionality.)

INFO

The performance issue event occurs when initialization determines that the client is overloaded with execution and the user has confirmed the .nuxt-booster-button-init-reduced-view button in the BoosterLayer.

Learn more about BoosterLayer interactions)

Basically, the overlay is used to make content visible when the Weak Hardware has occurred, if this does not occur, the overlay is not visible.

It is recommended to include an interaction element in the overlay that allows the user to switch to the normal state. For this the interaction element must get the Style Class .nuxt-booster-button-init-app and reacts on click with the initialization of the app.

Example

Example of defining a custom WeakHardwareOverlay component and placing it in a target component that is affected by the Weak Hardware event.

Customize Overlay

vue
<template>
   <booster-weak-hardware-overlay>
     To improve your experience, extensive features have been disabled.<br>
     <button class="nuxt-booster-button-init-app">
@@ -22,7 +22,7 @@ import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.
   background: rgb(0 0 0 / 60%);
   backdrop-filter: blur(em(2px));
 }
-</style>

Usage Overlay

vue
<template>
+</style>

Usage Overlay

vue
<template>
   <div>
     <div ref="player" />
     <weak-hardware-overlay />
diff --git a/assets/components_weak-hardware-overlay.md.OARp2jlg.lean.js b/assets/components_weak-hardware-overlay.md.DS4AzeXN.lean.js
similarity index 97%
rename from assets/components_weak-hardware-overlay.md.OARp2jlg.lean.js
rename to assets/components_weak-hardware-overlay.md.DS4AzeXN.lean.js
index f2621761c6..abec2d38eb 100644
--- a/assets/components_weak-hardware-overlay.md.OARp2jlg.lean.js
+++ b/assets/components_weak-hardware-overlay.md.DS4AzeXN.lean.js
@@ -1,4 +1,4 @@
-import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"WeakHardwareOverlay","description":"","frontmatter":{"title":"WeakHardwareOverlay"},"headers":[],"relativePath":"components/weak-hardware-overlay.md","filePath":"components/weak-hardware-overlay.md"}'),k={name:"components/weak-hardware-overlay.md"},r={id:"frontmatter-title",tabindex:"-1"};function E(a,s,d,o,g,c){return h(),t("div",null,[i("h1",r,[e(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

The WeakHardwareOverlay is used in components that are affected by the BoosterLayer event Weak Hardware. (Example: Component requires the execution of mounted for functionality.)

INFO

The performance issue event occurs when initialization determines that the client is overloaded with execution and the user has confirmed the .nuxt-booster-button-init-reduced-view button in the BoosterLayer.

Learn more about BoosterLayer interactions)

Basically, the overlay is used to make content visible when the Weak Hardware has occurred, if this does not occur, the overlay is not visible.

It is recommended to include an interaction element in the overlay that allows the user to switch to the normal state. For this the interaction element must get the Style Class .nuxt-booster-button-init-app and reacts on click with the initialization of the app.

Example

Example of defining a custom WeakHardwareOverlay component and placing it in a target component that is affected by the Weak Hardware event.

Customize Overlay

vue
<template>
+import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"WeakHardwareOverlay","description":"","frontmatter":{"title":"WeakHardwareOverlay"},"headers":[],"relativePath":"components/weak-hardware-overlay.md","filePath":"components/weak-hardware-overlay.md"}'),k={name:"components/weak-hardware-overlay.md"},r={id:"frontmatter-title",tabindex:"-1"};function E(a,s,d,o,c,y){return h(),t("div",null,[i("h1",r,[e(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

The WeakHardwareOverlay is used in components that are affected by the BoosterLayer event Weak Hardware. (Example: Component requires the execution of mounted for functionality.)

INFO

The performance issue event occurs when initialization determines that the client is overloaded with execution and the user has confirmed the .nuxt-booster-button-init-reduced-view button in the BoosterLayer.

Learn more about BoosterLayer interactions)

Basically, the overlay is used to make content visible when the Weak Hardware has occurred, if this does not occur, the overlay is not visible.

It is recommended to include an interaction element in the overlay that allows the user to switch to the normal state. For this the interaction element must get the Style Class .nuxt-booster-button-init-app and reacts on click with the initialization of the app.

Example

Example of defining a custom WeakHardwareOverlay component and placing it in a target component that is affected by the Weak Hardware event.

Customize Overlay

vue
<template>
   <booster-weak-hardware-overlay>
     To improve your experience, extensive features have been disabled.<br>
     <button class="nuxt-booster-button-init-app">
@@ -22,7 +22,7 @@ import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.
   background: rgb(0 0 0 / 60%);
   backdrop-filter: blur(em(2px));
 }
-</style>

Usage Overlay

vue
<template>
+</style>

Usage Overlay

vue
<template>
   <div>
     <div ref="player" />
     <weak-hardware-overlay />
diff --git a/assets/guide_setup.md.CEfJ7p-4.js b/assets/guide_setup.md.D6N-RRvC.js
similarity index 97%
rename from assets/guide_setup.md.CEfJ7p-4.js
rename to assets/guide_setup.md.D6N-RRvC.js
index 64b8cc51cb..dac3cdf776 100644
--- a/assets/guide_setup.md.CEfJ7p-4.js
+++ b/assets/guide_setup.md.D6N-RRvC.js
@@ -1,10 +1,10 @@
-import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.BTPXxG66.js";const F=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"guide/setup.md","filePath":"guide/setup.md"}'),e={name:"guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,o,y){return k(),l("div",null,[i("h1",E,[t(p(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=h(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster
bash
npm install nuxt-booster

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
+import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.BTPXxG66.js";const F=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"guide/setup.md","filePath":"guide/setup.md"}'),e={name:"guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,o,y){return k(),l("div",null,[i("h1",E,[t(p(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=h(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster
bash
npm install nuxt-booster

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
   domains: ['img.youtube.com', 'i.vimeocdn.com'],
   alias: {
     youtube: 'https://img.youtube.com',
     vimeo: 'https://i.vimeocdn.com',
   }
-}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
+}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
   modules: [
     'nuxt-booster'
   ],
diff --git a/assets/guide_setup.md.CEfJ7p-4.lean.js b/assets/guide_setup.md.D6N-RRvC.lean.js
similarity index 97%
rename from assets/guide_setup.md.CEfJ7p-4.lean.js
rename to assets/guide_setup.md.D6N-RRvC.lean.js
index 64b8cc51cb..dac3cdf776 100644
--- a/assets/guide_setup.md.CEfJ7p-4.lean.js
+++ b/assets/guide_setup.md.D6N-RRvC.lean.js
@@ -1,10 +1,10 @@
-import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.BTPXxG66.js";const F=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"guide/setup.md","filePath":"guide/setup.md"}'),e={name:"guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,o,y){return k(),l("div",null,[i("h1",E,[t(p(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=h(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster
bash
npm install nuxt-booster

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
+import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.BTPXxG66.js";const F=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"guide/setup.md","filePath":"guide/setup.md"}'),e={name:"guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,o,y){return k(),l("div",null,[i("h1",E,[t(p(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=h(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster
bash
npm install nuxt-booster

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
   domains: ['img.youtube.com', 'i.vimeocdn.com'],
   alias: {
     youtube: 'https://img.youtube.com',
     vimeo: 'https://i.vimeocdn.com',
   }
-}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
+}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
   modules: [
     'nuxt-booster'
   ],
diff --git a/assets/v2_guide_caveats.md.DSFfA9pw.js b/assets/v2_guide_caveats.md.Di9i8oN-.js
similarity index 97%
rename from assets/v2_guide_caveats.md.DSFfA9pw.js
rename to assets/v2_guide_caveats.md.Di9i8oN-.js
index 047fa8b099..a31a4dc030 100644
--- a/assets/v2_guide_caveats.md.DSFfA9pw.js
+++ b/assets/v2_guide_caveats.md.Di9i8oN-.js
@@ -1,4 +1,4 @@
-import{_ as n,c as e,j as i,a as t,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"Caveats","description":"","frontmatter":{"title":"Caveats"},"headers":[],"relativePath":"v2/guide/caveats.md","filePath":"v2/guide/caveats.md"}'),k={name:"v2/guide/caveats.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,o,c,g){return h(),e("div",null,[i("h1",E,[t(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

v-font and custom head

When a v-font directive is called in a component with a custom head, the directive specific head settings must be applied in the head.

The method this.$booster.head(headAddition) is provided, it queries the required head settings and returns them.

By passing the headAddition argument, additional head settings can be applied.

WARNING

$booster.head() is only available in vue component scope.

Example

html
<template>
+import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"Caveats","description":"","frontmatter":{"title":"Caveats"},"headers":[],"relativePath":"v2/guide/caveats.md","filePath":"v2/guide/caveats.md"}'),k={name:"v2/guide/caveats.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,o,c,g){return h(),t("div",null,[i("h1",E,[e(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

v-font and custom head

When a v-font directive is called in a component with a custom head, the directive specific head settings must be applied in the head.

The method this.$booster.head(headAddition) is provided, it queries the required head settings and returns them.

By passing the headAddition argument, additional head settings can be applied.

WARNING

$booster.head() is only available in vue component scope.

Example

html
<template>
   <span v-font="$getFont(…)"></span>
 </template>
 
@@ -17,7 +17,7 @@ import{_ as n,c as e,j as i,a as t,t as l,U as p,o as h}from"./chunks/framework.
       });
     }
   }
-</script>

Issues

Browser compatibility

You can use nuxt-booster with Internet Explorer 11 browser.

INFO

Note that there is no optimization based on preloads in IE 11.

You need the following polyfills:

The PostCSS Plugin postcss-object-fit-images and following build.transpile entries for @nuxt/image:

  • @nuxt/image
  • image-meta

For the polyfills, it is recommended to integrate them as a plugin, polyfills loading must follow a specific order.

You can see a example with live demo at Nuxt Booster Example.

Example

js
async function polyfills (){
+</script>

Issues

Browser compatibility

You can use nuxt-booster with Internet Explorer 11 browser.

INFO

Note that there is no optimization based on preloads in IE 11.

You need the following polyfills:

The PostCSS Plugin postcss-object-fit-images and following build.transpile entries for @nuxt/image:

  • @nuxt/image
  • image-meta

For the polyfills, it is recommended to integrate them as a plugin, polyfills loading must follow a specific order.

You can see a example with live demo at Nuxt Booster Example.

Example

js
async function polyfills (){
 
   if (!('IntersectionObserver' in global)) {
     await import('intersection-observer');
@@ -34,7 +34,7 @@ import{_ as n,c as e,j as i,a as t,t as l,U as p,o as h}from"./chunks/framework.
 
 }
 
-polyfills ();

js
{
+polyfills ();

js
{
   build: {
     
     transpile: ['@nuxt/image', 'image-meta'],
diff --git a/assets/v2_guide_caveats.md.DSFfA9pw.lean.js b/assets/v2_guide_caveats.md.Di9i8oN-.lean.js
similarity index 97%
rename from assets/v2_guide_caveats.md.DSFfA9pw.lean.js
rename to assets/v2_guide_caveats.md.Di9i8oN-.lean.js
index 047fa8b099..a31a4dc030 100644
--- a/assets/v2_guide_caveats.md.DSFfA9pw.lean.js
+++ b/assets/v2_guide_caveats.md.Di9i8oN-.lean.js
@@ -1,4 +1,4 @@
-import{_ as n,c as e,j as i,a as t,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"Caveats","description":"","frontmatter":{"title":"Caveats"},"headers":[],"relativePath":"v2/guide/caveats.md","filePath":"v2/guide/caveats.md"}'),k={name:"v2/guide/caveats.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,o,c,g){return h(),e("div",null,[i("h1",E,[t(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

v-font and custom head

When a v-font directive is called in a component with a custom head, the directive specific head settings must be applied in the head.

The method this.$booster.head(headAddition) is provided, it queries the required head settings and returns them.

By passing the headAddition argument, additional head settings can be applied.

WARNING

$booster.head() is only available in vue component scope.

Example

html
<template>
+import{_ as n,c as t,j as i,a as e,t as l,U as p,o as h}from"./chunks/framework.BTPXxG66.js";const u=JSON.parse('{"title":"Caveats","description":"","frontmatter":{"title":"Caveats"},"headers":[],"relativePath":"v2/guide/caveats.md","filePath":"v2/guide/caveats.md"}'),k={name:"v2/guide/caveats.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,o,c,g){return h(),t("div",null,[i("h1",E,[e(l(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=p(`

v-font and custom head

When a v-font directive is called in a component with a custom head, the directive specific head settings must be applied in the head.

The method this.$booster.head(headAddition) is provided, it queries the required head settings and returns them.

By passing the headAddition argument, additional head settings can be applied.

WARNING

$booster.head() is only available in vue component scope.

Example

html
<template>
   <span v-font="$getFont(…)"></span>
 </template>
 
@@ -17,7 +17,7 @@ import{_ as n,c as e,j as i,a as t,t as l,U as p,o as h}from"./chunks/framework.
       });
     }
   }
-</script>

Issues

Browser compatibility

You can use nuxt-booster with Internet Explorer 11 browser.

INFO

Note that there is no optimization based on preloads in IE 11.

You need the following polyfills:

The PostCSS Plugin postcss-object-fit-images and following build.transpile entries for @nuxt/image:

  • @nuxt/image
  • image-meta

For the polyfills, it is recommended to integrate them as a plugin, polyfills loading must follow a specific order.

You can see a example with live demo at Nuxt Booster Example.

Example

js
async function polyfills (){
+</script>

Issues

Browser compatibility

You can use nuxt-booster with Internet Explorer 11 browser.

INFO

Note that there is no optimization based on preloads in IE 11.

You need the following polyfills:

The PostCSS Plugin postcss-object-fit-images and following build.transpile entries for @nuxt/image:

  • @nuxt/image
  • image-meta

For the polyfills, it is recommended to integrate them as a plugin, polyfills loading must follow a specific order.

You can see a example with live demo at Nuxt Booster Example.

Example

js
async function polyfills (){
 
   if (!('IntersectionObserver' in global)) {
     await import('intersection-observer');
@@ -34,7 +34,7 @@ import{_ as n,c as e,j as i,a as t,t as l,U as p,o as h}from"./chunks/framework.
 
 }
 
-polyfills ();

js
{
+polyfills ();

js
{
   build: {
     
     transpile: ['@nuxt/image', 'image-meta'],
diff --git a/assets/v2_guide_setup.md.4xibyHQY.js b/assets/v2_guide_setup.md.CZKcSKmb.js
similarity index 96%
rename from assets/v2_guide_setup.md.4xibyHQY.js
rename to assets/v2_guide_setup.md.CZKcSKmb.js
index bb20d7bfc7..8ce1042040 100644
--- a/assets/v2_guide_setup.md.4xibyHQY.js
+++ b/assets/v2_guide_setup.md.CZKcSKmb.js
@@ -1,10 +1,10 @@
-import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.BTPXxG66.js";const c=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"v2/guide/setup.md","filePath":"v2/guide/setup.md"}'),e={name:"v2/guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,y,o){return k(),l("div",null,[i("h1",E,[t(p(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=h(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster@2
bash
npm install nuxt-booster@2

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
+import{_ as n,c as l,j as i,a as p,t as h,U as t,o as k}from"./chunks/framework.BTPXxG66.js";const F=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"v2/guide/setup.md","filePath":"v2/guide/setup.md"}'),e={name:"v2/guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,y,o){return k(),l("div",null,[i("h1",E,[p(h(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=t(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster@2
bash
npm install nuxt-booster@2

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
   domains: ['img.youtube.com', 'i.vimeocdn.com'],
   alias: {
     youtube: 'https://img.youtube.com',
     vimeo: 'https://i.vimeocdn.com',
   }
-}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
+}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
   modules: [
     'nuxt-booster'
   ],
@@ -98,4 +98,4 @@ import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.
       vimeo: 'https://i.vimeocdn.com',
     }
   }
-}

See module options.

`,13))])}const C=n(e,[["render",r]]);export{c as __pageData,C as default}; +}

See module options.

`,13))])}const C=n(e,[["render",r]]);export{F as __pageData,C as default}; diff --git a/assets/v2_guide_setup.md.4xibyHQY.lean.js b/assets/v2_guide_setup.md.CZKcSKmb.lean.js similarity index 96% rename from assets/v2_guide_setup.md.4xibyHQY.lean.js rename to assets/v2_guide_setup.md.CZKcSKmb.lean.js index bb20d7bfc7..8ce1042040 100644 --- a/assets/v2_guide_setup.md.4xibyHQY.lean.js +++ b/assets/v2_guide_setup.md.CZKcSKmb.lean.js @@ -1,10 +1,10 @@ -import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.BTPXxG66.js";const c=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"v2/guide/setup.md","filePath":"v2/guide/setup.md"}'),e={name:"v2/guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,y,o){return k(),l("div",null,[i("h1",E,[t(p(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=h(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster@2
bash
npm install nuxt-booster@2

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
+import{_ as n,c as l,j as i,a as p,t as h,U as t,o as k}from"./chunks/framework.BTPXxG66.js";const F=JSON.parse('{"title":"Setup","description":"","frontmatter":{"title":"Setup"},"headers":[],"relativePath":"v2/guide/setup.md","filePath":"v2/guide/setup.md"}'),e={name:"v2/guide/setup.md"},E={id:"frontmatter-title",tabindex:"-1"};function r(a,s,d,g,y,o){return k(),l("div",null,[i("h1",E,[p(h(a.$frontmatter.title)+" ",1),s[0]||(s[0]=i("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{$frontmatter.title}}"'},"​",-1))]),s[1]||(s[1]=t(`

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster@2
bash
npm install nuxt-booster@2

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
   domains: ['img.youtube.com', 'i.vimeocdn.com'],
   alias: {
     youtube: 'https://img.youtube.com',
     vimeo: 'https://i.vimeocdn.com',
   }
-}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
+}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
   modules: [
     'nuxt-booster'
   ],
@@ -98,4 +98,4 @@ import{_ as n,c as l,j as i,a as t,t as p,U as h,o as k}from"./chunks/framework.
       vimeo: 'https://i.vimeocdn.com',
     }
   }
-}

See module options.

`,13))])}const C=n(e,[["render",r]]);export{c as __pageData,C as default}; +}

See module options.

`,13))])}const C=n(e,[["render",r]]);export{F as __pageData,C as default}; diff --git a/components/booster-iframe.html b/components/booster-iframe.html index 407d01af61..900377f445 100644 --- a/components/booster-iframe.html +++ b/components/booster-iframe.html @@ -38,7 +38,7 @@ @load="console.log('Iframe Loaded!')" @enter="console.log('Iframe enter viewport!')" />
NameDescription
loadTriggered when Iframe has finished loading.
enterTriggered when component has reached the viewport.
- + \ No newline at end of file diff --git a/components/booster-image.html b/components/booster-image.html index a97e04782b..a880bc2e10 100644 --- a/components/booster-image.html +++ b/components/booster-image.html @@ -83,7 +83,7 @@ }

Learn more about modifiers:

preset

  • Type: Object

If a preset is set on a source, the globally defined one is ignored.

This means that a separate preset can be specified for each source.

Learn more about preset:

provider

  • Type: String

If a provider is set on a source, the globally defined one is ignored.

This means that a separate provider can be specified for each source.

Learn more about provider:

densities

  • Type: String
    • Default: 'x1 x2'

If a densities is set on a source, the globally defined one is ignored.

Learn more about densities:

alt

  • Type: String

Image alternative Text.

MDN - HTMLImageElement.alt

title

  • Type: String

Image Title.

MDN - HTMLElement.title

crossorigin

  • Type: String, Boolean

If not set, the global crossorigin is used this.$booster.crossorigin.

Learn more about crossorigin option

MDN - HTML.Attributes.crossorigin

critical

  • Type: Boolean
    • Default: $parent.isCritical

Set component as critical component.

Learn more about critical components

Events

html
<booster-image 
   @load="console.log('Image Loaded!')" 
 />
NameDescription
loadTriggered when the image resource has been completely loaded.
- + \ No newline at end of file diff --git a/components/booster-layer.html b/components/booster-layer.html index 71100ef4c3..869761a72d 100644 --- a/components/booster-layer.html +++ b/components/booster-layer.html @@ -75,7 +75,7 @@ </button> </div> </booster-layer>

Force App initialization

Set the global variable __NUXT_BOOSTER_AUTO_INIT__ to true to force the initialization of the app.

VariableTypeDescriptionDefault
__NUXT_BOOSTER_AUTO_INIT__BooleanIf set, initialisation continues after the javascript has been fully loaded.false
- + \ No newline at end of file diff --git a/components/booster-picture.html b/components/booster-picture.html index 9b99faaf9c..b07946f769 100644 --- a/components/booster-picture.html +++ b/components/booster-picture.html @@ -67,7 +67,7 @@ ]

formats

Overrides the pictureFormats property defined in the module options.

Defines the formats that are to be generated and provided as source in the Picture.
Is used to offer the correct image type for the browser.

WARNING

Formats can also be specified as OR condition (jpg|jpeg|png|gif). This is important when using JPGs and PNGs with the same format configuration.

alt

Image alternative Text.

MDN - HTMLImageElement.alt

title

Image Title.

MDN - HTMLElement.title

crossorigin

If not set, the global crossorigin is used this.$booster.crossorigin.

Learn more about crossorigin option

MDN - HTML.Attributes.crossorigin

sortSources

If set, the sources are sorted by the media properties.

This is made possible by sort-css-media-queries.

critical

Set component as critical component.

Learn more about critical components

Events

html
<booster-picture 
   @load="console.log('Loaded!')" 
 />
NameDescription
loadTriggered when the image resource has been completely loaded.
- + \ No newline at end of file diff --git a/components/booster-vimeo.html b/components/booster-vimeo.html index 6555980c98..b371f98795 100644 --- a/components/booster-vimeo.html +++ b/components/booster-vimeo.html @@ -85,7 +85,7 @@ @ready="console.log('Player Ready!')" @playing="console.log('Player Playing!')" />
NameDescription
readyTriggered when Vimeo Player-SDK is completely loaded.
playingTriggered when video is finished loading and playing.
beforePlayerUsed to place elements in the player container (before).
afterPlayerUsed to place elements in the player container (after).
- + \ No newline at end of file diff --git a/components/booster-youtube.html b/components/booster-youtube.html index f1915ae6cc..9a93e21707 100644 --- a/components/booster-youtube.html +++ b/components/booster-youtube.html @@ -77,7 +77,7 @@ @ready="console.log('Player Ready!')" @playing="console.log('Player Playing!')" />
NameDescription
readyTriggered when Youtube-API is completely loaded.
playingTriggered when video is finished loading and playing.
beforePlayerUsed to place elements in the player container (before).
afterPlayerUsed to place elements in the player container (after).
- + \ No newline at end of file diff --git a/components/weak-hardware-overlay.html b/components/weak-hardware-overlay.html index 4debd5e78a..4f69040af1 100644 --- a/components/weak-hardware-overlay.html +++ b/components/weak-hardware-overlay.html @@ -13,12 +13,12 @@ - + -
Skip to content

WeakHardwareOverlay

The WeakHardwareOverlay is used in components that are affected by the BoosterLayer event Weak Hardware. (Example: Component requires the execution of mounted for functionality.)

INFO

The performance issue event occurs when initialization determines that the client is overloaded with execution and the user has confirmed the .nuxt-booster-button-init-reduced-view button in the BoosterLayer.

Learn more about BoosterLayer interactions)

Basically, the overlay is used to make content visible when the Weak Hardware has occurred, if this does not occur, the overlay is not visible.

It is recommended to include an interaction element in the overlay that allows the user to switch to the normal state. For this the interaction element must get the Style Class .nuxt-booster-button-init-app and reacts on click with the initialization of the app.

Example

Example of defining a custom WeakHardwareOverlay component and placing it in a target component that is affected by the Weak Hardware event.

Customize Overlay

vue
<template>
+    
Skip to content

WeakHardwareOverlay

The WeakHardwareOverlay is used in components that are affected by the BoosterLayer event Weak Hardware. (Example: Component requires the execution of mounted for functionality.)

INFO

The performance issue event occurs when initialization determines that the client is overloaded with execution and the user has confirmed the .nuxt-booster-button-init-reduced-view button in the BoosterLayer.

Learn more about BoosterLayer interactions)

Basically, the overlay is used to make content visible when the Weak Hardware has occurred, if this does not occur, the overlay is not visible.

It is recommended to include an interaction element in the overlay that allows the user to switch to the normal state. For this the interaction element must get the Style Class .nuxt-booster-button-init-app and reacts on click with the initialization of the app.

Example

Example of defining a custom WeakHardwareOverlay component and placing it in a target component that is affected by the Weak Hardware event.

Customize Overlay

vue
<template>
   <booster-weak-hardware-overlay>
     To improve your experience, extensive features have been disabled.<br>
     <button class="nuxt-booster-button-init-app">
@@ -42,7 +42,7 @@
   background: rgb(0 0 0 / 60%);
   backdrop-filter: blur(em(2px));
 }
-</style>

Usage Overlay

vue
<template>
+</style>

Usage Overlay

vue
<template>
   <div>
     <div ref="player" />
     <weak-hardware-overlay />
@@ -68,7 +68,7 @@
   backdrop-filter: blur(2px);
 }
 </style>
- + \ No newline at end of file diff --git a/composables/useBoosterComponentObserver.html b/composables/useBoosterComponentObserver.html index aea28ca050..b1a9b6fdcf 100644 --- a/composables/useBoosterComponentObserver.html +++ b/composables/useBoosterComponentObserver.html @@ -30,7 +30,7 @@ delay: 350 }); </script>
- + \ No newline at end of file diff --git a/composables/useBoosterConfig.html b/composables/useBoosterConfig.html index 62c42915b4..4091b2f980 100644 --- a/composables/useBoosterConfig.html +++ b/composables/useBoosterConfig.html @@ -19,7 +19,7 @@
Skip to content

useBoosterConfig

Return

Returns nuxt-booster public runtime options.

Example

js
const $boosterOptions = useBoosterConfig();
- + \ No newline at end of file diff --git a/composables/useBoosterCritical.html b/composables/useBoosterCritical.html index edf0912213..1cb2375008 100644 --- a/composables/useBoosterCritical.html +++ b/composables/useBoosterCritical.html @@ -25,7 +25,7 @@ <script setup> const { isCritical } = useBoosterCritical(); </script> - + \ No newline at end of file diff --git a/composables/useBoosterFont.html b/composables/useBoosterFont.html index 4a818879fd..f6c32f637a 100644 --- a/composables/useBoosterFont.html +++ b/composables/useBoosterFont.html @@ -25,7 +25,7 @@ <script setup> const { $getFont } = useBoosterFonts(); </script> - + \ No newline at end of file diff --git a/composables/useBoosterHead.html b/composables/useBoosterHead.html index 6af02ed9d6..17f51bc030 100644 --- a/composables/useBoosterHead.html +++ b/composables/useBoosterHead.html @@ -19,7 +19,7 @@
Skip to content

⚠️ useBoosterHead

WARNING

useBoosterhead is an internally used composable that is called once in the plugin.

Is required to create and manage a head entry.

- + \ No newline at end of file diff --git a/composables/useBoosterHydrate.html b/composables/useBoosterHydrate.html index 3930f1fe7a..ec1d1737f1 100644 --- a/composables/useBoosterHydrate.html +++ b/composables/useBoosterHydrate.html @@ -33,7 +33,7 @@ hydrate(); } }; - + \ No newline at end of file diff --git a/concept.html b/concept.html index 42a73707ba..1bffb32966 100644 --- a/concept.html +++ b/concept.html @@ -19,7 +19,7 @@
Skip to content

Concept

Current Situation

The loading behavior of webpages based on NuxtJS is designed in such a way that all necessary Javascript resources are preloaded and directly initialized with the initial load of the page. However, this behavior creates a negative impact on the Lighthouse Performance Score (TTI) for larger pages that have an increased initial load of additional resources, such as fonts, images, plugins, modules (@nuxtjs/i18n, ...).

Excursus

The Lighthouse Test is not a tool to make a general statement about the quality of a website programming. Lighthouse rather tries to map a metric for the usability of a page from the user's point of view. This includes accessibility, best practices, SEO and of course performance.

This last point is often misinterpreted by developers. If you want to implement features that increase usability for the user (interactions/more complex animations, ...), this will always have an impact on performance in the Lighthouse Test for larger website projects, as the corresponding Javascript must be loaded for this. Finally, Lighthouse does also not rate the design, but the accessibility (size of click areas, etc.) of a website. You should therefore not ask yourself the following question: "How can I fully optimize my JavaScript to achieve a Lighthouse score of 100/100?". You have to ask yourself much more the question: "What is especially important to a user with low bandwidth or weak hardware on my site?".

The answer to this is relatively simple: the content must be accessible and you must be able to get to the information you need quickly.

No more and no less.

The user doesn't need any fancy slider animations and parallax effects that can only be implemented with certain libraries. Or a softload mechanism to get to more pages in a more elegant and animated way, but which initially needs an increased amount of javascript logic. All he wants is that information is retrievable reasonably fast and he can click through the presence.

Problem

The good news is that the NuxtJS SSR build provides the right foundation. The content is already in the form of HTML and CSS and can be used without Javascript. But what is missing

  • is a fully automated preload logic that allows component and viewport based handling and prioritization of the individual resources (FCP, LCP, CLS)
  • is a logic that enables a perfomance-oriented initialization of the javascript (TTI, TBT)

These two central points are handled by Nuxt Booster and enable a fast and resource-saving loading behavior of the website.

Approach

Over a longer period of time, we analyzed the Google Lighthouse test in more detail and approached the topic with the help of use cases. We did not start with the best case for page content (one image, one font, minimal javascript), but with the worst case (many images, many fonts, large Javascript files, ...). So we avoided to develop only a solution for simple SinglePages. Our claim was much more to create a generalistic, performant solution even with a CMS connection and dynamic component compositions per page. All our thoughts are based on HTTP/2 request prioritization and the lazy hydration approach. Initial resources are prioritized by preload and all further data is reloaded viewport-based.

Insights & Solutions

During the tests, we gained the following insights, which we would like to share with you, but which also allow us to draw conclusions regarding the performance optimization of the initial loading process and which have been incorporated into the Nuxt Booster solution.

Critical Render Path

The critical render path is the core of a high-performance and efficient loading and rendering behavior of a website. It is important that components and resources in the viewport are loaded and executed with priority so that the user can be provided with a functioning page as quickly as possible. A browser is not able to recognize this fully automatically to dynamically adapt the loading behavior. Some attempts have been made in the past to systematically identify the critical render path.However, this has the consequence that every generated page in a virtual browser has to be analyzed in given viewport sizes, which slows down the deployment process and makes it more error-prone. For this reason, we (the developers) will be forced to provide the build process with appropriate hints in the form of a Critical Attribute on the affected component, so that an automated optimization by preloads, lazy hydration, etc. can be performed in response.

Font Loading

Fonts are the great mystery on the Internet. For more complex designs it is not uncommon that more than 6 font files have to be loaded. It would be desirable if there were many more variable fonts, but the reality is usually different. Often, developers are forced to register tons of fonts with different font styles. So it can happen that the website needs a total count of 12 font files, which have to be loaded initially to achieve the right visual result on the whole page.

This is a real performance problem. If you look for solutions, you like to hear

  • don't use WebFonts that have to be loaded
  • use another optimized font
  • reduce the number of used fonts
  • embed the fonts via Base64

You will find some articles about font loading. But most of them are more than 3 years old. Summary: not much happened here. A nice and recommendable list of different strategies can be found at web-font-loading-recipes or comprehensive-webfonts. From this it can be deduced that there is still no universal solution to the problem. However, it is possible to approach the issue very efficiently by using a preload strategy and setting classes accordingly. However, this does not make the handling of the fonts any easier. On the one hand, the preloads have to be defined per page and on the other hand, the CSS in the respective component has to be activated with the corresponding font declaration per class on demand. This is manageable for smaller projects in a 1 person team. But if several people are working in parallel, it can quickly become a nightmare. This will inevitably lead to the fact that the approach will not be accepted by the team and the optimization will be optimized out of the project in the long run.

INFO

A few words about Google Fonts: If possible, the FontFaces should always be included directly as Woff/Woff2 files via inline style. The loading mechanism via external CSS file, as it is the case with Google Fonts, creates an additional network roundtrip, which delays the loading of the actual font files.

The strategy mentioned above makes sense, but is hardly implementable with the current tools. For this reason, we are introducing Directive v-font, which takes care of the outlined behavior in a fully automated way and thus represents a truly relevant solution even on larger projects. Combined with the lazy hydration approach, the relevant fonts can be declared and loaded per component. The preloads are controlled via the critical attribute. With the help of this loading strategy, a FOUT (flash of unstyled text) and CLS can be massively reduced or eliminated. If no javascript is activated on the end device, all fonts are automatically activated via CSS.

Image Loading

For image compression and different image formats, the module nuxt-optimized-images was popularly used in the nuxt world in the past. The downside, however, is that this approach is not particularly CMS and deployment friendly. With each image change, a full build process had to be initiated. For this reason, we use the nuxt-image module, as this takes advantage of a change in NuxtJS as of version 2.13.0. In this version update, the build was split into two separate processes (javascript compilation + page generation). With nuxt-optimized-images the full build process had to be run for every image change. This is no longer the case with nuxt-image. Here only the page generation process is necessary. As a result, deployment times for all content changes can be massively reduced.

We use the module in its complete form. However, we have redeveloped the nuxt-image and nuxt-picture components, as the current version does not fully meet our requirements. For example, we lacked an appropriate preloading and lazy hydration strategy. Although there is a native loading attribute on the image element that allows prioritization, the use for websites with a lot of images is still not optimal, because the distance-from-viewport threshold is still too generous and the loading performance can deteriorate unintentionally. For this we have implemented a corresponding SEO-compliant alternative, which loads the images only when the viewport is reached, but also provides the image sources for search engines via no-script tag. This way all relevant images can be displayed even if Javascript is disabled. Furthermore you can also define multiple image sources in the picture, so it is possible to display an image in portait mode with a 9/16 aspect-ratio (multiple renditions) and in landscape mode with a 16/9 aspect-ratio (multiple renditions).

Javascript Loading

NuxtJS follows the approach to load the core files (page, app, payload, vendor, state, etc.) as fast and efficient as possible via (module-)preload from the client. This also makes total sense if you want to deliver an SPA. For the SSR build, however, we modified the delivery a bit. The many parallel downloads (fonts, images, js, ...) have a negative impact from a performance perspective. This effect increases when the javascript files grow in size due to modules and plugins. It would make sense if the initial package is kept small and only the absolutely necessary resources that can trigger the further initialization process are transferred via dynamic import. This leaves enough bandwidth to load the remaining resources (fonts, images).

This loading behavior only makes sense with an SSR build, since the full page-related static content can already be delivered and rendered with the HTML and the included CSS. This means that the user does not notice any time lags and the page is still usable. Another advantage: If the bandwidth is low, a basic functionality of the page (links, ...) can be ensured thanks to the SSR build.

RequestIdleCallback

The TimeRemaining function of the IdleDeadline object continuously returns a value <= 10 in the Lighthouse Test (simulated Motorola G4). This can be seen as an indicator for weak hardware on the end device and allows the following conclusion. If there are not enough hardware resources available to execute the JavaScript quickly, this process is suppressed. Who needs optional functionality that takes a long time to initialize and possibly leads to a temporary freeze in the browser.

We use this effect by executing the intial javascript process and the component initialization in the RequestIdleCallback, if we get a time slot >10ms from the device. Hereby we achieve a massive reduction of the TTI/TBT in the Lighthouse Test and on weak hardware, because the javascript execution is simply paused in the worst case until sufficient resources are available. This also prevents blocking of the MainThread.

Side effect: The timeslots in the Google Lighthouse Test are always <= 10ms, so no javascript will be initialized.

BoosterLayer

With the solutions described above, the user gets a functioning webpage displayed very quickly. However, the following situation can also occur on the end device:

  • no Javascript enabled
  • reduced bandwidth
  • weak hardware
  • unsupported browser

The reduced bandwidth or weak hardware should get a focus especially when larger amounts of data have to be transferred and executed, e.g. a ThreeJS component with more complex 3D objects. In this case, we should inform the user that the experience will be negatively affected and that there may be waiting times.

For this purpose, we provide an InfoLayer that is displayed when a minimum FCP time is exceeded, when the number of available CPU cores falls below a minimum level, when javascript is disabled or the users opens the page by an unsupported browser. The user can decide in this dialog box whether he wants to load the remaining resources despite the restrictions. If the user declines this dialog, only the fonts and images for the page will be loaded and no further javascript will be loaded or executed.

Conclusion

The findings and solutions described above have been incorporated and systematized in the Nuxt Booster module. Only in combination can they unfold their full functionality and ensure an overall optimization of the loading behavior. Overall we have reduced the following timing metrics ...

  • FCP
  • LCP
  • TTI
  • TBT

With this module we enable every developer in the NuxtJS context to achieve a Lighthouse Performance Score 100/100 and drastically reduce the development time for website performance optimization.

- + \ No newline at end of file diff --git a/directives/v-font.html b/directives/v-font.html index 9c578aa71f..34d512be80 100644 --- a/directives/v-font.html +++ b/directives/v-font.html @@ -47,7 +47,7 @@ $getFont('Font Family B', 700, 'normal', { selector: 'b, strong', media: '(min-width: 768px)' }) ] - + \ No newline at end of file diff --git a/guide/caveats.html b/guide/caveats.html index 8b5028f870..ad2f02b954 100644 --- a/guide/caveats.html +++ b/guide/caveats.html @@ -41,7 +41,7 @@ }) </script> - + \ No newline at end of file diff --git a/guide/options.html b/guide/options.html index a1bcd0495a..e39e767ab7 100644 --- a/guide/options.html +++ b/guide/options.html @@ -82,7 +82,7 @@ stdTTL: 3600, checkperiod: 1800 }

disableNuxtFontaine

If set, @nuxtjs/fontaine will not be integrated.

INFO

For more information: https://github.com/nuxt-modules/fontaine

disableNuxtImage

If set, @nuxt/image will not be integrated.

DANGER

Note that the use of BoosterImage, BoosterPicture, BoosterVimeo and BoosterYoutube is not supported if @nuxt/image is not integrated.

- + \ No newline at end of file diff --git a/guide/setup.html b/guide/setup.html index 6232520b3c..0868d07963 100644 --- a/guide/setup.html +++ b/guide/setup.html @@ -13,18 +13,18 @@ - + -
Skip to content

Setup

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster
bash
npm install nuxt-booster

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
+    
Skip to content

Setup

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster
bash
npm install nuxt-booster

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
   domains: ['img.youtube.com', 'i.vimeocdn.com'],
   alias: {
     youtube: 'https://img.youtube.com',
     vimeo: 'https://i.vimeocdn.com',
   }
-}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
+}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
   modules: [
     'nuxt-booster'
   ],
@@ -113,7 +113,7 @@
     }
   }
 }

See module options.

- + \ No newline at end of file diff --git a/guide/usage.html b/guide/usage.html index 826be9dc67..e3b627f835 100644 --- a/guide/usage.html +++ b/guide/usage.html @@ -36,7 +36,7 @@ } } </script>

INFO

The booster components will be expanded in the future. If you have explicit wishes, please send us a feature request or directly a pull request with the corresponding feature 😃

- + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json index a4d5791081..b0f96105e8 100644 --- a/hashmap.json +++ b/hashmap.json @@ -1 +1 @@ -{"components_booster-iframe.md":"DewifIWH","components_booster-image.md":"DI1CXARJ","components_booster-layer.md":"CbnxCS7q","components_booster-picture.md":"CdFj24tC","components_booster-vimeo.md":"B77xNqAi","components_booster-youtube.md":"BIu7DkrA","components_weak-hardware-overlay.md":"OARp2jlg","composables_useboostercomponentobserver.md":"BkQ4hcz3","composables_useboosterconfig.md":"B6NOls_e","composables_useboostercritical.md":"Dyi4Zgv_","composables_useboosterfont.md":"Ccydds_O","composables_useboosterhead.md":"DIrqPJig","composables_useboosterhydrate.md":"dvXW5RST","concept.md":"682dqkbQ","directives_v-font.md":"CGop7P5Z","guide_caveats.md":"B7VTlpms","guide_options.md":"CFAOniKe","guide_setup.md":"CEfJ7p-4","guide_usage.md":"IxRXWUKL","index.md":"TkpCxDr1","migration_v2-0-13.md":"DiDnxTT1","migration_v2-2-0.md":"QLI9GM6o","migration_v2.md":"lHvb4SrJ","migration_v3.1.0.md":"CO4dZGl5","migration_v3.md":"DJib9_zJ","v2_classes_loading-spinner.md":"Ny1XgwWK","v2_components_booster-iframe.md":"pnnV4ms5","v2_components_booster-image.md":"CqNwy1CV","v2_components_booster-layer.md":"DgIahzTB","v2_components_booster-picture.md":"8mw9vWsk","v2_components_booster-vimeo.md":"BE5KVc2K","v2_components_booster-youtube.md":"8gep-Xuj","v2_concept.md":"UIBM5ko-","v2_directives_v-font.md":"CbFUz2n3","v2_guide_caveats.md":"DSFfA9pw","v2_guide_options.md":"CK_gYSfe","v2_guide_setup.md":"4xibyHQY","v2_guide_usage.md":"DapNg4e5","v2_index.md":"DJxV8Ady"} +{"components_booster-iframe.md":"DewifIWH","components_booster-image.md":"DI1CXARJ","components_booster-layer.md":"CbnxCS7q","components_booster-picture.md":"CdFj24tC","components_booster-vimeo.md":"B77xNqAi","components_booster-youtube.md":"BIu7DkrA","components_weak-hardware-overlay.md":"DS4AzeXN","composables_useboostercomponentobserver.md":"BkQ4hcz3","composables_useboosterconfig.md":"B6NOls_e","composables_useboostercritical.md":"Dyi4Zgv_","composables_useboosterfont.md":"Ccydds_O","composables_useboosterhead.md":"DIrqPJig","composables_useboosterhydrate.md":"dvXW5RST","concept.md":"682dqkbQ","directives_v-font.md":"CGop7P5Z","guide_caveats.md":"B7VTlpms","guide_options.md":"CFAOniKe","guide_setup.md":"D6N-RRvC","guide_usage.md":"IxRXWUKL","index.md":"TkpCxDr1","migration_v2-0-13.md":"DiDnxTT1","migration_v2-2-0.md":"QLI9GM6o","migration_v2.md":"lHvb4SrJ","migration_v3.1.0.md":"CO4dZGl5","migration_v3.md":"DJib9_zJ","v2_classes_loading-spinner.md":"Ny1XgwWK","v2_components_booster-iframe.md":"pnnV4ms5","v2_components_booster-image.md":"CqNwy1CV","v2_components_booster-layer.md":"DgIahzTB","v2_components_booster-picture.md":"8mw9vWsk","v2_components_booster-vimeo.md":"BE5KVc2K","v2_components_booster-youtube.md":"8gep-Xuj","v2_concept.md":"UIBM5ko-","v2_directives_v-font.md":"CbFUz2n3","v2_guide_caveats.md":"Di9i8oN-","v2_guide_options.md":"CK_gYSfe","v2_guide_setup.md":"CZKcSKmb","v2_guide_usage.md":"DapNg4e5","v2_index.md":"DJxV8Ady"} diff --git a/index.html b/index.html index 2d1524252e..51f9970895 100644 --- a/index.html +++ b/index.html @@ -20,7 +20,7 @@
Skip to content
nuxt boosternuxt booster

Module for NuxtJS.

You are reading the documentation for Nuxt Booster (v3)!

Nuxt Booster takes over the lighthouse performance optimization of your generated website.

In order to achieve a performance score of 100/100, only the necessary resources located in the current viewport may be initialized when the page is loaded. This includes images, fonts and the js-modules. Until now, there has been no practical and usable concept to help developers maintain an overview and enable accurate targeting in NuxtJS projects.

This module addresses this problem and provides a holistic approach to intelligently load the necessary viewport related resources to reduce FCP, DCL, TTI, TBT and CLS.

We didn't reinvent the whole wheel. We adapt the lazy hydration concept of Markus Oberlehner to load js components in an efficient way, use the nuxt/image module as a base to retrieve optimized image resolutions for our picture and image components and add some new stuff to obtain a holistic solution.

Requirements

  • NodeJS >= 19
  • NuxtJS >= 3.5.0

Features

We provide the following CMS-friendly features:

  • dynamic loading of viewport based page resources like fonts, components, pictures, images and iframes
  • optional blocking of javascript execution by initial performance measuring
  • optimized initial load of javascript files by eliminating of unnecessary javascript files
  • prevents the loading of unnecessary resources (including components) that are outside the current viewport.
  • optional info layer concept to inform users about a reduced UX when bandwidth or hardware is compromised.
  • completely new approach of font declaration
  • optimized picture component (supports viewport based sources e.g. landscape/portrait)
  • optimized image component
  • supports SEO-friendly lazy hydration mode (picture + image)
  • optimized youtube/vimeo component (auto generated poster image in different resolutions)

Results

  • delivery of the minimum required resources based on the current viewport
  • if you use the tools as specified you will get a lighthouse performance score of 100/100

Demos

- + \ No newline at end of file diff --git a/migration/v2-0-13.html b/migration/v2-0-13.html index 09e5999261..212c61895c 100644 --- a/migration/v2-0-13.html +++ b/migration/v2-0-13.html @@ -27,7 +27,7 @@ </li>

replaced with

html
<li id="nuxt-booster-message-reduced-bandwidth">
   reduced-bandwidth
 </li>

Button Interactions

Button #nuxt-booster-button-init-font has been replaced by #nuxt-booster-button-init-reduced-view.

#nuxt-booster-button-init-reduced-view does the following when clicked:

  1. Sets the CSS class nuxt-booster-reduced-view on the html tag.
  2. Activates all fonts by setting the class font-active on all elements with the attribute data-font.
  3. Converts all not activated pictures (:hydrate="false") from noscript to picture.

INFO

The CSS class nuxt-booster-reduced-view is removed again at app initialization.

- + \ No newline at end of file diff --git a/migration/v2-2-0.html b/migration/v2-2-0.html index 4fe0746014..c5a2fc836f 100644 --- a/migration/v2-2-0.html +++ b/migration/v2-2-0.html @@ -19,7 +19,7 @@
Skip to content

Migrate from v2.0.13 to v2.2.0

With the change to version 2.2.0 there are the following changes:

Package Structure

Package structure was updated.

Everything in the folder runtime is available with the alias #booster.

General

Old PathNew Path
nuxt-booster/hydrate#booster/hyrdate

Components

Old PathNew Path
nuxt-booster/components/abstracts/ComponentObserver#booster/components/abstracts/ComponentObserver
nuxt-booster/components/abstracts/OnlySsr#booster/components/abstracts/OnlySsr
nuxt-booster/components/GoogleLighthouse#booster/components/GoogleLighthouse
nuxt-booster/components/BoosterImage#booster/components/BoosterImage
nuxt-booster/components/BoosterPicture#booster/components/BoosterPicture
nuxt-booster/components/BoosterVimeo#booster/components/BoosterVimeo
nuxt-booster/components/BoosterYoutube#booster/components/BoosterYoutube
nuxt-booster/components/BoosterIframe#booster/components/BoosterIframe
nuxt-booster/components/BoosterImage#booster/components/BoosterImage
nuxt-booster/components/BoosterLayer#booster/components/BoosterLayer
nuxt-booster/components/BoosterPicture#booster/components/BoosterPicture
nuxt-booster/components/BoosterVimeo#booster/components/BoosterVimeo
nuxt-booster/components/BoosterYoutube#booster/components/BoosterYoutube

Utils

Old PathNew Path
nuxt-booster/utils#booster/utils
nuxt-booster/utils/base64#booster/utils/base64
nuxt-booster/utils/browser#booster/utils/browser
nuxt-booster/utils/description#booster/utils/description
nuxt-booster/utils/lighthouse#booster/utils/lighthouse
nuxt-booster/utils/mimeType#booster/utils/mimeType
nuxt-booster/utils/performance#booster/utils/performance
nuxt-booster/utils/placeholder#booster/utils/placeholder
nuxt-booster/utils/string#booster/utils/string
nuxt-booster/utils/support#booster/utils/support
- + \ No newline at end of file diff --git a/migration/v2.html b/migration/v2.html index cebc5b1dd1..0694e957e3 100644 --- a/migration/v2.html +++ b/migration/v2.html @@ -36,7 +36,7 @@ { src: '/img/landscape.png', sizes: { md: '100vw' }, media: '(orientation: landscape)' }, { src: '/img/portrait.png', sizes: { default: '100vw', sm: '100vw' }, media: '(orientation: portrait)' } ]

More information about the integration of BoosterPicture can be found here.

WARNING

Important: In the new version of BoosterPicture the placeholder property is no longer included.

BoosterYoutube / BoosterYoutubeExperimental

With the change of the BoosterPicture also BoosterYoutube and BoosterYoutubeExperimental were reduced to BoosterYoutube.

The events loading and enter have been removed.

More information about the integration of BoosterYoutube can be found here.

BoosterIframe

Property intersectionObserver was renamed to componentObserver.

More information about the integration of BoosterIframe can be found here.

- + \ No newline at end of file diff --git a/migration/v3.1.0.html b/migration/v3.1.0.html index 57b221f5db..5f25529477 100644 --- a/migration/v3.1.0.html +++ b/migration/v3.1.0.html @@ -55,7 +55,7 @@ ]" /> </template> - + \ No newline at end of file diff --git a/migration/v3.html b/migration/v3.html index d398a1c859..6c9e47e75a 100644 --- a/migration/v3.html +++ b/migration/v3.html @@ -29,7 +29,7 @@ </script>

for the use of critical components.

html
<template>
   <component critical></component>
 </template>
- + \ No newline at end of file diff --git a/playground/200.html b/playground/200.html index a21808b22b..a3d69e462c 100644 --- a/playground/200.html +++ b/playground/200.html @@ -4,5 +4,5 @@ -
- \ No newline at end of file +
+ \ No newline at end of file diff --git a/playground/404.html b/playground/404.html index a21808b22b..3c7b7b7e03 100644 --- a/playground/404.html +++ b/playground/404.html @@ -4,5 +4,5 @@ -
- \ No newline at end of file +
+ \ No newline at end of file diff --git a/playground/_nuxt/builds/latest.json b/playground/_nuxt/builds/latest.json index b873d1b9fc..996e29d935 100644 --- a/playground/_nuxt/builds/latest.json +++ b/playground/_nuxt/builds/latest.json @@ -1 +1 @@ -{"id":"834c7aa3-db68-4414-aea4-a9b0c5a5f366","timestamp":1733415969343} \ No newline at end of file +{"id":"9ca15f2b-2e0b-4b80-9bb9-04d987fd2045","timestamp":1733997690269} \ No newline at end of file diff --git a/playground/_nuxt/builds/meta/834c7aa3-db68-4414-aea4-a9b0c5a5f366.json b/playground/_nuxt/builds/meta/834c7aa3-db68-4414-aea4-a9b0c5a5f366.json deleted file mode 100644 index c7e5d0ef98..0000000000 --- a/playground/_nuxt/builds/meta/834c7aa3-db68-4414-aea4-a9b0c5a5f366.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"834c7aa3-db68-4414-aea4-a9b0c5a5f366","timestamp":1733415969343,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":["/","/tests","/tests/booster-layer","/tests/youtube","/tests/image","/tests/vimeo","/tests/picture","/tests/iframe","/tests/v-font","/tests/v-font-media","/tests/booster-hydrate","/tests/booster-loader","/tests/v-font-scroll","/tests/useBoosterHead/1","/tests/useBoosterHead","/tests/useBoosterHead/2","/tests/useBoosterHead/empty-1","/tests/useBoosterHead/empty-2","/tests/weak-hardware-overlay"]} \ No newline at end of file diff --git a/playground/_nuxt/builds/meta/9ca15f2b-2e0b-4b80-9bb9-04d987fd2045.json b/playground/_nuxt/builds/meta/9ca15f2b-2e0b-4b80-9bb9-04d987fd2045.json new file mode 100644 index 0000000000..a75bea3f47 --- /dev/null +++ b/playground/_nuxt/builds/meta/9ca15f2b-2e0b-4b80-9bb9-04d987fd2045.json @@ -0,0 +1 @@ +{"id":"9ca15f2b-2e0b-4b80-9bb9-04d987fd2045","timestamp":1733997690269,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":["/","/tests","/tests/booster-layer","/tests/youtube","/tests/picture","/tests/vimeo","/tests/image","/tests/iframe","/tests/v-font","/tests/v-font-media","/tests/booster-loader","/tests/booster-hydrate","/tests/v-font-scroll","/tests/useBoosterHead/1","/tests/useBoosterHead","/tests/useBoosterHead/2","/tests/useBoosterHead/empty-1","/tests/useBoosterHead/empty-2","/tests/weak-hardware-overlay"]} \ No newline at end of file diff --git a/playground/_payload.json b/playground/_payload.json index 3f11aabaf4..1efd7f6956 100644 --- a/playground/_payload.json +++ b/playground/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979666] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700595] \ No newline at end of file diff --git a/playground/index.html b/playground/index.html index 3a22c8a31b..392233f24a 100644 --- a/playground/index.html +++ b/playground/index.html @@ -136,8 +136,8 @@ .nuxt-booster-weak-hardware-overlay[data-v-0ed2b2ab]{align-items:center;-webkit-backdrop-filter:blur(.25em);backdrop-filter:blur(.25em);background:#0009;display:flex;flex-direction:column;height:100%;justify-content:center;left:0;position:absolute;top:0;width:100%}.nuxt-booster-weak-hardware-overlay div[data-v-0ed2b2ab]{font-size:14px;text-align:center} /*! purgecss start ignore */html:not(.nuxt-booster-reduced-view) .nuxt-booster-weak-hardware-overlay[data-v-d93e0c67]{display:none}/*! purgecss end ignore */ .base-button[data-v-e4ca9d38]{--font-size:16;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:.0625em solid;border:calc(1/var(--font-size)*1em) solid;border-radius:.3125em;border-radius:calc(5/var(--font-size)*1em);color:currentColor;cursor:pointer;font-size:1em;font-size:calc(var(--font-size)/16*1em);outline:none;padding:.5em 1em;padding:calc(8/var(--font-size)*1em) calc(16/var(--font-size)*1em);transition:transform .1s ease-in;will-change:transform}.base-button[data-v-e4ca9d38]:hover{transform:scale(1.05)}.base-button[data-v-e4ca9d38]:active{transform:scale(.95)} -/*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ .player[data-v-a7b12ddf]{margin:0;padding:0;position:relative;width:100%}.player button[data-v-a7b12ddf]{cursor:pointer;display:block;width:100%}.ready .player button[data-v-a7b12ddf]{pointer-events:none;visibility:hidden}:is(.ready .player) button[data-v-a7b12ddf]{pointer-events:none;visibility:hidden}.player iframe[data-v-a7b12ddf]{border:none;bottom:0;height:100%;left:0;margin:auto;position:absolute;right:0;top:0;width:100%}.iframe-mode .player[data-v-a7b12ddf]{aspect-ratio:16/9}/*! purgecss start ignore */.loading-spinner[data-v-540459c3],.play[data-v-540459c3]{align-items:center;background:#0003;bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0}.loading-spinner svg[data-v-540459c3]{display:block;width:64px}[data-v-540459c3] button{--color-background:rgba(30,30,30,.7);--color-foreground:#fff;--transition-duration:.1s}@supports (color:rgb(0 0 0/0)){[data-v-540459c3] button{--color-background:rgba(30,30,30,.7)}}[data-v-540459c3] button:focus,[data-v-540459c3] button:hover{--color-background:rgba(30,30,30,.9);--color-foreground:#00adef;--transition-duration:.2s}@supports (color:rgb(0 0 0/0)){[data-v-540459c3] button:focus,[data-v-540459c3] button:hover{--color-background:rgba(30,30,30,.9);--color-foreground:#00adef}}.play span[data-v-540459c3]{align-items:center;background:var(--color-background);border-radius:.5em;color:var(--color-foreground);display:flex;height:4em;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:opacity var(--transition-duration),background-color var(--transition-duration),color var(--transition-duration);width:6.5em}.play span svg[data-v-540459c3]{display:block;height:2em;width:2em;fill:currentColor}:is(.play span) svg[data-v-540459c3]{display:block;height:2em;width:2em;fill:currentColor}/*! purgecss end ignore */ +/*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */
Stage

nuxt-boosterpowered by Basics

Text A

Aliqua odit anim vehicula varius eget feugiat beatae. Fringilla cumque, nulla pulvinar necessitatibus pharetra vehicula ultricies egestas rhoncus justo occaecati amet, fames quod. Similique! Ornare nesciunt inventore nulla, montes doloribus, erat, parturient! Accumsan omnis doloribus perspiciatis, blanditiis ullamcorper adipisicing quisquam. Nobis placerat. Eget do sagittis elit wisi voluptates, facilisis veritatis.

Laboriosam recusandae blandit nunc tempor urna veniam? Etiam perferendis, quisquam class ea eos habitasse quis tempora nulla? Non, facilis consectetuer suspendisse tortor, etiam dolor? Blanditiis suspendisse, massa. Tempus consequatur bibendum magnam? Praesentium, posuere consequuntur, tenetur tempus quod suscipit nibh? Voluptate ratione justo! Ullamcorper! Cursus auctor magna. Beatae corporis. Inceptos nisi.

Image Text A

Image Text A

Aliqua odit anim vehicula varius eget feugiat beatae. Fringilla cumque, nulla pulvinar necessitatibus pharetra vehicula ultricies egestas rhoncus justo occaecati amet, fames quod. Similique! Ornare nesciunt inventore nulla, montes doloribus, erat, parturient! Accumsan omnis doloribus perspiciatis, blanditiis ullamcorper adipisicing quisquam. Nobis placerat. Eget do sagittis elit wisi voluptates, facilisis veritatis.

Laboriosam recusandae blandit nunc tempor urna veniam? Etiam perferendis, quisquam class ea eos habitasse quis tempora nulla? Non, facilis consectetuer suspendisse tortor, etiam dolor? Blanditiis suspendisse, massa. Tempus consequatur bibendum magnam? Praesentium, posuere consequuntur, tenetur tempus quod suscipit nibh? Voluptate ratione justo! Ullamcorper! Cursus auctor magna. Beatae corporis. Inceptos nisi.

To improve your experience, extensive features have been disabled.

Nunc odio nisl dapibus consequat recusandae doloremque nisi natus repudiandae do accusantium corrupti. Harum quisquam, maxime, perspiciatis lobortis earum iure.

To improve your experience, extensive features have been disabled.

We wanted to make incredible stock video accessible to all creators. So we did. www.vimeo.com/stock Learn more about Vimeo Stock: https://vimeo.com/blog/post/introducing-a-new-kind-of-stock-video @@ -148,5 +148,5 @@ Learn more about Vimeo Stock: https://vimeo.com/blog/post/introducing-a-new-kind-of-stock-video Created by Amy Kawabata & Luke Shock. -Made with Vimeo Stock.

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +Made with Vimeo Stock.

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/_payload.json b/playground/tests/_payload.json index 12af450bca..d86a63c524 100644 --- a/playground/tests/_payload.json +++ b/playground/tests/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979668] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700598] \ No newline at end of file diff --git a/playground/tests/booster-hydrate/_payload.json b/playground/tests/booster-hydrate/_payload.json index 12af450bca..42448b9594 100644 --- a/playground/tests/booster-hydrate/_payload.json +++ b/playground/tests/booster-hydrate/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979668] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700597] \ No newline at end of file diff --git a/playground/tests/booster-hydrate/index.html b/playground/tests/booster-hydrate/index.html index 135431afef..69e4a62f99 100644 --- a/playground/tests/booster-hydrate/index.html +++ b/playground/tests/booster-hydrate/index.html @@ -28,5 +28,5 @@
inactive

Critical
BoosterHydrate

inactive

Lazy
BoosterHydrate

inactive

Media
BoosterHydrate

inactive

Custom
BoosterHydrate

- \ No newline at end of file +
inactive

Critical
BoosterHydrate

inactive

Lazy
BoosterHydrate

inactive

Media
BoosterHydrate

inactive

Custom
BoosterHydrate

+ \ No newline at end of file diff --git a/playground/tests/booster-layer/_payload.json b/playground/tests/booster-layer/_payload.json index 12af450bca..42448b9594 100644 --- a/playground/tests/booster-layer/_payload.json +++ b/playground/tests/booster-layer/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979668] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700597] \ No newline at end of file diff --git a/playground/tests/booster-layer/index.html b/playground/tests/booster-layer/index.html index 1501ba2429..ed9b9877da 100644 --- a/playground/tests/booster-layer/index.html +++ b/playground/tests/booster-layer/index.html @@ -40,5 +40,5 @@ /*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ /*! purgecss start ignore */.nuxt-booster-picture[data-v-fc7d4048]{box-sizing:border-box;display:block;position:relative;width:100%}.nuxt-booster-picture img[data-v-fc7d4048]{bottom:0;box-sizing:border-box;left:0;position:absolute;right:0;top:0}.nuxt-booster-picture[data-v-fc7d4048]:before{box-sizing:border-box;content:"";display:block;position:relative}@supports (aspect-ratio:1){.nuxt-booster-picture[data-v-fc7d4048],.nuxt-booster-picture img[data-v-fc7d4048]{position:static;position:unset}.nuxt-booster-picture img[data-v-fc7d4048]{bottom:auto;bottom:unset;left:auto;left:unset;right:auto;right:unset;top:auto;top:unset}.nuxt-booster-picture[data-v-fc7d4048]:before{display:none}}/*! purgecss end ignore */ /*! purgecss start ignore */.nuxt-booster-image[data-v-3621510f]{content-visibility:auto;display:block;height:auto;-o-object-fit:cover;object-fit:cover;width:100%}/*! purgecss end ignore */ -
BoosterLayer Test

BoosterLayer Test

Aliqua odit anim vehicula varius eget feugiat beatae. Fringilla cumque, nulla pulvinar necessitatibus pharetra vehicula ultricies egestas rhoncus justo occaecati amet, fames quod. Similique! Ornare nesciunt inventore nulla, montes doloribus, erat, parturient! Accumsan omnis doloribus perspiciatis, blanditiis ullamcorper adipisicing quisquam. Nobis placerat. Eget do sagittis elit wisi voluptates, facilisis veritatis.

Laboriosam recusandae blandit nunc tempor urna veniam? Etiam perferendis, quisquam class ea eos habitasse quis tempora nulla? Non, facilis consectetuer suspendisse tortor, etiam dolor? Blanditiis suspendisse, massa. Tempus consequatur bibendum magnam? Praesentium, posuere consequuntur, tenetur tempus quod suscipit nibh? Voluptate ratione justo! Ullamcorper! Cursus auctor magna. Beatae corporis. Inceptos nisi.

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • slow connection
  • weak hardware
  • low battery
- \ No newline at end of file +
BoosterLayer Test

BoosterLayer Test

Aliqua odit anim vehicula varius eget feugiat beatae. Fringilla cumque, nulla pulvinar necessitatibus pharetra vehicula ultricies egestas rhoncus justo occaecati amet, fames quod. Similique! Ornare nesciunt inventore nulla, montes doloribus, erat, parturient! Accumsan omnis doloribus perspiciatis, blanditiis ullamcorper adipisicing quisquam. Nobis placerat. Eget do sagittis elit wisi voluptates, facilisis veritatis.

Laboriosam recusandae blandit nunc tempor urna veniam? Etiam perferendis, quisquam class ea eos habitasse quis tempora nulla? Non, facilis consectetuer suspendisse tortor, etiam dolor? Blanditiis suspendisse, massa. Tempus consequatur bibendum magnam? Praesentium, posuere consequuntur, tenetur tempus quod suscipit nibh? Voluptate ratione justo! Ullamcorper! Cursus auctor magna. Beatae corporis. Inceptos nisi.

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • slow connection
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/booster-loader/_payload.json b/playground/tests/booster-loader/_payload.json index 12af450bca..42448b9594 100644 --- a/playground/tests/booster-loader/_payload.json +++ b/playground/tests/booster-loader/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979668] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700597] \ No newline at end of file diff --git a/playground/tests/booster-loader/index.html b/playground/tests/booster-loader/index.html index b9bb561034..4cc19532f6 100644 --- a/playground/tests/booster-loader/index.html +++ b/playground/tests/booster-loader/index.html @@ -26,5 +26,5 @@
inactive

Critical
BoosterHydrate

inactive

Critical
BoosterHydrate

- \ No newline at end of file +
inactive

Critical
BoosterHydrate

inactive

Critical
BoosterHydrate

+ \ No newline at end of file diff --git a/playground/tests/iframe/_payload.json b/playground/tests/iframe/_payload.json index 12af450bca..42448b9594 100644 --- a/playground/tests/iframe/_payload.json +++ b/playground/tests/iframe/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979668] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700597] \ No newline at end of file diff --git a/playground/tests/iframe/index.html b/playground/tests/iframe/index.html index 6bf92776a6..3e52a7b419 100644 --- a/playground/tests/iframe/index.html +++ b/playground/tests/iframe/index.html @@ -56,5 +56,5 @@ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} /*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ .base-button[data-v-e4ca9d38]{--font-size:16;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:.0625em solid;border:calc(1/var(--font-size)*1em) solid;border-radius:.3125em;border-radius:calc(5/var(--font-size)*1em);color:currentColor;cursor:pointer;font-size:1em;font-size:calc(var(--font-size)/16*1em);outline:none;padding:.5em 1em;padding:calc(8/var(--font-size)*1em) calc(16/var(--font-size)*1em);transition:transform .1s ease-in;will-change:transform}.base-button[data-v-e4ca9d38]:hover{transform:scale(1.05)}.base-button[data-v-e4ca9d38]:active{transform:scale(.95)} -

Critical
Iframe

Lazy
Iframe

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +

Critical
Iframe

Lazy
Iframe

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/image/_payload.json b/playground/tests/image/_payload.json index 12af450bca..a8dd02ae59 100644 --- a/playground/tests/image/_payload.json +++ b/playground/tests/image/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979668] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700596] \ No newline at end of file diff --git a/playground/tests/image/index.html b/playground/tests/image/index.html index 12535fe828..8b26646059 100644 --- a/playground/tests/image/index.html +++ b/playground/tests/image/index.html @@ -65,5 +65,5 @@ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} /*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ .base-button[data-v-e4ca9d38]{--font-size:16;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:.0625em solid;border:calc(1/var(--font-size)*1em) solid;border-radius:.3125em;border-radius:calc(5/var(--font-size)*1em);color:currentColor;cursor:pointer;font-size:1em;font-size:calc(var(--font-size)/16*1em);outline:none;padding:.5em 1em;padding:calc(8/var(--font-size)*1em) calc(16/var(--font-size)*1em);transition:transform .1s ease-in;will-change:transform}.base-button[data-v-e4ca9d38]:hover{transform:scale(1.05)}.base-button[data-v-e4ca9d38]:active{transform:scale(.95)} -
Critical - Image

Critical - Image

Lazy - Image

Lazy - Image

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +
Critical - Image

Critical - Image

Lazy - Image

Lazy - Image

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/index.html b/playground/tests/index.html index a40c59415e..e5e9d822e7 100644 --- a/playground/tests/index.html +++ b/playground/tests/index.html @@ -9,5 +9,5 @@
blank
- \ No newline at end of file +
blank
+ \ No newline at end of file diff --git a/playground/tests/picture/_payload.json b/playground/tests/picture/_payload.json index 0647643d16..d86a63c524 100644 --- a/playground/tests/picture/_payload.json +++ b/playground/tests/picture/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733415979669] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997700598] \ No newline at end of file diff --git a/playground/tests/picture/index.html b/playground/tests/picture/index.html index 849361275a..d1dc4421d9 100644 --- a/playground/tests/picture/index.html +++ b/playground/tests/picture/index.html @@ -70,5 +70,5 @@ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} /*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ .base-button[data-v-e4ca9d38]{--font-size:16;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:.0625em solid;border:calc(1/var(--font-size)*1em) solid;border-radius:.3125em;border-radius:calc(5/var(--font-size)*1em);color:currentColor;cursor:pointer;font-size:1em;font-size:calc(var(--font-size)/16*1em);outline:none;padding:.5em 1em;padding:calc(8/var(--font-size)*1em) calc(16/var(--font-size)*1em);transition:transform .1s ease-in;will-change:transform}.base-button[data-v-e4ca9d38]:hover{transform:scale(1.05)}.base-button[data-v-e4ca9d38]:active{transform:scale(.95)} -
Critical

Critical - Picture

Lazy

Lazy - Picture

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +
Critical

Critical - Picture

Lazy

Lazy - Picture

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/useBoosterHead/1/_payload.json b/playground/tests/useBoosterHead/1/_payload.json index 40cffe1a69..8fe51d0ebd 100644 --- a/playground/tests/useBoosterHead/1/_payload.json +++ b/playground/tests/useBoosterHead/1/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416198453] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997921544] \ No newline at end of file diff --git a/playground/tests/useBoosterHead/1/index.html b/playground/tests/useBoosterHead/1/index.html index 93da61598f..e47d34c6d0 100644 --- a/playground/tests/useBoosterHead/1/index.html +++ b/playground/tests/useBoosterHead/1/index.html @@ -23,5 +23,5 @@

Merriweather - 400 - normal

Merriweather - 700 - normal

Merriweather - 400 - italic

Merriweather - 700 - italic

- \ No newline at end of file +

Merriweather - 400 - normal

Merriweather - 700 - normal

Merriweather - 400 - italic

Merriweather - 700 - italic

+ \ No newline at end of file diff --git a/playground/tests/useBoosterHead/2/_payload.json b/playground/tests/useBoosterHead/2/_payload.json index 232ea61378..36483dfcd8 100644 --- a/playground/tests/useBoosterHead/2/_payload.json +++ b/playground/tests/useBoosterHead/2/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416198463] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997921576] \ No newline at end of file diff --git a/playground/tests/useBoosterHead/2/index.html b/playground/tests/useBoosterHead/2/index.html index 8f928ce219..2dbbd2a458 100644 --- a/playground/tests/useBoosterHead/2/index.html +++ b/playground/tests/useBoosterHead/2/index.html @@ -25,5 +25,5 @@

Quicksand - 300 - normal

Quicksand - 400 - normal

Quicksand - 500 - normal

Quicksand - 600 - normal

Quicksand - 700 - normal

- \ No newline at end of file +

Quicksand - 300 - normal

Quicksand - 400 - normal

Quicksand - 500 - normal

Quicksand - 600 - normal

Quicksand - 700 - normal

+ \ No newline at end of file diff --git a/playground/tests/useBoosterHead/_payload.json b/playground/tests/useBoosterHead/_payload.json index f08ac9373c..632e21195d 100644 --- a/playground/tests/useBoosterHead/_payload.json +++ b/playground/tests/useBoosterHead/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416198434] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997920520] \ No newline at end of file diff --git a/playground/tests/useBoosterHead/empty-1/_payload.json b/playground/tests/useBoosterHead/empty-1/_payload.json index ab72f8ea46..11d1c9eb33 100644 --- a/playground/tests/useBoosterHead/empty-1/_payload.json +++ b/playground/tests/useBoosterHead/empty-1/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416198474] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997921600] \ No newline at end of file diff --git a/playground/tests/useBoosterHead/empty-1/index.html b/playground/tests/useBoosterHead/empty-1/index.html index fdb0f7c1da..307bc3e549 100644 --- a/playground/tests/useBoosterHead/empty-1/index.html +++ b/playground/tests/useBoosterHead/empty-1/index.html @@ -12,5 +12,5 @@
- \ No newline at end of file +
+ \ No newline at end of file diff --git a/playground/tests/useBoosterHead/empty-2/_payload.json b/playground/tests/useBoosterHead/empty-2/_payload.json index 36db70c924..31c8ed3c3b 100644 --- a/playground/tests/useBoosterHead/empty-2/_payload.json +++ b/playground/tests/useBoosterHead/empty-2/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416198482] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997921808] \ No newline at end of file diff --git a/playground/tests/useBoosterHead/empty-2/index.html b/playground/tests/useBoosterHead/empty-2/index.html index 09fc97be9b..a9f7f2b470 100644 --- a/playground/tests/useBoosterHead/empty-2/index.html +++ b/playground/tests/useBoosterHead/empty-2/index.html @@ -12,5 +12,5 @@
- \ No newline at end of file +
+ \ No newline at end of file diff --git a/playground/tests/useBoosterHead/index.html b/playground/tests/useBoosterHead/index.html index 735ed73167..0b8595828b 100644 --- a/playground/tests/useBoosterHead/index.html +++ b/playground/tests/useBoosterHead/index.html @@ -28,5 +28,5 @@

Montserrat Alternates - 400 - normal

Montserrat Alternates - 700 - normal

Montserrat Alternates - 400 - italic

Montserrat Alternates - 700 - italic

- \ No newline at end of file +

Montserrat Alternates - 400 - normal

Montserrat Alternates - 700 - normal

Montserrat Alternates - 400 - italic

Montserrat Alternates - 700 - italic

+ \ No newline at end of file diff --git a/playground/tests/v-font-media/_payload.json b/playground/tests/v-font-media/_payload.json index aad37a1528..068b0c66c2 100644 --- a/playground/tests/v-font-media/_payload.json +++ b/playground/tests/v-font-media/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416094526] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997817694] \ No newline at end of file diff --git a/playground/tests/v-font-media/index.html b/playground/tests/v-font-media/index.html index 9a1ed9cc13..1992256cff 100644 --- a/playground/tests/v-font-media/index.html +++ b/playground/tests/v-font-media/index.html @@ -67,5 +67,5 @@ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} /*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ .base-button[data-v-e4ca9d38]{--font-size:16;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:.0625em solid;border:calc(1/var(--font-size)*1em) solid;border-radius:.3125em;border-radius:calc(5/var(--font-size)*1em);color:currentColor;cursor:pointer;font-size:1em;font-size:calc(var(--font-size)/16*1em);outline:none;padding:.5em 1em;padding:calc(8/var(--font-size)*1em) calc(16/var(--font-size)*1em);transition:transform .1s ease-in;will-change:transform}.base-button[data-v-e4ca9d38]:hover{transform:scale(1.05)}.base-button[data-v-e4ca9d38]:active{transform:scale(.95)} -
    • Merriweather - 300 - normal - (orientation: portrait)
    font assign simple by portrait
    • Merriweather - 300 - italic - (orientation: landscape)
    font assign simple by landscape
    • Merriweather - 700 - italic - (max-width: 479px)
    font assign simple by max 479px
    • Merriweather - 400 - normal - (min-width: 480px)
    font assign simple by 480px
    • Merriweather - 400 - italic - (min-width: 960px)
    font assign simple by 960px
    • Merriweather - 700 - normal - strong - (min-width: 1440px)
    font assign with selector by 1440px

Critical - v-font with media

    • Montserrat Alternates - 300 - normal - (orientation: portrait)
    font assign simple by portrait
    • Montserrat Alternates - 300 - italic - (orientation: landscape)
    font assign simple by landscape
    • Montserrat Alternates - 700 - italic - (max-width: 479px)
    font assign simple by max 479px
    • Montserrat Alternates - 400 - normal - (min-width: 480px)
    font assign simple by 480px
    • Montserrat Alternates - 400 - italic - (min-width: 960px)
    font assign simple by 960px
    • Montserrat Alternates - 700 - normal - strong - (min-width: 1440px)
    font assign with selector by 1440px

Lazy - v-font with media

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +
    • Merriweather - 300 - normal - (orientation: portrait)
    font assign simple by portrait
    • Merriweather - 300 - italic - (orientation: landscape)
    font assign simple by landscape
    • Merriweather - 700 - italic - (max-width: 479px)
    font assign simple by max 479px
    • Merriweather - 400 - normal - (min-width: 480px)
    font assign simple by 480px
    • Merriweather - 400 - italic - (min-width: 960px)
    font assign simple by 960px
    • Merriweather - 700 - normal - strong - (min-width: 1440px)
    font assign with selector by 1440px

Critical - v-font with media

    • Montserrat Alternates - 300 - normal - (orientation: portrait)
    font assign simple by portrait
    • Montserrat Alternates - 300 - italic - (orientation: landscape)
    font assign simple by landscape
    • Montserrat Alternates - 700 - italic - (max-width: 479px)
    font assign simple by max 479px
    • Montserrat Alternates - 400 - normal - (min-width: 480px)
    font assign simple by 480px
    • Montserrat Alternates - 400 - italic - (min-width: 960px)
    font assign simple by 960px
    • Montserrat Alternates - 700 - normal - strong - (min-width: 1440px)
    font assign with selector by 1440px

Lazy - v-font with media

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/v-font-scroll/_payload.json b/playground/tests/v-font-scroll/_payload.json index 33e7cebfc2..5ea604eb16 100644 --- a/playground/tests/v-font-scroll/_payload.json +++ b/playground/tests/v-font-scroll/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416094581] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997817747] \ No newline at end of file diff --git a/playground/tests/v-font-scroll/index.html b/playground/tests/v-font-scroll/index.html index b13e3590ff..a941094a8c 100644 --- a/playground/tests/v-font-scroll/index.html +++ b/playground/tests/v-font-scroll/index.html @@ -81,5 +81,5 @@ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} /*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ .base-button[data-v-e4ca9d38]{--font-size:16;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:.0625em solid;border:calc(1/var(--font-size)*1em) solid;border-radius:.3125em;border-radius:calc(5/var(--font-size)*1em);color:currentColor;cursor:pointer;font-size:1em;font-size:calc(var(--font-size)/16*1em);outline:none;padding:.5em 1em;padding:calc(8/var(--font-size)*1em) calc(16/var(--font-size)*1em);transition:transform .1s ease-in;will-change:transform}.base-button[data-v-e4ca9d38]:hover{transform:scale(1.05)}.base-button[data-v-e4ca9d38]:active{transform:scale(.95)} -
Merriweather - 300 - normal
Merriweather - 300 - italic
Merriweather - 400 - normal
Merriweather - 400 - italic
Merriweather - 700 - normal
Merriweather - 700 - italic

Horizontal Scroll - v-font

Montserrat Alternates - 300 - normal
Montserrat Alternates - 300 - italic
Montserrat Alternates - 400 - normal
Montserrat Alternates - 400 - italic
Montserrat Alternates - 700 - normal
Montserrat Alternates - 700 - italic

Vertical Scroll - v-font

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +
Merriweather - 300 - normal
Merriweather - 300 - italic
Merriweather - 400 - normal
Merriweather - 400 - italic
Merriweather - 700 - normal
Merriweather - 700 - italic

Horizontal Scroll - v-font

Montserrat Alternates - 300 - normal
Montserrat Alternates - 300 - italic
Montserrat Alternates - 400 - normal
Montserrat Alternates - 400 - italic
Montserrat Alternates - 700 - normal
Montserrat Alternates - 700 - italic

Vertical Scroll - v-font

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/v-font/_payload.json b/playground/tests/v-font/_payload.json index dc593dbb5a..9b632e2c5c 100644 --- a/playground/tests/v-font/_payload.json +++ b/playground/tests/v-font/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416094611] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997817783] \ No newline at end of file diff --git a/playground/tests/v-font/index.html b/playground/tests/v-font/index.html index c7376cdd72..186012c522 100644 --- a/playground/tests/v-font/index.html +++ b/playground/tests/v-font/index.html @@ -65,5 +65,5 @@ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} /*! purgecss start ignore */#nuxt-booster-layer{height:0;width:0}#nuxt-booster-button-init-nojs,#nuxt-booster-layer input,#nuxt-booster-layer input:checked+*,#nuxt-booster-message-low-battery,#nuxt-booster-message-nojs,#nuxt-booster-message-reduced-bandwidth,#nuxt-booster-message-unsupported-browser,#nuxt-booster-message-weak-hardware,.nuxt-booster-button-init-nojs{display:none}/*! purgecss end ignore */ .base-button[data-v-e4ca9d38]{--font-size:16;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:.0625em solid;border:calc(1/var(--font-size)*1em) solid;border-radius:.3125em;border-radius:calc(5/var(--font-size)*1em);color:currentColor;cursor:pointer;font-size:1em;font-size:calc(var(--font-size)/16*1em);outline:none;padding:.5em 1em;padding:calc(8/var(--font-size)*1em) calc(16/var(--font-size)*1em);transition:transform .1s ease-in;will-change:transform}.base-button[data-v-e4ca9d38]:hover{transform:scale(1.05)}.base-button[data-v-e4ca9d38]:active{transform:scale(.95)} -
    • Merriweather - 400 - normal
    font assign simple
    • Merriweather - 700 - normal - strong
    font assign by single selector
    • Merriweather - 700 - normal - strong
    • Merriweather - 400 - italic - em
    font assign by multiple variances
    • Merriweather - 400 - italic - em, span
    font assign by multiple selectors
    • Merriweather - 700 - italic - strong > em
    font assign by deep selector

Critical - v-font

    • Montserrat Alternates - 400 - normal
    font assign simple

    • Montserrat Alternates - 700 - normal
    font assign by single selector
    • Montserrat Alternates - 700 - normal - strong
    • Montserrat Alternates - 400 - italic - em
    font assign by multiple variances

    • Montserrat Alternates - 400 - italic - em, span
    font assign by multiple selectors

    • Montserrat Alternates - 700 - italic - strong > em
    font assign by deep selector

Lazy - v-font

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +
    • Merriweather - 400 - normal
    font assign simple
    • Merriweather - 700 - normal - strong
    font assign by single selector
    • Merriweather - 700 - normal - strong
    • Merriweather - 400 - italic - em
    font assign by multiple variances
    • Merriweather - 400 - italic - em, span
    font assign by multiple selectors
    • Merriweather - 700 - italic - strong > em
    font assign by deep selector

Critical - v-font

    • Montserrat Alternates - 400 - normal
    font assign simple

    • Montserrat Alternates - 700 - normal
    font assign by single selector
    • Montserrat Alternates - 700 - normal - strong
    • Montserrat Alternates - 400 - italic - em
    font assign by multiple variances

    • Montserrat Alternates - 400 - italic - em, span
    font assign by multiple selectors

    • Montserrat Alternates - 700 - italic - strong > em
    font assign by deep selector

Lazy - v-font

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/vimeo/_payload.json b/playground/tests/vimeo/_payload.json index 6ec9fa4e44..cd6e100ba7 100644 --- a/playground/tests/vimeo/_payload.json +++ b/playground/tests/vimeo/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416094684] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997817822] \ No newline at end of file diff --git a/playground/tests/vimeo/index.html b/playground/tests/vimeo/index.html index a56f3d4edf..4874758f47 100644 --- a/playground/tests/vimeo/index.html +++ b/playground/tests/vimeo/index.html @@ -85,5 +85,5 @@ /*! purgecss start ignore */.nuxt-booster-picture[data-v-fc7d4048]{box-sizing:border-box;display:block;position:relative;width:100%}.nuxt-booster-picture img[data-v-fc7d4048]{bottom:0;box-sizing:border-box;left:0;position:absolute;right:0;top:0}.nuxt-booster-picture[data-v-fc7d4048]:before{box-sizing:border-box;content:"";display:block;position:relative}@supports (aspect-ratio:1){.nuxt-booster-picture[data-v-fc7d4048],.nuxt-booster-picture img[data-v-fc7d4048]{position:static;position:unset}.nuxt-booster-picture img[data-v-fc7d4048]{bottom:auto;bottom:unset;left:auto;left:unset;right:auto;right:unset;top:auto;top:unset}.nuxt-booster-picture[data-v-fc7d4048]:before{display:none}}/*! purgecss end ignore */ /*! purgecss start ignore */.nuxt-booster-image[data-v-3621510f]{content-visibility:auto;display:block;height:auto;-o-object-fit:cover;object-fit:cover;width:100%}/*! purgecss end ignore */ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} -

Vimeo 1

Vimeo 2

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +

Vimeo 1

Vimeo 2

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/weak-hardware-overlay/_payload.json b/playground/tests/weak-hardware-overlay/_payload.json index 504f383d3e..856df908a7 100644 --- a/playground/tests/weak-hardware-overlay/_payload.json +++ b/playground/tests/weak-hardware-overlay/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416094713] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997817872] \ No newline at end of file diff --git a/playground/tests/weak-hardware-overlay/index.html b/playground/tests/weak-hardware-overlay/index.html index 05864dea8c..659dc07824 100644 --- a/playground/tests/weak-hardware-overlay/index.html +++ b/playground/tests/weak-hardware-overlay/index.html @@ -24,5 +24,5 @@
WeakHardwareOverlay
Area is disabled for performance reasons.

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • slow connection
  • weak hardware
  • low battery
- \ No newline at end of file +
WeakHardwareOverlay
Area is disabled for performance reasons.

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • slow connection
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/playground/tests/youtube/_payload.json b/playground/tests/youtube/_payload.json index 44aa09db74..26dc12b530 100644 --- a/playground/tests/youtube/_payload.json +++ b/playground/tests/youtube/_payload.json @@ -1 +1 @@ -[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733416094783] \ No newline at end of file +[{"data":1,"prerenderedAt":3},["ShallowReactive",2],{},1733997817874] \ No newline at end of file diff --git a/playground/tests/youtube/index.html b/playground/tests/youtube/index.html index 96c67c20cd..a4b21ce519 100644 --- a/playground/tests/youtube/index.html +++ b/playground/tests/youtube/index.html @@ -86,5 +86,5 @@ /*! purgecss start ignore */.nuxt-booster-picture[data-v-fc7d4048]{box-sizing:border-box;display:block;position:relative;width:100%}.nuxt-booster-picture img[data-v-fc7d4048]{bottom:0;box-sizing:border-box;left:0;position:absolute;right:0;top:0}.nuxt-booster-picture[data-v-fc7d4048]:before{box-sizing:border-box;content:"";display:block;position:relative}@supports (aspect-ratio:1){.nuxt-booster-picture[data-v-fc7d4048],.nuxt-booster-picture img[data-v-fc7d4048]{position:static;position:unset}.nuxt-booster-picture img[data-v-fc7d4048]{bottom:auto;bottom:unset;left:auto;left:unset;right:auto;right:unset;top:auto;top:unset}.nuxt-booster-picture[data-v-fc7d4048]:before{display:none}}/*! purgecss end ignore */ /*! purgecss start ignore */.nuxt-booster-image[data-v-3621510f]{content-visibility:auto;display:block;height:auto;-o-object-fit:cover;object-fit:cover;width:100%}/*! purgecss end ignore */ .preview-container[data-v-861695da]{display:flex;flex-direction:column;margin:3.125em 0;min-height:100vh;min-height:-webkit-fill-available;min-height:-moz-available;min-height:stretch}.preview-container[data-v-861695da]:first-child{margin-top:0}.preview-container[data-v-861695da]:last-child{margin-bottom:0}@media (orientation:landscape){.preview-container[data-v-861695da]{flex-direction:row}}@media (min-width:992px){.preview-container[data-v-861695da]{flex-direction:row}}.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{align-items:center;display:flex;height:50vh;justify-content:center;margin:0;overflow:hidden;width:100%}@media (orientation:landscape){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}@media (min-width:992px){.preview-container>.info[data-v-861695da],.preview-container>.preview[data-v-861695da]{height:100vh;width:50vw}}.preview-container .info[data-v-861695da]{font-size:2em}.preview-container .info p[data-v-861695da]{line-height:1.375;text-align:center}:is(.preview-container .info) p[data-v-861695da]{line-height:1.375;text-align:center}.preview-container .info button[data-v-861695da]{margin:0 auto;width:90%}:is(.preview-container .info) button[data-v-861695da]{margin:0 auto;width:90%}.preview-container .preview[data-v-861695da]{font-size:1.125em;--bg-opacity:1;background-color:#0006}@media (prefers-color-scheme:dark){.preview-container .preview[data-v-861695da]{background-color:#fff6}}.preview-container .preview[data-v-861695da] img,.preview-container .preview img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}:is(.preview-container .preview[data-v-861695da]) img,:is(.preview-container .preview) img[data-v-861695da]{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.preview-container .preview[data-v-861695da] picture{height:100%;width:100%}:is(.preview-container .preview[data-v-861695da]) picture{height:100%;width:100%}.preview-container .preview>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}:is(.preview-container .preview)>article[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;text-align:center;width:100%}.preview-container .preview>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}:is(.preview-container .preview)>div[data-v-861695da]{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.preview-container .preview>div[data-v-861695da] .list{list-style:none;margin:0;padding:0}:is(:is(.preview-container .preview)>div[data-v-861695da]) .list{list-style:none;margin:0;padding:0}.preview-container .preview>div[data-v-861695da] .list>*{margin:.625em 0}:is(:is(:is(.preview-container .preview)>div[data-v-861695da]) .list)>*{margin:.625em 0}.preview-container .preview>div[data-v-861695da] .test-iframe{height:100%;position:relative;width:100%}:is(:is(.preview-container .preview)>div[data-v-861695da]) .test-iframe{height:100%;position:relative;width:100%} -

Youtube 1

Youtube 2

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
- \ No newline at end of file +

Youtube 1

Youtube 2

Sorry, but you will have a limited user experience due to a…

  • disabled javascript
  • outdated browser
  • reduced-bandwidth
  • weak hardware
  • low battery
+ \ No newline at end of file diff --git a/v2/classes/loading-spinner.html b/v2/classes/loading-spinner.html index fb40f6f53a..1f424d8373 100644 --- a/v2/classes/loading-spinner.html +++ b/v2/classes/loading-spinner.html @@ -19,7 +19,7 @@
Skip to content

LoadingSpinner

Path: #booster/components/BoosterImage/classes/LoadingSpinner.js

The LoadingSpinner instance describes the visual appearance of the loading state in the BoosterImage. This can be defined globally via the module settings or at the specific components.

js
new LoadingSpinner({dataUri, size, backgroundColor});

dataUri

  • Type: String

Defines the source of the loader. (e.g. @/assets/spinner/three-circles.svg)

size

  • Type: String

Defines the size of the loader. Use css background-size definition. (e.g. 100px)

backgroundColor

  • Type: String

Defines the background color of the loader. Use css color definition. (e.g. #fff)

- + \ No newline at end of file diff --git a/v2/components/booster-iframe.html b/v2/components/booster-iframe.html index 596ff19e6c..9e45fce4fc 100644 --- a/v2/components/booster-iframe.html +++ b/v2/components/booster-iframe.html @@ -40,7 +40,7 @@ @load="console.log('Iframe Loaded!')" @enter="console.log('Iframe enter viewport!')" />
NameDescription
loadTriggered when Iframe has finished loading.
enterTriggered when component has reached the viewport.
- + \ No newline at end of file diff --git a/v2/components/booster-image.html b/v2/components/booster-image.html index f53fb1a01d..9b40adc6cf 100644 --- a/v2/components/booster-image.html +++ b/v2/components/booster-image.html @@ -60,7 +60,7 @@ ]

modifiers

You can give separate modifiers to each source. This overwrites the global ones of the preset if available.

Learn more about modifiers:

preset

If a preset is set on a source, the globally defined one is ignored.

This means that a separate preset can be specified for each source.

Learn more about preset:

provider

If a provider is set on a source, the globally defined one is ignored.

This means that a separate provider can be specified for each source.

Learn more about provider:

loadingSpinner

Sets a loading spinner definition of type LoadingSpinner, this describes the visual appearance of the loading state.

alt

Image alternative Text.

MDN - HTMLImageElement.alt

title

Image Title.

MDN - HTMLElement.title

crossorigin

If not set, the global crossorigin is used this.$booster.crossorigin.

Learn more about crossorigin option

MDN - HTML.Attributes.crossorigin

critical

Set component as critical component.

Learn more about critical components

Events

html
<booster-image 
   @load="console.log('Image Loaded!')" 
 />
NameDescription
loadTriggered when the image resource has been completely loaded.
- + \ No newline at end of file diff --git a/v2/components/booster-layer.html b/v2/components/booster-layer.html index 5049b02524..0e7c45106a 100644 --- a/v2/components/booster-layer.html +++ b/v2/components/booster-layer.html @@ -71,7 +71,7 @@ </button> </div> </booster-layer>

Force App initialization

For Unsupported-Browser and Insufficient Hardware events, an onclick event must also be set with the id.

In the event, the global variable __NUXT_BOOSTER_AUTO_INIT__ must be set to true.

These are needed if the user has already reacted before the initial Javascript has been loaded. After the javascript has been successfully loaded, the app is automatically initialised.

VariableTypeDescriptionDefault
__NUXT_BOOSTER_AUTO_INIT__BooleanIf set, initialisation continues after the javascript has been fully loaded.false
- + \ No newline at end of file diff --git a/v2/components/booster-picture.html b/v2/components/booster-picture.html index 0b0645738b..b9e2e14e20 100644 --- a/v2/components/booster-picture.html +++ b/v2/components/booster-picture.html @@ -58,7 +58,7 @@ ]

formats

Overrides the pictureFormats property defined in the module options.

Defines the formats that are to be generated and provided as source in the Picture.
Is used to offer the correct image type for the browser.

WARNING

Formats can also be specified as OR condition (jpg|jpeg|png|gif). This is important when using JPGs and PNGs with the same format configuration.

loadingSpinner

Sets a loading spinner definition of type LoadingSpinner, this describes the visual appearance of the loading state of the BoosterImage contained in the BoosterPicture.

alt

Image alternative Text.

MDN - HTMLImageElement.alt

title

Image Title.

MDN - HTMLElement.title

crossorigin

If not set, the global crossorigin is used this.$booster.crossorigin.

Learn more about crossorigin option

MDN - HTML.Attributes.crossorigin

sortSources

If set, the sources are sorted by the media properties.

This is made possible by sort-css-media-queries.

critical

Set component as critical component.

Learn more about critical components

Events

html
<booster-picture 
   @load="console.log('Loaded!')" 
 />
NameDescription
loadTriggered when the image resource has been completely loaded.
- + \ No newline at end of file diff --git a/v2/components/booster-vimeo.html b/v2/components/booster-vimeo.html index 74f9428e60..ad9b0ae3bc 100644 --- a/v2/components/booster-vimeo.html +++ b/v2/components/booster-vimeo.html @@ -71,7 +71,7 @@ @ready="console.log('Player Ready!')" @playing="console.log('Player Playing!')" />
NameDescription
readyTriggered when Vimeo Player-SDK is completely loaded.
playingTriggered when video is finished loading and playing.
- + \ No newline at end of file diff --git a/v2/components/booster-youtube.html b/v2/components/booster-youtube.html index dd9abb0fb7..eb9ec789c7 100644 --- a/v2/components/booster-youtube.html +++ b/v2/components/booster-youtube.html @@ -68,7 +68,7 @@ @ready="console.log('Player Ready!')" @playing="console.log('Player Playing!')" />
NameDescription
readyTriggered when Youtube-API is completely loaded.
playingTriggered when video is finished loading and playing.
- + \ No newline at end of file diff --git a/v2/concept.html b/v2/concept.html index 74bbc4fb35..f038343bf6 100644 --- a/v2/concept.html +++ b/v2/concept.html @@ -19,7 +19,7 @@
Skip to content

Concept

Current Situation

The loading behavior of webpages based on NuxtJS is designed in such a way that all necessary Javascript resources are preloaded and directly initialized with the initial load of the page. However, this behavior creates a negative impact on the Lighthouse Performance Score (TTI) for larger pages that have an increased initial load of additional resources, such as fonts, images, plugins, modules (@nuxtjs/i18n, ...).

Excursus

The Lighthouse Test is not a tool to make a general statement about the quality of a website programming. Lighthouse rather tries to map a metric for the usability of a page from the user's point of view. This includes accessibility, best practices, SEO and of course performance.

This last point is often misinterpreted by developers. If you want to implement features that increase usability for the user (interactions/more complex animations, ...), this will always have an impact on performance in the Lighthouse Test for larger website projects, as the corresponding Javascript must be loaded for this. Finally, Lighthouse does also not rate the design, but the accessibility (size of click areas, etc.) of a website. You should therefore not ask yourself the following question: "How can I fully optimize my JavaScript to achieve a Lighthouse score of 100/100?". You have to ask yourself much more the question: "What is especially important to a user with low bandwidth or weak hardware on my site?".

The answer to this is relatively simple: the content must be accessible and you must be able to get to the information you need quickly.

No more and no less.

The user doesn't need any fancy slider animations and parallax effects that can only be implemented with certain libraries. Or a softload mechanism to get to more pages in a more elegant and animated way, but which initially needs an increased amount of javascript logic. All he wants is that information is retrievable reasonably fast and he can click through the presence.

Problem

The good news is that the NuxtJS SSR build provides the right foundation. The content is already in the form of HTML and CSS and can be used without Javascript. But what is missing

  • is a fully automated preload logic that allows component and viewport based handling and prioritization of the individual resources (FCP, LCP, CLS)
  • is a logic that enables a perfomance-oriented initialization of the javascript (TTI, TBT)

These two central points are handled by Nuxt Booster and enable a fast and resource-saving loading behavior of the website.

Approach

Over a longer period of time, we analyzed the Google Lighthouse test in more detail and approached the topic with the help of use cases. We did not start with the best case for page content (one image, one font, minimal javascript), but with the worst case (many images, many fonts, large Javascript files, ...). So we avoided to develop only a solution for simple SinglePages. Our claim was much more to create a generalistic, performant solution even with a CMS connection and dynamic component compositions per page. All our thoughts are based on HTTP/2 request prioritization and the lazy hydration approach. Initial resources are prioritized by preload and all further data is reloaded viewport-based.

Insights & Solutions

During the tests, we gained the following insights, which we would like to share with you, but which also allow us to draw conclusions regarding the performance optimization of the initial loading process and which have been incorporated into the Nuxt Booster solution.

Critical Render Path

The critical render path is the core of a high-performance and efficient loading and rendering behavior of a website. It is important that components and resources in the viewport are loaded and executed with priority so that the user can be provided with a functioning page as quickly as possible. A browser is not able to recognize this fully automatically to dynamically adapt the loading behavior. Some attempts have been made in the past to systematically identify the critical render path.However, this has the consequence that every generated page in a virtual browser has to be analyzed in given viewport sizes, which slows down the deployment process and makes it more error-prone. For this reason, we (the developers) will be forced to provide the build process with appropriate hints in the form of a Critical Attribute on the affected component, so that an automated optimization by preloads, lazy hydration, etc. can be performed in response.

Font Loading

Fonts are the great mystery on the Internet. For more complex designs it is not uncommon that more than 6 font files have to be loaded. It would be desirable if there were many more variable fonts, but the reality is usually different. Often, developers are forced to register tons of fonts with different font styles. So it can happen that the website needs a total count of 12 font files, which have to be loaded initially to achieve the right visual result on the whole page.

This is a real performance problem. If you look for solutions, you like to hear

  • don't use WebFonts that have to be loaded
  • use another optimized font
  • reduce the number of used fonts
  • embed the fonts via Base64

You will find some articles about font loading. But most of them are more than 3 years old. Summary: not much happened here. A nice and recommendable list of different strategies can be found at web-font-loading-recipes or comprehensive-webfonts. From this it can be deduced that there is still no universal solution to the problem. However, it is possible to approach the issue very efficiently by using a preload strategy and setting classes accordingly. However, this does not make the handling of the fonts any easier. On the one hand, the preloads have to be defined per page and on the other hand, the CSS in the respective component has to be activated with the corresponding font declaration per class on demand. This is manageable for smaller projects in a 1 person team. But if several people are working in parallel, it can quickly become a nightmare. This will inevitably lead to the fact that the approach will not be accepted by the team and the optimization will be optimized out of the project in the long run.

INFO

A few words about Google Fonts: If possible, the FontFaces should always be included directly as Woff/Woff2 files via inline style. The loading mechanism via external CSS file, as it is the case with Google Fonts, creates an additional network roundtrip, which delays the loading of the actual font files.

The strategy mentioned above makes sense, but is hardly implementable with the current tools. For this reason, we are introducing Directive v-font, which takes care of the outlined behavior in a fully automated way and thus represents a truly relevant solution even on larger projects. Combined with the lazy hydration approach, the relevant fonts can be declared and loaded per component. The preloads are controlled via the critical attribute. With the help of this loading strategy, a FOUT (flash of unstyled text) and CLS can be massively reduced or eliminated. If no javascript is activated on the end device, all fonts are automatically activated via CSS.

Image Loading

For image compression and different image formats, the module nuxt-optimized-images was popularly used in the nuxt world in the past. The downside, however, is that this approach is not particularly CMS and deployment friendly. With each image change, a full build process had to be initiated. For this reason, we use the nuxt-image module, as this takes advantage of a change in NuxtJS as of version 2.13.0. In this version update, the build was split into two separate processes (javascript compilation + page generation). With nuxt-optimized-images the full build process had to be run for every image change. This is no longer the case with nuxt-image. Here only the page generation process is necessary. As a result, deployment times for all content changes can be massively reduced.

We use the module in its complete form. However, we have redeveloped the nuxt-image and nuxt-picture components, as the current version does not fully meet our requirements. For example, we lacked an appropriate preloading and lazy hydration strategy. Although there is a native loading attribute on the image element that allows prioritization, the use for websites with a lot of images is still not optimal, because the distance-from-viewport threshold is still too generous and the loading performance can deteriorate unintentionally. For this we have implemented a corresponding SEO-compliant alternative, which loads the images only when the viewport is reached, but also provides the image sources for search engines via no-script tag. This way all relevant images can be displayed even if Javascript is disabled. Furthermore you can also define multiple image sources in the picture, so it is possible to display an image in portait mode with a 9/16 aspect-ratio (multiple renditions) and in landscape mode with a 16/9 aspect-ratio (multiple renditions).

Javascript Loading

NuxtJS follows the approach to load the core files (page, app, payload, vendor, state, etc.) as fast and efficient as possible via (module-)preload from the client. This also makes total sense if you want to deliver an SPA. For the SSR build, however, we modified the delivery a bit. The many parallel downloads (fonts, images, js, ...) have a negative impact from a performance perspective. This effect increases when the javascript files grow in size due to modules and plugins. It would make sense if the initial package is kept small and only the absolutely necessary resources that can trigger the further initialization process are transferred via dynamic import. This leaves enough bandwidth to load the remaining resources (fonts, images).

This loading behavior only makes sense with an SSR build, since the full page-related static content can already be delivered and rendered with the HTML and the included CSS. This means that the user does not notice any time lags and the page is still usable. Another advantage: If the bandwidth is low, a basic functionality of the page (links, ...) can be ensured thanks to the SSR build.

RequestIdleCallback

The TimeRemaining function of the IdleDeadline object continuously returns a value <= 10 in the Lighthouse Test (simulated Motorola G4). This can be seen as an indicator for weak hardware on the end device and allows the following conclusion. If there are not enough hardware resources available to execute the JavaScript quickly, this process is suppressed. Who needs optional functionality that takes a long time to initialize and possibly leads to a temporary freeze in the browser.

We use this effect by executing the intial javascript process and the component initialization in the RequestIdleCallback, if we get a time slot >10ms from the device. Hereby we achieve a massive reduction of the TTI/TBT in the Lighthouse Test and on weak hardware, because the javascript execution is simply paused in the worst case until sufficient resources are available. This also prevents blocking of the MainThread.

Side effect: The timeslots in the Google Lighthouse Test are always <= 10ms, so no javascript will be initialized.

BoosterLayer

With the solutions described above, the user gets a functioning webpage displayed very quickly. However, the following situation can also occur on the end device:

  • no Javascript enabled
  • reduced bandwidth
  • weak hardware
  • unsupported browser

The reduced bandwidth or weak hardware should get a focus especially when larger amounts of data have to be transferred and executed, e.g. a ThreeJS component with more complex 3D objects. In this case, we should inform the user that the experience will be negatively affected and that there may be waiting times.

For this purpose, we provide an InfoLayer that is displayed when a minimum FCP time is exceeded, when the number of available CPU cores falls below a minimum level, when javascript is disabled or the users opens the page by an unsupported browser. The user can decide in this dialog box whether he wants to load the remaining resources despite the restrictions. If the user declines this dialog, only the fonts and images for the page will be loaded and no further javascript will be loaded or executed.

Conclusion

The findings and solutions described above have been incorporated and systematized in the Nuxt Booster module. Only in combination can they unfold their full functionality and ensure an overall optimization of the loading behavior. Overall we have reduced the following timing metrics ...

  • FCP
  • LCP
  • TTI
  • TBT

With this module we enable every developer in the NuxtJS context to achieve a Lighthouse Performance Score 100/100 and drastically reduce the development time for website performance optimization.

- + \ No newline at end of file diff --git a/v2/directives/v-font.html b/v2/directives/v-font.html index 2542cc9d0d..d327faadb0 100644 --- a/v2/directives/v-font.html +++ b/v2/directives/v-font.html @@ -58,7 +58,7 @@ <div v-html="…" /> </div> </template> - + \ No newline at end of file diff --git a/v2/guide/caveats.html b/v2/guide/caveats.html index f4fcf40726..a6db960444 100644 --- a/v2/guide/caveats.html +++ b/v2/guide/caveats.html @@ -13,7 +13,7 @@ - + @@ -37,7 +37,7 @@ }); } } -</script>

Issues

Browser compatibility

You can use nuxt-booster with Internet Explorer 11 browser.

INFO

Note that there is no optimization based on preloads in IE 11.

You need the following polyfills:

The PostCSS Plugin postcss-object-fit-images and following build.transpile entries for @nuxt/image:

For the polyfills, it is recommended to integrate them as a plugin, polyfills loading must follow a specific order.

You can see a example with live demo at Nuxt Booster Example.

Example

js
async function polyfills (){
+</script>

Issues

Browser compatibility

You can use nuxt-booster with Internet Explorer 11 browser.

INFO

Note that there is no optimization based on preloads in IE 11.

You need the following polyfills:

The PostCSS Plugin postcss-object-fit-images and following build.transpile entries for @nuxt/image:

For the polyfills, it is recommended to integrate them as a plugin, polyfills loading must follow a specific order.

You can see a example with live demo at Nuxt Booster Example.

Example

js
async function polyfills (){
 
   if (!('IntersectionObserver' in global)) {
     await import('intersection-observer');
@@ -54,7 +54,7 @@
 
 }
 
-polyfills ();

js
{
+polyfills ();

js
{
   build: {
     
     transpile: ['@nuxt/image', 'image-meta'],
@@ -98,7 +98,7 @@
     }
   };
 </script>
- + \ No newline at end of file diff --git a/v2/guide/options.html b/v2/guide/options.html index b76e693789..c56ab1671a 100644 --- a/v2/guide/options.html +++ b/v2/guide/options.html @@ -76,7 +76,7 @@ size: '100px', backgroundColor: 'grey' }
KeyTypeRequiredDescriptionDefault
dataUriStringnoDefines the source of the loader. (e.g. @/assets/spinner/three-circles.svg)undefined
sizeStringnoDefines the size of the loader. Use css background-size definition.100px
backgroundColorStringnoDefines the background color of the loader. Use css color definition.grey

disableNuxtImage

If set, @nuxt/image will not be integrated.

DANGER

Note that the use of BoosterImage, BoosterPicture, BoosterVimeo and BoosterYoutube is not supported if @nuxt/image is not integrated.

- + \ No newline at end of file diff --git a/v2/guide/setup.html b/v2/guide/setup.html index 0df6036e12..d1b276ae1a 100644 --- a/v2/guide/setup.html +++ b/v2/guide/setup.html @@ -13,18 +13,18 @@ - + -
Skip to content

Setup

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster@2
bash
npm install nuxt-booster@2

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
+    
Skip to content

Setup

Check the Nuxt.js documentation for more information about installing and using modules in Nuxt.js.

Installation

Install nuxt-booster as a dependency to your project:

bash
yarn add nuxt-booster@2
bash
npm install nuxt-booster@2

Add nuxt-booster to the modules section of nuxt.config.js:

@nuxt/image

Nuxt Booster uses the module @nuxt/image, if this is not already present, it will be integrated automatically.

It is necessary for the use of the components BoosterYoutube and BoosterVimeo to add aliases and domains to the @nuxt/image options. These are needed to retrieve the images from Youtube and Vimeo.

js
{
   domains: ['img.youtube.com', 'i.vimeocdn.com'],
   alias: {
     youtube: 'https://img.youtube.com',
     vimeo: 'https://i.vimeocdn.com',
   }
-}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
+}

More about @nuxt/image module options can be found here.

Example Configuration

js
{
   modules: [
     'nuxt-booster'
   ],
@@ -119,7 +119,7 @@
     }
   }
 }

See module options.

- + \ No newline at end of file diff --git a/v2/guide/usage.html b/v2/guide/usage.html index e721ed759f..32ed0cfaa5 100644 --- a/v2/guide/usage.html +++ b/v2/guide/usage.html @@ -36,7 +36,7 @@ } } </script>

INFO

The booster components will be expanded in the future. If you have explicit wishes, please send us a feature request or directly a pull request with the corresponding feature 😃

- + \ No newline at end of file diff --git a/v2/index.html b/v2/index.html index 3a6de3f53f..6cd7cd9d07 100644 --- a/v2/index.html +++ b/v2/index.html @@ -20,7 +20,7 @@
Skip to content
nuxt boosternuxt booster

Module for NuxtJS.

WARNING

You are reading Nuxt Booster v2 docs. For Nuxt 3 go to the v3 docs

Nuxt Booster takes over the lighthouse performance optimization of your generated website.

In order to achieve a performance score of 100/100, only the necessary resources located in the current viewport may be initialized when the page is loaded. This includes images, fonts and the js-modules. Until now, there has been no practical and usable concept to help developers maintain an overview and enable accurate targeting in NuxtJS projects.

This module addresses this problem and provides a holistic approach to intelligently load the necessary viewport related resources to reduce FCP, DCL, TTI, TBT and CLS.

We didn't reinvent the whole wheel. We adapt the lazy hydration concept of Markus Oberlehner to load js components in an efficient way, use the nuxt/image module as a base to retrieve optimized image resolutions for our picture and image components and add some new stuff to obtain a holistic solution.

Requirements

  • NodeJS >= 12.x.x
  • NuxtJS >= 2.15.0

Features

We provide the following CMS-friendly features:

  • dynamic loading of viewport based page resources like fonts, components, pictures, images and iframes
  • optional blocking of javascript execution by initial performance measuring
  • optimized initial load of javascript files by eliminating of unnecessary javascript files
  • prevents the loading of unnecessary resources (including components) that are outside the current viewport.
  • optional info layer concept to inform users about a reduced UX when bandwidth or hardware is compromised.
  • completely new approach of font declaration
  • optimized picture component (supports viewport based sources e.g. landscape/portrait)
  • optimized image component
  • supports SEO-friendly lazy hydration mode (picture + image)
  • optimized youtube/vimeo component (auto generated poster image in different resolutions)

Results

  • delivery of the minimum required resources based on the current viewport
  • if you use the tools as specified you will get a lighthouse performance score of 100/100
- + \ No newline at end of file