Skip to content

Commit

Permalink
fixup! feat: improvement of the web perf
Browse files Browse the repository at this point in the history
  • Loading branch information
fpasquet committed Mar 31, 2023
1 parent 2bef38e commit fb5cf2a
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 53 deletions.
File renamed without changes.
6 changes: 6 additions & 0 deletions src/config/website/socialNetworks.ts
@@ -1,26 +1,32 @@
import { IconNameType } from '@eleven-labs/design-system';

export const socialNetworks: {
label: string;
iconName: Extract<IconNameType, 'rss' | 'facebook' | 'twitter' | 'linkedin' | 'welcometothejungle'>;
url: string;
}[] = [
{
label: 'RSS',
iconName: 'rss',
url: 'https://blog.eleven-labs.com/feed.xml',
},
{
label: 'Facebook',
iconName: 'facebook',
url: 'https://www.facebook.com/11Labs',
},
{
label: 'Twitter',
iconName: 'twitter',
url: 'https://www.twitter.com/eleven_labs/',
},
{
label: 'LinkedIn',
iconName: 'linkedin',
url: 'https://linkedin.com/company/eleven-labs',
},
{
label: 'Welcome to the Jungle',
iconName: 'welcometothejungle',
url: 'https://www.welcometothejungle.com/companies/eleven-labs',
},
Expand Down
Expand Up @@ -48,6 +48,7 @@ export const useFooterContainer = (): LayoutTemplateProps['footer'] => {
eventLabel: socialNetwork.iconName,
iconName: socialNetwork.iconName,
to: socialNetwork.url,
'aria-label': socialNetwork.label,
})),
languageLinks: AUTHORIZED_LANGUAGES.map((currentLang) => {
const isActive = currentLang === i18n.language;
Expand Down
@@ -1,20 +1,42 @@
import { useTitle } from 'hoofd';
import { useHead, useLink } from 'hoofd';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom';

import { googleSiteVerificationKey, themeColor } from '@/config/website';
import { useCookieConsentContainer } from '@/containers/LayoutTemplateContainer/useCookieConsentContainer';
import { useFooterContainer } from '@/containers/LayoutTemplateContainer/useFooterContainer';
import { useHeaderContainer } from '@/containers/LayoutTemplateContainer/useHeaderContainer';
import { getPathFile } from '@/helpers/assetHelper';
import { useLayoutEffect } from '@/hooks/useLayoutEffect';
import { LayoutTemplateProps } from '@/templates/LayoutTemplate';

export const useLayoutTemplateContainer = (): Omit<LayoutTemplateProps, 'children'> => {
const { t } = useTranslation();
const { t, i18n } = useTranslation();
const location = useLocation();
const header = useHeaderContainer();
const footer = useFooterContainer();
const cookieConsent = useCookieConsentContainer();
useTitle(t<string>('meta.title'));
useHead({
title: t<string>('meta.title'),
metas: [
{
name: 'google-site-verification',
content: googleSiteVerificationKey,
},
{
name: 'apple-mobile-web-app-title',
content: 'Blog Eleven Labs',
},
{
name: 'theme-color',
content: themeColor,
},
],
language: i18n.language,
});
useLink({ rel: 'apple-touch-icon', sizes: '120x120', href: getPathFile('/imgs/icons/apple-icon-120x120.png') });
useLink({ rel: 'apple-touch-icon', sizes: '152x152', href: getPathFile('/imgs/icons/apple-icon-152x152.png') });
useLink({ rel: 'apple-touch-icon', sizes: '180x180', href: getPathFile('/imgs/icons/apple-icon-180x180.png') });

/* eslint-disable @typescript-eslint/no-explicit-any */
useLayoutEffect(() => {
Expand Down
27 changes: 24 additions & 3 deletions src/entry-server.tsx
Expand Up @@ -14,7 +14,7 @@ import { HtmlTemplate, HtmlTemplateProps } from '@/templates/HtmlTemplate';
export type RenderOptions = {
request: Request;
i18n: i18n;
} & Pick<HtmlTemplateProps, 'links' | 'scripts'>;
} & Pick<HtmlTemplateProps, 'links' | 'styles' | 'scripts'>;

export const render = async (options: RenderOptions): Promise<string> => {
const dispatcher = createDispatcher();
Expand All @@ -37,9 +37,30 @@ export const render = async (options: RenderOptions): Promise<string> => {
);

const staticPayload = dispatcher.toStatic();
return ReactDOMServer.renderToString(
const html = ReactDOMServer.renderToString(
<React.StrictMode>
<HtmlTemplate staticPayload={staticPayload} content={content} scripts={options.scripts} links={options.links} />
<HtmlTemplate
lang={staticPayload.lang ?? options.i18n.language}
title={staticPayload.title ?? ''}
content={content}
metas={staticPayload.metas?.map(({ charset: charSet, ...meta }) => ({ charSet, ...meta }))}
styles={options.styles}
scripts={[
...(options.scripts ?? []),
...(staticPayload.scripts?.map(({ crossorigin: crossOrigin, ...script }) => ({ crossOrigin, ...script })) ??
[]),
]}
links={[
...(options.links ?? []),
...(staticPayload.links?.map(({ crossorigin: crossOrigin, hreflang: hrefLang, ...link }) => ({
crossOrigin,
hrefLang,
...link,
})) ?? []),
]}
/>
</React.StrictMode>
);

return `<!DOCTYPE html>\n${html}`;
};
92 changes: 46 additions & 46 deletions src/templates/HtmlTemplate/HtmlTemplate.tsx
@@ -1,54 +1,63 @@
import { StaticPayload } from 'hoofd/dist/dispatcher';
import React from 'react';
import * as React from 'react';

import { googleSiteVerificationKey, themeColor } from '@/config/website';
import { getPathFile } from '@/helpers/assetHelper';

export interface HtmlTemplateProps {
staticPayload: StaticPayload;
lang: string;
title: string;
content: string;
links?: StaticPayload['links'];
scripts?: StaticPayload['scripts'];
metas?: Array<React.MetaHTMLAttributes<HTMLMetaElement>>;
links?: Array<React.LinkHTMLAttributes<HTMLLinkElement>>;
styles?: Array<React.StyleHTMLAttributes<HTMLStyleElement> & { text?: string }>;
scripts?: Array<React.ScriptHTMLAttributes<HTMLScriptElement> & { critical?: boolean; text?: string }>;
}

export const HtmlTemplate: React.FC<HtmlTemplateProps> = ({ staticPayload, content, links, scripts }) => (
<html lang={staticPayload.lang}>
const renderScripts = (scripts: HtmlTemplateProps['scripts']): JSX.Element[] | undefined =>
scripts?.map<JSX.Element>((script, index) => (
<script
key={index}
{...script}
dangerouslySetInnerHTML={
script.text
? {
__html: script.text,
}
: undefined
}
/>
));

export const HtmlTemplate: React.FC<HtmlTemplateProps> = ({ lang, title, content, metas, links, styles, scripts }) => (
<html lang={lang}>
<head>
<meta charSet="UTF-8" />
<meta name="robots" content="index, follow, noarchive" />
<meta name="google-site-verification" content={googleSiteVerificationKey} />

{/* SEO */}
{staticPayload?.metas?.map((meta, index) => (
<meta key={index} {...meta} />
))}
{[...(scripts || []), ...(staticPayload?.scripts || [])]
.filter((script) => script.type === 'application/ld+json' && script.text)
.map((script, index) => (
<script key={index} type={script.type} dangerouslySetInnerHTML={{ __html: script.text as string }} />
))}

{/* Allow installing the app to the homescreen */}
<link rel="manifest" href={getPathFile('/manifest.json')} />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="mobile-web-app-capable" content="yes" />

{/* iOS home screen icons */}
<meta name="apple-mobile-web-app-title" content="Blog Eleven Labs" />
{[
{ sizes: '120x120', path: '/imgs/icons/apple-icon-120x120.png' },
{ sizes: '120x120', path: '/imgs/icons/apple-icon-152x152.png' },
{ sizes: '120x120', path: '/imgs/icons/apple-icon-180x180.png' },
].map((appleTouchIcon, index) => (
<link key={index} rel="apple-touch-icon" sizes={appleTouchIcon.sizes} href={getPathFile(appleTouchIcon.path)} />
<meta name="apple-mobile-web-app-capable" content="yes" />
{metas?.map((meta, index) => (
<meta key={index} {...meta} />
))}
<meta name="theme-color" content={themeColor} />
<link rel="shortcut icon" type="image/x-icon" href={getPathFile('/favicon.ico')} />

{[...(links || []), ...(staticPayload?.links || [])].map((link, index) => (
<link rel="manifest" href={getPathFile('/web-app-manifest.json')} />
{links?.map((link, index) => (
<link key={index} {...link} />
))}
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{staticPayload.title}</title>
{styles?.map(({ text, ...props }, index) => (
<style
key={index}
{...props}
dangerouslySetInnerHTML={
text
? {
__html: text,
}
: undefined
}
/>
))}
{renderScripts(scripts?.filter((script) => script.critical))}
<title>{title}</title>
</head>
<body>
<div
Expand All @@ -57,16 +66,7 @@ export const HtmlTemplate: React.FC<HtmlTemplateProps> = ({ staticPayload, conte
__html: content,
}}
/>
{[...(scripts || []), ...(staticPayload?.scripts || [])]
.filter((script) => script.type !== 'application/ld+json' && script.text)
.map((script, index) => (
<script key={index} type={script.type} dangerouslySetInnerHTML={{ __html: script.text as string }} />
))}
{[...(scripts || []), ...(staticPayload?.scripts || [])]
.filter((script) => script.type === 'module')
.map((script, index) => (
<script key={index} defer {...script} />
))}
{renderScripts(scripts?.filter((script) => !script.critical))}
</body>
</html>
);
2 changes: 1 addition & 1 deletion src/templates/LayoutTemplate/Header/Header.tsx
Expand Up @@ -34,7 +34,7 @@ export const Header: React.FC<HeaderProps> = ({
{isNotTablet || autocompleteIsDisplayed ? (
<AutocompleteField {...autocomplete} />
) : (
<Box as="button" className="header__icon-button" onClick={onToggleSearch}>
<Box as="button" className="header__icon-button" onClick={onToggleSearch} aria-label="Open search">
<Icon name="search" color="white" size="28px" />
</Box>
)}
Expand Down

0 comments on commit fb5cf2a

Please sign in to comment.