Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Next.js] Introduce nextjs-xmcloud Initializer Template #1653

Merged
merged 8 commits into from
Nov 7, 2023
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
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Our versioning strategy is as follows:
* `[sitecore-jss-nextjs]` (Vercel/Sitecore) Deployment Protection Bypass support for editing integration. ([#1634](https://github.com/Sitecore/jss/pull/1634))
* `[sitecore-jss]` `[templates/nextjs]` Load environment-specific FEAAS theme stylesheets based on Sitecore Edge Platform URL ([#1645](https://github.com/Sitecore/jss/pull/1645))
* `[sitecore-jss-nextjs]` The _GraphQLRequestClient_ import from _@sitecore-jss/sitecore-jss-nextjs_ is deprecated, use import from _@sitecore-jss/sitecore-jss-nextjs/graphql_ submodule instead ([#1650](https://github.com/Sitecore/jss/pull/1650) [#1648](https://github.com/Sitecore/jss/pull/1648))
* `[create-sitecore-jss]` Introduced `nextjs-xmcloud` initializer template. This will include all base XM Cloud features, including Personalize, FEaaS, BYOC, Sitecore Edge Platform and Context support. ([#1653](https://github.com/Sitecore/jss/pull/1653))

### 🐛 Bug Fixes

Expand All @@ -33,7 +34,11 @@ Our versioning strategy is as follows:
* `[sitecore-jss-nextjs]` Fix issue when redirects works each every other times. ([#1629](https://github.com/Sitecore/jss/pull/1629))
* `[templates/nextjs]` Fix custom headers. Now in cors-header plugin extends custom headers from next.config.js file. ([#1637](https://github.com/Sitecore/jss/pull/1637))
* `[sitecore-jss-react]` Fix PlaceholderCommon with using two and more dynamic placeholders. ([#1641](https://github.com/Sitecore/jss/pull/1641))
* `[templates/nextjs-multisite]` Fix site info fetch errors (now skipped) on XM Cloud rendering/editing host builds. ([#1649](https://github.com/Sitecore/jss/pull/1649))
* `[templates/nextjs-multisite]` Fix site info fetch errors (now skipped) on XM Cloud rendering/editing host builds. ([#1649](https://github.com/Sitecore/jss/pull/1649)), ([#1653](https://github.com/Sitecore/jss/pull/1653))

### 🛠 Breaking Changes

* `[create-sitecore-jss]` The `nextjs-personalize` initializer add-on template has been removed and is replaced by the `nextjs-xmcloud` initializer template. You can use the interactive prompts or the `--xmcloud` argument to include this template. ([#1653](https://github.com/Sitecore/jss/pull/1653))

## 21.5.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ export default class NextjsStyleguideInitializer implements Initializer {
}

if (
args.templates.includes('nextjs-personalize') ||
pkg.config?.templates?.includes('nextjs-personalize')
args.templates.includes('nextjs-xmcloud') ||
pkg.config?.templates?.includes('nextjs-xmcloud')
) {
console.log(incompatibleAddonsMsg('nextjs-styleguide-tracking', 'nextjs-personalize'));
console.log(incompatibleAddonsMsg('nextjs-styleguide-tracking', 'nextjs-xmcloud'));
}

const response = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,29 @@ import {
incompatibleAddonsMsg,
} from '../../common';

export default class NextjsPersonalizeInitializer implements Initializer {
export default class NextjsXMCloudInitializer implements Initializer {
get isBase(): boolean {
return false;
}

async init(args: ClientAppArgs) {
const pkg = openPackageJson(`${args.destination}${sep}package.json`);

// TODO: prompts for Personalize and argument types
// const answers = await prompt<StyleguideAnswer>(styleguidePrompts, args);

const mergedArgs = {
...args,
appName: args.appName || pkg?.config?.appName || DEFAULT_APPNAME,
appPrefix: args.appPrefix || pkg?.config?.prefix || false,
};

const templatePath = path.resolve(__dirname, '../../templates/nextjs-personalize');
const templatePath = path.resolve(__dirname, '../../templates/nextjs-xmcloud');

await transform(templatePath, mergedArgs);

if (
args.templates.includes('nextjs-styleguide-tracking') ||
pkg.config?.templates?.includes('nextjs-styleguide-tracking')
) {
console.log(incompatibleAddonsMsg('nextjs-personalize', 'nextjs-styleguide-tracking'));
console.log(incompatibleAddonsMsg('nextjs-xmcloud', 'nextjs-styleguide-tracking'));
}

const response = {
Expand Down
71 changes: 44 additions & 27 deletions packages/create-sitecore-jss/src/initializers/nextjs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,36 @@ import { NextjsArgs } from './args';

inquirer.registerPrompt('nextjs-checkbox', NextjsCheckbox);

enum PlatformCompatibility {
SXP,
XMC,
Both,
}

const addOnChoices = [
{
name: 'nextjs-styleguide - Includes example components and setup for working disconnected',
value: 'nextjs-styleguide',
platform: PlatformCompatibility.Both,
},
{
name: 'nextjs-styleguide-tracking - Includes example (Sitecore XP) tracking component',
value: 'nextjs-styleguide-tracking',
platform: PlatformCompatibility.SXP,
},
{
name: 'nextjs-sxa - Includes example components and setup for Headless SXA projects',
value: 'nextjs-sxa',
platform: PlatformCompatibility.Both,
},
{
name:
'nextjs-multisite - Includes example setup for hosting multiple sites in a single NextJS application',
value: 'nextjs-multisite',
platform: PlatformCompatibility.Both,
},
];

export default class NextjsInitializer implements Initializer {
get isBase(): boolean {
return true;
Expand All @@ -31,7 +61,12 @@ export default class NextjsInitializer implements Initializer {
removeDevDependencies(args.destination);
}

let addInitializers: string[] = [];
const addInitializers: string[] = [];

if (answers.xmcloud && !args.templates.includes('nextjs-xmcloud')) {
// add the "system" nextjs-xmcloud template if needed
addInitializers.push('nextjs-xmcloud');
}

// don't prompt for add-on initializers if --yes or they've already specified
// multiple via --templates (assume they know what they're doing)
Expand All @@ -40,33 +75,15 @@ export default class NextjsInitializer implements Initializer {
type: 'nextjs-checkbox' as 'checkbox',
name: 'addInitializers',
message: 'Would you like to include any add-on initializers?',
choices: [
{
name:
'nextjs-styleguide - Includes example components and setup for working disconnected',
value: 'nextjs-styleguide',
},
{
name: 'nextjs-styleguide-tracking - Includes example (Sitecore XP) tracking component',
value: 'nextjs-styleguide-tracking',
},
{
name: 'nextjs-sxa - Includes example components and setup for Headless SXA projects',
value: 'nextjs-sxa',
},
{
name:
'nextjs-personalize - Includes example setup for projects using XM Cloud Embedded Personalization',
value: 'nextjs-personalize',
},
{
name:
'nextjs-multisite - Includes example setup for hosting multiple sites in a single NextJS application',
value: 'nextjs-multisite',
},
],
choices: addOnChoices.filter((choice) => {
return (
choice.platform === PlatformCompatibility.Both ||
(answers.xmcloud && choice.platform === PlatformCompatibility.XMC) ||
(!answers.xmcloud && choice.platform === PlatformCompatibility.SXP)
);
}),
});
addInitializers = addInitAnswer.addInitializers;
addInitializers.push(...addInitAnswer.addInitializers);
}

if (
Expand Down
19 changes: 10 additions & 9 deletions packages/create-sitecore-jss/src/initializers/nextjs/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export enum Prerender {

export type NextjsAnswer = ClientAppAnswer & {
prerender: Prerender;
xmcloud: boolean;
};

const DEFAULT_PRERENDER = Prerender.SSG;
Expand All @@ -29,6 +30,15 @@ export const prompts: QuestionCollection<NextjsAnswer> = [
return !answers.prerender;
},
},
{
type: 'confirm',
name: 'xmcloud',
message: 'Are you building for Sitecore XM Cloud?',
default: false,
when: (answers: NextjsAnswer): boolean => {
return !answers.yes;
},
},
];

/**
Expand All @@ -45,15 +55,6 @@ export class NextjsCheckbox extends CheckboxPrompt {
return value === initializer && checked;
});

const isPersonalizeSelected = isSelected('nextjs-personalize');
const isTrackingSelected = isSelected('nextjs-styleguide-tracking');

if (isPersonalizeSelected && isTrackingSelected) {
this.onError({
isValid: incompatibleAddonsMsg('nextjs-styleguide-tracking', 'nextjs-personalize'),
});
}

const isSxaSelected = isSelected('nextjs-sxa');
const isStyleguideSelected = isSelected('nextjs-styleguide');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,15 @@ class MultisitePlugin implements ConfigPlugin {

async exec(config: JssConfig) {
let sites: SiteInfo[] = [];

const endpoint = config.sitecoreEdgeContextId ? config.sitecoreEdgeUrl : config.graphQLEndpoint;

if (!endpoint || process.env.SITECORE) {
console.warn(
chalk.yellow(
`Skipping site information fetch (${
!endpoint ? 'missing GraphQL endpoint' : 'building on XM Cloud'
})`
)
);
} else {
console.log(`Fetching site information from ${endpoint}`);

try {
const siteInfoService = new GraphQLSiteInfoService({
clientFactory: createGraphQLClientFactory(config),
});
sites = await siteInfoService.fetchSiteInfo();
} catch (error) {
console.error(chalk.red('Error fetching site information'));
console.error(error);
}
console.log('Fetching site information');
try {
const siteInfoService = new GraphQLSiteInfoService({
clientFactory: createGraphQLClientFactory(config),
});
sites = await siteInfoService.fetchSiteInfo();
} catch (error) {
console.error(chalk.red('Error fetching site information'));
console.error(error);
}

return Object.assign({}, config, {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import {
} from '@sitecore-jss/sitecore-jss-nextjs';
import { getPublicUrl } from '@sitecore-jss/sitecore-jss-nextjs/utils';
import Scripts from 'src/Scripts';
// The bundle imports external (BYOC) components into the app and makes sure they are ready to be used.
import BYOC from 'src/byoc';

// Prefix public assets with a public URL to enable compatibility with Sitecore Experience Editor.
// If you're not supporting the Experience Editor, you can remove this.
Expand All @@ -37,7 +35,6 @@ const Layout = ({ layoutData, headLinks }: LayoutProps): JSX.Element => {
return (
<>
<Scripts />
<BYOC />
<Head>
<title>{fields?.Title?.value?.toString() || 'Page'}</title>
<link rel="icon" href={`${publicUrl}/favicon.ico`} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
# Your Sitecore CDP API target (specific to your data center region)
NEXT_PUBLIC_CDP_TARGET_URL=

# Your Sitecore CDP client key
NEXT_PUBLIC_CDP_CLIENT_KEY=

# An optional Sitecore Personalize scope identifier.
# This can be used to isolate personalization data when multiple XM Cloud Environments share a Personalize tenant.
# This should match the PAGES_PERSONALIZE_SCOPE environment variable for your connected XM Cloud Environment.
NEXT_PUBLIC_PERSONALIZE_SCOPE=

# Your Sitecore CDP point(s) of sale
# Can be provided as a single value (mypoint.com) or a multi-value JSON with locales ({"en":"en.mypoint.com","fr":"fr.mypoint.com"} etc)
NEXT_PUBLIC_CDP_POINTOFSALE=

# Timeout (ms) for Sitecore CDP requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT=

# Timeout (ms) for Sitecore Experience Edge requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT=

# ========== Sitecore Edge Platform ===========

# Your unified Sitecore Edge Context Id.
# This will be used over any Sitecore Preview / Delivery Edge variables (above).
SITECORE_EDGE_CONTEXT_ID=

# ==============================================

# Your Sitecore CDP API target (specific to your data center region)
NEXT_PUBLIC_CDP_TARGET_URL=

# Your Sitecore CDP client key
NEXT_PUBLIC_CDP_CLIENT_KEY=

# An optional Sitecore Personalize scope identifier.
# This can be used to isolate personalization data when multiple XM Cloud Environments share a Personalize tenant.
# This should match the PAGES_PERSONALIZE_SCOPE environment variable for your connected XM Cloud Environment.
NEXT_PUBLIC_PERSONALIZE_SCOPE=

# Your Sitecore CDP point(s) of sale
# Can be provided as a single value (mypoint.com) or a multi-value JSON with locales ({"en":"en.mypoint.com","fr":"fr.mypoint.com"} etc)
NEXT_PUBLIC_CDP_POINTOFSALE=

# Timeout (ms) for Sitecore CDP requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT=

# Timeout (ms) for Sitecore Experience Edge requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT=
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": {
"@sitecore/components": "~1.0.19",
"@sitecore/engage": "^1.4.1",
"@sitecore-feaas/clientside": "^0.4.12"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'dotenv/config';
import chalk from 'chalk';
import { constantCase } from 'constant-case';
import { JssConfig } from 'lib/config';
import { ConfigPlugin } from '..';

/**
* This plugin will set config props used by the Sitecore Edge Platform.
*/
class EdgePlatformPlugin implements ConfigPlugin {
order = 2;

async exec(config: JssConfig) {
const sitecoreEdgeUrl = process.env[`${constantCase('sitecoreEdgeUrl')}`] || 'https://edge-platform.sitecorecloud.io';
const sitecoreEdgeContextId = process.env[`${constantCase('sitecoreEdgeContextId')}`];

if (config.sitecoreApiKey && sitecoreEdgeContextId) {
console.log(
chalk.yellow(
"You have configured both 'sitecoreApiKey' and 'sitecoreEdgeContextId' values. The 'sitecoreEdgeContextId' is used instead."
)
);
}

return Object.assign({}, config, {
sitecoreEdgeUrl,
sitecoreEdgeContextId,
});
}
}

export const edgePlatformPlugin = new EdgePlatformPlugin();
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// The BYOC bundle imports external (BYOC) components into the app and makes sure they are ready to be used
import BYOC from 'src/byoc';
import CdpPageView from 'components/CdpPageView';

const Scripts = (): JSX.Element => {
return (
<>
<BYOC />
<CdpPageView />
</>
);
Expand Down
Loading