From 8da040b89a3051e92f3acca0d7b5e22353e5c26b Mon Sep 17 00:00:00 2001 From: Fredrik Strand Oseberg Date: Wed, 27 Aug 2025 15:54:32 +0200 Subject: [PATCH] Fix/website performance (#10489) --- .github/workflows/dependency-review.yml | 2 +- website/docusaurus.config.ts | 48 +- website/global.js | 3 - website/package.json | 1 + website/src/components/VideoContent.jsx | 111 ++- .../src/components/VideoContent.module.css | 129 ++++ website/src/css/custom.css | 32 +- .../DocItem/Footer/GitHubContributors.jsx | 2 +- website/src/theme/Root.tsx | 161 +++++ website/yarn.lock | 650 +++++++++++++++++- 10 files changed, 1066 insertions(+), 73 deletions(-) delete mode 100644 website/global.js create mode 100644 website/src/components/VideoContent.module.css create mode 100644 website/src/theme/Root.tsx diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 9b6c2210a0..d50ec086be 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -22,5 +22,5 @@ jobs: uses: actions/dependency-review-action@v4 with: fail-on-severity: moderate - allow-licenses: Apache-2.0, MIT, BSD-2-Clause, BSD-3-Clause, ISC, 0BSD, CC0-1.0, Unlicense, BlueOak-1.0.0, CC-BY-4.0, Artistic-2.0, PSF-2.0 + allow-licenses: Apache-2.0, MIT, BSD-2-Clause, BSD-3-Clause, ISC, 0BSD, CC0-1.0, Unlicense, BlueOak-1.0.0, CC-BY-4.0, Artistic-2.0, PSF-2.0, MPL-2.0 comment-summary-in-pr: always diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index e2aa0effc0..0dd5d6b442 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -64,6 +64,9 @@ const getUnleashRepoStars = async () => { export default async function createConfigAsync(): Promise { const stars = await getUnleashRepoStars(); return { + future: { + experimental_faster: true, // turns Docusaurus Faster on globally + }, title: 'Unleash Documentation', tagline: 'The enterprise ready feature flag service', url: 'https://docs.getunleash.io', @@ -81,6 +84,17 @@ export default async function createConfigAsync(): Promise { // expose env vars etc here environment: process.env.NODE_ENV, }, + headTags: [ + { + tagName: 'link', + attributes: { + rel: 'preload', + href: '/img/unleash_logo_dark.svg', + as: 'image', + type: 'image/svg+xml', + }, + }, + ], themeConfig: { defaultMode: 'light', disableSwitch: true, @@ -90,6 +104,9 @@ export default async function createConfigAsync(): Promise { apiKey: 'dc9c4491fcf9143ee34015f22d1dd9d6', indexName: 'getunleash', }, + theme: { + customCss: './src/css/custom.css', + }, metadata: [ { name: 'og:image:width', content: '1200' }, { name: 'og:image:height', content: '630' }, @@ -421,16 +438,11 @@ class="header-github-link" remarkPlugins: [[pluginNpm2Yarn, { sync: true }]], docItemComponent: '@theme/ApiItem', sidebarPath: './sidebars.ts', + breadcrumbs: true, }, theme: { customCss: './src/css/custom.css', }, - googleAnalytics: { - trackingID: 'UA-134882379-1', - }, - googleTagManager: { - containerId: 'GTM-KV5PRR2', - }, sitemap: { changefreq: 'weekly', lastmod: 'date', @@ -902,29 +914,5 @@ class="header-github-link" 'docusaurus-theme-openapi-docs', // Allows use of @theme/ApiItem and other components '@docusaurus/theme-mermaid', ], - scripts: [ - { - src: 'https://widget.kapa.ai/kapa-widget.bundle.js', // See configuration: https://docs.kapa.ai/integrations/website-widget/configuration - 'data-website-id': '1d187510-1726-4011-b0f7-62742ae064ee', - 'data-project-name': 'Unleash', - 'data-project-color': '#1A4049', - 'data-project-logo': - 'https://cdn.getunleash.io/uploads/2024/05/logo-unleash-white.svg', - 'data-modal-image': - 'https://cdn.getunleash.io/uploads/2022/05/logo.png', - 'data-button-position-right': '0', - 'data-button-border-radius': '10px 0px 0px 10px', - 'data-button-width': '80px', - 'data-button-height': '100px', - 'data-button-image-height': '55px', - 'data-button-image-width': '55px', - 'data-button-text-font-weight': '400', - 'data-button-text-font-size': '16px', - 'data-button-text-font-family': '"Sen", sans-serif', - 'data-button-text': 'ASK AI', - defer: true, - }, - ], - clientModules: ['./global.js'], }; } diff --git a/website/global.js b/website/global.js deleted file mode 100644 index 035e2ee1b0..0000000000 --- a/website/global.js +++ /dev/null @@ -1,3 +0,0 @@ -if(typeof document !== 'undefined') { - !function(){var e,t,n;e="5fe670e3422303a",t=function(){Reo.init({clientID:"5fe670e3422303a"})},(n=document.createElement("script")).src="https://static.reo.dev/"+e+"/reo.js",n.async=!0,n.onload=t,document.head.appendChild(n)}(); -} diff --git a/website/package.json b/website/package.json index e69ccbfb16..5012a67782 100644 --- a/website/package.json +++ b/website/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@docusaurus/core": "^3.7.0", + "@docusaurus/faster": "^3.8.1", "@docusaurus/plugin-client-redirects": "^3.7.0", "@docusaurus/plugin-content-docs": "^3.7.0", "@docusaurus/plugin-google-analytics": "^3.7.0", diff --git a/website/src/components/VideoContent.jsx b/website/src/components/VideoContent.jsx index 3e6e6b0d40..ef908ead83 100644 --- a/website/src/components/VideoContent.jsx +++ b/website/src/components/VideoContent.jsx @@ -1,29 +1,98 @@ // biome-ignore lint/correctness/noUnusedImports: Needs this for React to work -import React from 'react'; +import React, { useState, useCallback } from 'react'; import Admonition from '@theme/Admonition'; +import styles from './VideoContent.module.css'; + +// Extract YouTube video ID from various URL formats +const extractVideoId = (url) => { + const regex = + /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/; + const match = url.match(regex); + return match ? match[1] : null; +}; + +const LazyVideo = ({ url, title = 'YouTube video player' }) => { + const [isLoaded, setIsLoaded] = useState(false); + const videoId = extractVideoId(url); + + const handleLoad = useCallback(() => { + setIsLoaded(true); + }, []); + + if (!videoId) { + return ( + Invalid YouTube URL: {url} + ); + } + + if (!isLoaded) { + return ( +
e.key === 'Enter' && handleLoad()} + role='button' + tabIndex={0} + aria-label={`Load ${title}`} + > + {`${title} +
+ + + +
+ +
Click to load video
+
+ ); + } -const Component = ({ videoUrls }) => { return ( -
- {videoUrls ? ( - videoUrls.map((url) => ( -