Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dotcom-rendering/.storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ if (isChromatic()) {
MockDate.set('Sat Jan 1 2022 12:00:00 GMT+0000 (Greenwich Mean Time)');
}

window.IS_STORYBOOK = true;

mockRESTCalls();

setABTests(
Expand Down
4 changes: 2 additions & 2 deletions dotcom-rendering/cypress/e2e/parallel-1/article.e2e.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe('E2E Page rendering', function () {

cy.get('gu-island[name=MostViewedFooterData]', { timeout: 30000 })
.scrollIntoView({ duration: 100 })
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');

cy.get('[data-cy-ab-user-in-variant=ab-test-variant]').should(
'be.visible',
Expand All @@ -104,7 +104,7 @@ describe('E2E Page rendering', function () {

cy.get('gu-island[name=MostViewedFooterData]', { timeout: 30000 })
.scrollIntoView({ duration: 100 })
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');

cy.get('[data-cy-ab-user-in-variant=ab-test-not-in-test]').should(
'be.visible',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('Interactivity', function () {
// Wait for hydration
cy.get('gu-island[name=MostViewedFooterData]')
.last()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.wait('@getMostRead');
cy.wait('@getMostReadGeo');
cy.get('[data-cy=mostviewed-footer]').should('exist');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Epics', function () {
// Wait for hydration of the Epic
cy.get('gu-island[name=LiveBlogEpic]')
.first()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.get('[data-cy=contributions-liveblog-epic]').scrollIntoView();
cy.get('[data-cy=contributions-liveblog-epic]').should('be.visible');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('Liveblogs', function () {
// Wait for hydration
cy.get('gu-island[name=Liveness]')
.first()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.scrollTo('center');
cy.get(`[data-cy="toast"]`).should('not.exist');
cy.window().then(function (win) {
Expand Down Expand Up @@ -75,7 +75,7 @@ describe('Liveblogs', function () {
// Wait for hydration
cy.get('gu-island[name=Liveness]')
.first()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.window().then(function (win) {
win.mockLiveUpdate({
numNewBlocks: 1,
Expand All @@ -92,7 +92,7 @@ describe('Liveblogs', function () {
// Wait for hydration
cy.get('gu-island[name=Liveness]', { timeout: 30000 })
.first()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.scrollTo('bottom');
cy.get(`[data-cy="toast"]`).should('not.exist');
cy.window().then(function (win) {
Expand Down Expand Up @@ -128,7 +128,7 @@ describe('Liveblogs', function () {
// Wait for hydration
cy.get('gu-island[name=Liveness]')
.first()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.window().then(function (win) {
win.mockLiveUpdate({
numNewBlocks: 1,
Expand Down Expand Up @@ -171,7 +171,7 @@ describe('Liveblogs', function () {
// Wait for hydration
cy.get('gu-island[name=Liveness]', { timeout: 30000 })
.first()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.scrollTo('bottom');
cy.get(`[data-cy="toast"]`).should('not.exist');
cy.window().then(function (win) {
Expand All @@ -198,7 +198,7 @@ describe('Liveblogs', function () {
// Wait for hydration
cy.get('gu-island[name=Liveness]')
.first()
.should('have.attr', 'data-island-status', 'rendered');
.should('have.attr', 'data-island-status', 'hydrated');
cy.scrollTo('bottom', { duration: 1000 });
cy.window().then(function (win) {
win.mockLiveUpdate({
Expand Down
5 changes: 1 addition & 4 deletions dotcom-rendering/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,10 @@ Cypress.Commands.add('hydrate', () => {
const islandMeta = `island: ${name} defer: ${deferuntil}`;

if (['idle', 'visible', undefined].includes(deferuntil)) {
const action = !!el.attr('clientOnly')
? 'rendered'
: 'hydrated';
cy.log(`Scrolling to ${islandMeta}`);
cy.wrap(el)
.scrollIntoView({ duration: 1000, timeout: 30000 })
.should('have.attr', 'data-island-status', action, {
.should('have.attr', 'data-island-status', 'hydrated', {
timeout: 30000,
});
// Additional wait to ensure island defer=visible has triggered
Expand Down
3 changes: 0 additions & 3 deletions dotcom-rendering/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,6 @@ type RichLinkCardType =
// 3rd party type declarations //
// ------------------------------

declare module 'chromatic/isChromatic';

declare module 'dynamic-import-polyfill' {
export const initialize: ({
modulePath,
Expand Down Expand Up @@ -518,7 +516,6 @@ declare namespace JSX {
name: string;
deferUntil?: 'idle' | 'visible' | 'interaction' | 'hash';
rootMargin?: string;
clientOnly?: boolean;
props: any;
children: React.ReactNode;
/**
Expand Down
45 changes: 14 additions & 31 deletions dotcom-rendering/src/client/islands/doHydration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { EmotionCache } from '@emotion/react';
import { CacheProvider } from '@emotion/react';
import { log, startPerformanceMeasure } from '@guardian/libs';
import { createElement } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { hydrateRoot } from 'react-dom/client';
import { ConfigProvider } from '../../components/ConfigContext';
import type { Config } from '../../types/configContext';

Expand All @@ -13,17 +13,14 @@ declare global {
* Defines the current state of the Island.
* `undefined` at server-side rendering
*/
islandStatus?: 'identified' | 'imported' | 'rendered' | 'hydrated';
islandStatus?: 'identified' | 'imported' | 'hydrated';
}
}

/**
* This function dynamically imports and then hydrates a specific component in
* a specific part of the page
*
* If the content being hydrated is not present in the dom then React renders
* it. This is how portals (non server side rendered content) work
*
* @param name The name of the component we want to hydrate
* @param data The deserialised props we want to use for hydration
* @param element The location on the DOM where the component to hydrate exists
Expand Down Expand Up @@ -52,47 +49,33 @@ export const doHydration = async (
.then((module) => {
/** The duration of importing the module for this island */
const importDuration = endImportPerformanceMeasure();
const clientOnly = element.hasAttribute('clientonly');
element.dataset.islandStatus = 'imported';

const { endPerformanceMeasure: endIslandPerformanceMeasure } =
startPerformanceMeasure('dotcom', name, 'island');

if (clientOnly) {
element.querySelector('[data-name="placeholder"]')?.remove();
const root = createRoot(element);
root.render(
<ConfigProvider value={config}>
<CacheProvider value={emotionCache}>
{createElement(module[name], data)}
</CacheProvider>
</ConfigProvider>,
);
} else {
hydrateRoot(
element,
<ConfigProvider value={config}>
<CacheProvider value={emotionCache}>
{createElement(module[name], data)}
</CacheProvider>
</ConfigProvider>,
);
}
hydrateRoot(
element,
<ConfigProvider value={config}>
<CacheProvider value={emotionCache}>
{createElement(module[name], data)}
</CacheProvider>
</ConfigProvider>,
);

/** The duration of rendering or hydrating this island */
const islandDuration = endIslandPerformanceMeasure();

return { clientOnly, importDuration, islandDuration };
return { importDuration, islandDuration };
})
.then(({ clientOnly, importDuration, islandDuration }) => {
.then(({ importDuration, islandDuration }) => {
if (!('getEntriesByType' in window.performance)) return;

const action = clientOnly ? 'rendered' : 'hydrated';
element.dataset.islandStatus = action;
element.dataset.islandStatus = 'hydrated';

log(
'dotcom',
`🏝 <${name} /> ${action} in ${islandDuration}ms (imported in ${importDuration}ms)`,
`🏝 hydrated <${name} /> in ${islandDuration}ms (imported in ${importDuration}ms)`,
);
})
.catch((error) => {
Expand Down
55 changes: 0 additions & 55 deletions dotcom-rendering/src/client/islands/doStorybookHydration.js

This file was deleted.

17 changes: 9 additions & 8 deletions dotcom-rendering/src/client/ophan/ophan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
OphanComponentEvent,
} from '@guardian/libs';
import { log } from '@guardian/libs';
import { isServer } from '../../lib/isServer';
import type { ServerSideTests } from '../../types/config';

export type OphanRecordFunction = (
Expand Down Expand Up @@ -55,15 +56,15 @@ export const getOphan = async (): Promise<
* @deprecated use `getOphan` instead
*/
export const getOphanRecordFunction = (): OphanRecordFunction => {
const record = window.guardian.ophan?.record;

if (record) return record;
if (isServer || window.guardian.ophan === undefined) {
// eslint-disable-next-line no-console -- worth informing all users
console.warn('window.guardian.ophan.record is not available');
return () => {
/* do nothing */
};
}

// eslint-disable-next-line no-console -- worth informing all users
console.warn('window.guardian.ophan.record is not available');
return () => {
/* do nothing */
};
return window.guardian.ophan.record;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ export const AllEditorialNewslettersPage = ({
/>
<SkipTo id="maincontent" label="Skip to main content" />
<SkipTo id="navigation" label="Skip to navigation" />
<Island clientOnly={true} deferUntil="idle">
<Island deferUntil="idle">
<AlreadyVisited />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island deferUntil="idle">
<FocusStyles />
</Island>
<Island clientOnly={true} deferUntil="idle">
<Island deferUntil="idle">
<Metrics
commercialMetricsEnabled={
!!newslettersPage.config.switches.commercialMetrics
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isServer } from '../lib/isServer';
import { useIsBridgetCompatible } from '../lib/useIsBridgetCompatible';
import type { EmailSignUpProps } from './EmailSignup';
import { EmailSignup } from './EmailSignup';
Expand All @@ -19,7 +20,7 @@ export const AppEmailSignUp = ({
}: AppEmailSignupProps) => {
const isCompatible = useIsBridgetCompatible();

if (!isCompatible) {
if (!isCompatible || isServer) {
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/ArticleBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export const ArticleBody = ({
dir={languageDirection}
>
{isRecipe(tags) && (
<Island deferUntil="hash" clientOnly={true}>
<Island deferUntil="hash">
<RecipeMultiplier />
</Island>
)}
Expand Down
2 changes: 1 addition & 1 deletion dotcom-rendering/src/components/ArticleMeta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ export const ArticleMeta = ({
>
<div>
{isCommentable && (
<Island clientOnly={true} deferUntil="idle">
<Island deferUntil="idle">
<CommentCount
discussionApiUrl={discussionApiUrl}
shortUrlId={shortUrlId}
Expand Down
Loading