Skip to content

Commit

Permalink
[NextJS] Fix dev mode fast refresh in Experience Editor (#532)
Browse files Browse the repository at this point in the history
  • Loading branch information
sc-illiakovalenko authored Jan 21, 2021
1 parent 915a1f6 commit fb0c79c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
2 changes: 2 additions & 0 deletions packages/sitecore-jss-nextjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export {
useComponentProps,
} from './components/ComponentPropsContext';

export { handleExperienceEditorFastRefresh } from './utils';

export { EditingData, EditingPreviewData, isEditingData } from './sharedTypes/editing-data';
export {
EditingDataService,
Expand Down
39 changes: 39 additions & 0 deletions packages/sitecore-jss-nextjs/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import chalk from 'chalk';
import { isExperienceEditorActive, resetExperienceEditorChromes } from '@sitecore-jss/sitecore-jss';

export const getPublicUrl = (): string => {
let url = process.env.PUBLIC_URL;
Expand All @@ -20,6 +21,44 @@ export const getPublicUrl = (): string => {
return url.toString().replace(/\/$/, '');
};

/**
* Since Experience Editor does not support Fast Refresh:
* 1. Subscribe on events provided by webpack.
* 2. Reset experience editor chromes when build is finished
* @param {boolean} [forceReload] force page reload instead of reset chromes
* @default forceReload false
*/
export const handleExperienceEditorFastRefresh = (forceReload = false): void => {
if (isExperienceEditorActive()) {
const eventSource = new window.EventSource(`${getPublicUrl()}/_next/webpack-hmr`);

window.addEventListener('beforeunload', () => eventSource.close());

eventSource.onopen = () => console.log('[Experience Editor Fast Refresh Listener] Online');

eventSource.onmessage = (event) => {
if (event.data.indexOf('{') === -1) return; // heartbeat

const payload = JSON.parse(event.data);

console.debug(
`[Experience Editor Fast Refresh Listener] Saw event: ${JSON.stringify(payload)}`
);

if (payload.action !== 'built') return;

if (forceReload) return window.location.reload();

setTimeout(() => {
console.log(
'[Experience Editor HMR Listener] Experience Editor does not support Fast Refresh, reloading chromes...'
);
resetExperienceEditorChromes();
}, 500);
};
}
};

export const getJssEditingSecret = (): string => {
const secret = process.env.JSS_EDITING_SECRET;
if (!secret || secret.length === 0) {
Expand Down
12 changes: 11 additions & 1 deletion samples/nextjs/src/pages/[[...path]].tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { useEffect } from 'react';
import { GetStaticPaths, GetStaticProps } from 'next';
import NotFound from 'components/NotFound';
import Layout from 'components/Layout';
import { SitecoreContext, ComponentPropsContext } from '@sitecore-jss/sitecore-jss-nextjs';
import {
SitecoreContext,
ComponentPropsContext,
handleExperienceEditorFastRefresh,
} from '@sitecore-jss/sitecore-jss-nextjs';
import { StyleguideSitecoreContextValue } from 'lib/component-props';
import { SitecorePageProps } from 'lib/page-props';
import { sitecorePagePropsFactory } from 'lib/page-props-factory';
import { componentFactory } from 'temp/componentFactory';

const SitecorePage = ({ notFound, layoutData, componentProps }: SitecorePageProps): JSX.Element => {
useEffect(() => {
// Since Experience Editor does not support Fast Refresh need to refresh EE chromes after Fast Refresh finished
handleExperienceEditorFastRefresh();
}, []);

if (notFound) {
return <NotFound context={layoutData?.sitecore?.context} />;
}
Expand Down

0 comments on commit fb0c79c

Please sign in to comment.