Skip to content

Commit 5c498b6

Browse files
[nextjs] Render FEaaS components server side (#1413)
* FEaaS server side implementation * bump sitecore-feaas/clientside module version
1 parent 6da9624 commit 5c498b6

File tree

8 files changed

+223
-132
lines changed

8 files changed

+223
-132
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Our versioning strategy is as follows:
1111

1212
## Unreleased
1313

14+
### 🛠 Breaking Changes
15+
16+
`[sitecore-jss-react]` `[sitecore-jss-nextjs]` FEaaS component is now server rendered. Prop type used FEaaSWrapper has been modified alongside with FEaaSWrapper implementation. Make sure you use the updated type and the updated wrapper. ([#1413](https://github.com/Sitecore/jss/pull/1413))
17+
1418
### 🎉 New Features & Improvements
1519
* `[templates/nextjs-personalize]` Disable page view tracking event in development ([#1414](https://github.com/Sitecore/jss/pull/1414))
1620

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
import { FEaaSComponent, FEaaSComponentProps } from '@sitecore-jss/sitecore-jss-nextjs';
1+
import {
2+
GetServerSideComponentProps,
3+
GetStaticComponentProps,
4+
FEaaSComponent,
5+
FEaaSComponentProps,
6+
FEaaSComponentParams,
7+
fetchFEaaSComponentServerProps,
8+
constants,
9+
} from '@sitecore-jss/sitecore-jss-nextjs';
210
import React from 'react';
311

412
export const Default = (props: FEaaSComponentProps): JSX.Element => {
513
const styles = `component feaas ${props.params?.styles}`.trimEnd();
614
const id = props.params?.RenderingIdentifier;
7-
815
return (
916
<div className={styles} id={id ? id : undefined}>
1017
<div className="component-content">
@@ -13,3 +20,33 @@ export const Default = (props: FEaaSComponentProps): JSX.Element => {
1320
</div>
1421
);
1522
};
23+
24+
/**
25+
* Will be called during SSG
26+
* @param {ComponentRendering} rendering
27+
* @param {LayoutServiceData} layoutData
28+
* @param {GetStaticPropsContext} context
29+
*/
30+
export const getStaticProps: GetStaticComponentProps = async (rendering) => {
31+
if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {
32+
return null;
33+
}
34+
const params: FEaaSComponentParams = rendering.params || {};
35+
const result = await fetchFEaaSComponentServerProps(params);
36+
return result;
37+
};
38+
39+
/**
40+
* Will be called during SSR
41+
* @param {ComponentRendering} rendering
42+
* @param {LayoutServiceData} layoutData
43+
* @param {GetStaticPropsContext} context
44+
*/
45+
export const getServerSideProps: GetServerSideComponentProps = async (rendering) => {
46+
if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {
47+
return null;
48+
}
49+
const params: FEaaSComponentParams = rendering.params || {};
50+
const result = await fetchFEaaSComponentServerProps(params);
51+
return result;
52+
};

packages/sitecore-jss-nextjs/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ export {
141141
EditFrame,
142142
FEaaSComponent,
143143
FEaaSComponentProps,
144+
FEaaSComponentParams,
145+
fetchFEaaSComponentServerProps,
144146
getFEAASLibraryStylesheetLinks,
145147
File,
146148
FileField,

packages/sitecore-jss-react/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"url": "https://github.com/sitecore/jss/issues"
2828
},
2929
"devDependencies": {
30-
"@sitecore-feaas/clientside": "^0.1.24",
30+
"@sitecore-feaas/clientside": "^0.1.48",
3131
"@types/chai": "^4.3.4",
3232
"@types/chai-string": "^1.4.2",
3333
"@types/deep-equal": "^1.0.1",

packages/sitecore-jss-react/src/components/FEaaSComponent.test.tsx

+62-60
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,80 @@
11
import React from 'react';
22
import { expect } from 'chai';
33
import { shallow } from 'enzyme';
4+
import {
5+
composeComponentEndpoint,
6+
FEaaSComponent,
7+
FEaaSComponentParams,
8+
FEaaSComponentProps,
9+
} from './FEaaSComponent';
410
import { ComponentFields } from '@sitecore-jss/sitecore-jss/layout';
5-
import { FEaaSComponent, FEaaSComponentParams } from './FEaaSComponent';
611

712
describe('<FEaaSComponent />', () => {
813
const requiredParams: FEaaSComponentParams = {
914
LibraryId: 'library123',
1015
ComponentId: 'component123',
1116
ComponentVersion: 'version123',
12-
ComponentRevision: 'revision123',
17+
ComponentRevision: 'staged',
1318
ComponentHostName: 'host123',
1419
};
1520

16-
it('should not render if missing params', () => {
17-
const rendered = shallow(<FEaaSComponent />).find('feaas-component');
18-
expect(rendered).to.have.length(0);
21+
describe('composeComponentEndpoint', () => {
22+
it('should return endpoint with https when hostname from params is missing it', () => {
23+
const endpoint = composeComponentEndpoint(requiredParams);
24+
expect(endpoint.startsWith('https://')).to.equal(true);
25+
});
1926
});
2027

21-
it('should not render if missing required params', () => {
22-
const params: FEaaSComponentParams = {
23-
LibraryId: '',
24-
ComponentId: '',
25-
ComponentVersion: '',
26-
ComponentRevision: '',
27-
ComponentHostName: '',
28-
ComponentInstanceId: 'instance',
29-
ComponentHTMLOverride: 'html',
30-
ComponentDataOverride: '{}',
31-
};
32-
const rendered = shallow(<FEaaSComponent params={params} />).find('feaas-component');
33-
expect(rendered).to.have.length(0);
28+
it('should not render with props and params missing', () => {
29+
const wrapper = shallow(<FEaaSComponent />);
30+
expect(wrapper).to.have.length(1);
31+
expect(wrapper.html()).to.equal(null);
3432
});
3533

36-
it('should render', () => {
37-
const wrapper = shallow(<FEaaSComponent params={requiredParams} />);
34+
it('should not render with props missing and only one param present', () => {
35+
const props = {
36+
params: {
37+
ComponentHostName: 'host123',
38+
},
39+
};
40+
const wrapper = shallow(<FEaaSComponent {...props} />);
3841
expect(wrapper).to.have.length(1);
39-
expect(wrapper.html()).to.contain(
40-
'<feaas-stylesheet library="library123" cdn="host123"></feaas-stylesheet>'
41-
);
42-
expect(wrapper.html()).to.contain(
43-
'<feaas-component library="library123" cdn="host123" component="component123" version="version123" revision="revision123" data=""></feaas-component>'
44-
);
45-
expect(wrapper.html()).to.contain(
46-
'<link rel="preload" as="style" href="host123/styles/library123/published.css"/>'
47-
);
48-
expect(wrapper.html()).to.contain(
49-
'<link rel="preload" as="fetch" href="host123/components/library123/component123/version123/revision123.html"/>'
50-
);
51-
expect(wrapper.html()).to.contain(
52-
'<link rel="preload" as="script" href="https://feaasstatic.blob.core.windows.net/packages/clientside/latest/browser/index.esm.js"/>'
53-
);
42+
expect(wrapper.html()).to.equal(null);
5443
});
5544

56-
it('should render optional instance', () => {
57-
const params: FEaaSComponentParams = {
58-
...requiredParams,
59-
ComponentInstanceId: 'instance123',
60-
};
61-
const wrapper = shallow(<FEaaSComponent params={params} />);
45+
it('should render with template and last-modified when provided', () => {
46+
const template = '<div>test output</div>';
47+
const lastModified = 'March 1 2020';
48+
const wrapper = shallow(<FEaaSComponent template={template} lastModified={lastModified} />);
6249
expect(wrapper).to.have.length(1);
63-
expect(wrapper.html()).to.contain('instance="instance123"');
50+
expect(wrapper.html()).to.equal(
51+
`<feaas-component last-modified="${lastModified}">${template}</feaas-component>`
52+
);
6453
});
6554

66-
it('should render optional html', () => {
67-
const params: FEaaSComponentParams = {
68-
...requiredParams,
69-
ComponentHTMLOverride: '<div>foo</div>',
55+
it('should render when only params are provided', () => {
56+
const props = {
57+
params: requiredParams,
7058
};
71-
const wrapper = shallow(<FEaaSComponent params={params} />);
59+
const wrapper = shallow(<FEaaSComponent {...props} />);
7260
expect(wrapper).to.have.length(1);
73-
expect(wrapper.html()).to.contain(params.ComponentHTMLOverride);
61+
expect(wrapper.html()).to.equal(
62+
'<feaas-component cdn="host123" library="library123" version="version123" component="component123" revision="staged"></feaas-component>'
63+
);
7464
});
7565

7666
describe('data', () => {
7767
it('should send override data', () => {
78-
const params: FEaaSComponentParams = {
79-
...requiredParams,
80-
ComponentDataOverride: '{ "foo": "bar", "baz": 1 }',
68+
const props: FEaaSComponentProps = {
69+
params: {
70+
...requiredParams,
71+
ComponentDataOverride: '{ "foo": "bar", "baz": 1 }',
72+
},
8173
};
82-
const wrapper = shallow(<FEaaSComponent params={params} />);
74+
const wrapper = shallow(<FEaaSComponent {...props} />);
8375
expect(wrapper).to.have.length(1);
8476
expect(wrapper.html()).to.contain(
85-
`data="${params.ComponentDataOverride!.replace(/"/g, '&quot;')}"`
77+
`data="${props.params?.ComponentDataOverride!.replace(/"/g, '&quot;')}"`
8678
);
8779
});
8880

@@ -108,6 +100,12 @@ describe('<FEaaSComponent />', () => {
108100
},
109101
},
110102
};
103+
const props: FEaaSComponentProps = {
104+
params: {
105+
...requiredParams,
106+
},
107+
fields,
108+
};
111109
const expectedData = {
112110
_: {
113111
sampleText: 'Welcome to Sitecore JSS',
@@ -123,27 +121,31 @@ describe('<FEaaSComponent />', () => {
123121
},
124122
},
125123
};
126-
const wrapper = shallow(<FEaaSComponent params={requiredParams} fields={fields} />);
124+
const wrapper = shallow(<FEaaSComponent {...props} />);
127125
expect(wrapper).to.have.length(1);
128126
expect(wrapper.html()).to.contain(
129127
`data="${JSON.stringify(expectedData).replace(/"/g, '&quot;')}"`
130128
);
131129
});
132130

133131
it('should prefer override data over datasource fields', () => {
134-
const params: FEaaSComponentParams = {
135-
...requiredParams,
136-
ComponentDataOverride: '{ "foo": "bar", "baz": 1 }',
137-
};
138132
const fields: ComponentFields = {
139133
sampleText: {
140134
value: 'Welcome to Sitecore JSS',
141135
},
142136
};
143-
const wrapper = shallow(<FEaaSComponent params={params} fields={fields} />);
137+
const props: FEaaSComponentProps = {
138+
params: {
139+
...requiredParams,
140+
ComponentDataOverride: '{ "foo": "bar", "baz": 1 }',
141+
},
142+
fields,
143+
};
144+
145+
const wrapper = shallow(<FEaaSComponent {...props} />);
144146
expect(wrapper).to.have.length(1);
145147
expect(wrapper.html()).to.contain(
146-
`data="${params.ComponentDataOverride!.replace(/"/g, '&quot;')}"`
148+
`data="${props.params?.ComponentDataOverride!.replace(/"/g, '&quot;')}"`
147149
);
148150
});
149151
});

0 commit comments

Comments
 (0)