Skip to content

Commit

Permalink
[Nextjs] Update nextjs to 12.2 (#1093)
Browse files Browse the repository at this point in the history
* Nextjs version update plus extra upgrade steps for middleware

* Moved middleware.ts to recommended location (adjacent to pages)

* Updated next-env.d.ts

* Comment updates (use generic "Sitecore editor", next/image now supported, next doc links changed)

* Removed .babelrc (as of 12.2, swc appears to work in Windows-based rendering hosts in containers - or at least acts no differently than with it)

* Add the _next... URL exclusion rule for personalize middleware

Co-authored-by: Adam Brauer <400763+ambrauer@users.noreply.github.com>
  • Loading branch information
art-alexeyenko and ambrauer authored Jul 7, 2022
1 parent 4d25363 commit 5fc2e3d
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 98 deletions.
9 changes: 0 additions & 9 deletions packages/create-sitecore-jss/src/templates/nextjs/.babelrc

This file was deleted.

4 changes: 2 additions & 2 deletions packages/create-sitecore-jss/src/templates/nextjs/.env
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
# https://nextjs.org/docs/basic-features/environment-variables

# The public URL to use for absolute URLs, which are required when
# the Next.js app is run within the Sitecore Experience Editor.
# the Next.js app is run within Sitecore editors.
# This should match the `serverSideRenderingEngineApplicationUrl`
# in your Sitecore configuration (see \sitecore\config\<%- appName %>.config).
# Be sure to update these values accordingly as your public endpoint changes.
# See https://jss.sitecore.com/docs/fundamentals/services/view-engine
PUBLIC_URL=http://localhost:3000

# To secure the Experience Editor endpoint exposed by your Next.js app
# To secure the Sitecore editor endpoint exposed by your Next.js app
# (`/api/editing/render` by default), a secret token is used. This (client-side)
# value must match your server-side value (see \sitecore\config\<%- appName %>.config).
# We recommend an alphanumeric value of at least 16 characters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
],
"ignorePatterns": [".generated/**/*", "**/*.d.ts", "**/*.js"],
"rules": {
"@next/next/no-img-element": "off", // Don't force next/image (not currently compatible with Sitecore editing)
"@next/next/no-img-element": "off", // Don't force next/image
"jsx-a11y/alt-text": ["warn", { "elements": ["img"] }], // Don't force alt for <Image/> (sourced from Sitecore media)
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@sitecore-jss/sitecore-jss-nextjs": "^21.0.0-canary",
"graphql": "~15.8.0",
"graphql-tag": "^2.11.0",
"next": "^12.1.6",
"next": "^12.2.0",
"next-localization": "^0.12.0",
"react": "^18.1.0",
"react-dom": "^18.1.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ ${componentFiles
// See https://nextjs.org/docs/advanced-features/dynamic-import
// At the end you will have single preloaded script for each lazy loading module.
// Editing mode doesn't work well with dynamic components in nextjs: dynamic components are not displayed without refresh after a rendering is added.
// This happens beacuse Experience Editor simply inserts updated HTML generated on server side. This conflicts with nextjs dynamic logic as no HTML gets rendered for dynamic component
// This happens beacuse Sitecore editors simply insert updated HTML generated on server side. This conflicts with nextjs dynamic logic as no HTML gets rendered for dynamic component
// So we use require() to obtain dynamic components in editing mode while preserving dynamic logic for non-editing scenarios
// As we need to be able to seamlessly work with dynamic components in both editing and normal modes, different componentFactory functions will be passed to app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

<!--
JSS EDITING SECRET
To secure the Experience Editor endpoint exposed by your Next.js app (see `serverSideRenderingEngineEndpointUrl` below),
To secure the Sitecore editor endpoint exposed by your Next.js app (see `serverSideRenderingEngineEndpointUrl` below),
a secret token is used. This is taken from an env variable by default, but could be patched and set directly by uncommenting.
This (server-side) value must match your client-side value, which is configured by the JSS_EDITING_SECRET env variable (see the Next.js .env file).
We recommend an alphanumeric value of at least 16 characters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
import Navigation from 'src/Navigation';
import Scripts from 'src/Scripts';

// 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.
// Prefix public assets with a public URL to enable compatibility with Sitecore editors.
// If you're not supporting Sitecore editors, you can remove this.
const publicUrl = getPublicUrl();

interface LayoutProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getPublicUrl } from '@sitecore-jss/sitecore-jss-nextjs';

// 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.
// Prefix public assets with a public URL to enable compatibility with Sitecore editors.
// If you're not supporting Sitecore editors, you can remove this.
const publicUrl = getPublicUrl();

const Navigation = (): JSX.Element => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ a[target='_blank']:after {
}

/*
Hides Sitecore Experience Editor markup,
Hides Sitecore editor markup,
if you run the app in connected mode while the Sitecore cookies
are set to edit mode.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { sitemapFetcher } from 'lib/sitemap-fetcher';

const SitecorePage = ({ notFound, componentProps, layoutData }: SitecorePageProps): JSX.Element => {
useEffect(() => {
// Since Sitecore editors do not support Fast Refresh, need to refresh EE chromes after Fast Refresh finished
// Since Sitecore editors do not support Fast Refresh, need to refresh editor chromes after Fast Refresh finished
handleEditorFastRefresh();
}, []);

Expand Down Expand Up @@ -58,7 +58,7 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
// will be generated on request (development mode in this example).
// Alternatively, the entire sitemap could be pre-rendered
// ahead of time (non-development mode in this example).
// See https://nextjs.org/docs/basic-features/data-fetching#incremental-static-regeneration
// See https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration

let paths: StaticPath[] = [];
let fallback: boolean | 'blocking' = 'blocking';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { EditingDataMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/middleware';

/**
* This Next.js API route is used to handle Sitecore Experience Editor data storage and retrieval by key
* (between the Sitecore Experience Editor POST and Next.js page render requests) via the `EditingDataService`.
* This Next.js API route is used to handle Sitecore editor data storage and retrieval by key
* (between the Sitecore editor POST and Next.js page render requests) via the `EditingDataService`.
*
* The `EditingDataMiddleware` expects this dynamic route name to be '[key]' by default, but can
* be configured to use something else with the `dynamicRouteKey` option.
*/

// Bump body size limit (1mb by default) for Experience Editor payload
// Bump body size limit (1mb by default) for Sitecore editor payload
// See https://nextjs.org/docs/api-routes/api-middlewares#custom-config
export const config = {
api: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { EditingRenderMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/middleware';

/**
* This Next.js API route is used to handle POST requests from the Sitecore Experience Editor.
* This Next.js API route is used to handle POST requests from Sitecore editors.
* This route should match the `serverSideRenderingEngineEndpointUrl` in your Sitecore configuration,
* which is set to "http://localhost:3000/api/editing/render" by default (see \sitecore\config\<%- appName %>.config).
*
* The `EditingRenderMiddleware` will
* 1. Extract editing data from the Experience Editor POST request
* 1. Extract editing data from the Sitecore editor POST request
* 2. Stash this data (for later use in the page render request) via the `EditingDataService`, which returns a key for retrieval
* 3. Enable Next.js Preview Mode, passing our stashed editing data key as preview data
* 4. Invoke the actual page render request, passing along the Preview Mode cookies.
* This allows retrieval of the editing data in preview context (via the `EditingDataService`) - see `SitecorePagePropsFactory`
* 5. Return the rendered page HTML to the Sitecore Experience Editor
* 5. Return the rendered page HTML to the Sitecore editor
*/

// Bump body size limit (1mb by default) for Experience Editor payload
// Bump body size limit (1mb by default) for Sitecore editor payload
// See https://nextjs.org/docs/api-routes/api-middlewares#custom-config
export const config = {
api: {
Expand Down
4 changes: 2 additions & 2 deletions packages/sitecore-jss-nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"eslint-plugin-react": "^7.21.5",
"jsdom": "^15.1.1",
"mocha": "^9.1.3",
"next": "^12.1.6",
"next": "^12.2.0",
"nock": "^13.0.5",
"nyc": "^15.1.0",
"react": "^18.1.0",
Expand All @@ -64,7 +64,7 @@
"typescript": "~4.3.5"
},
"peerDependencies": {
"next": "^12.1.6",
"next": "^12.2.0",
"react": "^18.1.0",
"react-dom": "^18.1.0"
},
Expand Down
14 changes: 8 additions & 6 deletions packages/sitecore-jss-nextjs/src/edge/personalize-middleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NextResponse, NextRequest } from 'next/server';
import { NextResponse, NextRequest, userAgent } from 'next/server';
import {
GraphQLPersonalizeService,
GraphQLPersonalizeServiceConfig,
Expand Down Expand Up @@ -72,18 +72,19 @@ export class PersonalizeMiddleware {
}

protected getBrowserId(req: NextRequest): string | undefined {
return req.cookies[this.browserIdCookieName] || undefined;
return req.cookies.get(this.browserIdCookieName) || undefined;
}

protected setBrowserId(res: NextResponse, browserId: string) {
if (browserId.length > 0) {
const expiryDate = new Date(new Date().setFullYear(new Date().getFullYear() + 2));
const options = { expires: expiryDate, secure: true };
res.cookie(this.browserIdCookieName, browserId, options);
res.cookies.set(this.browserIdCookieName, browserId, options);
}
}

protected getExperienceParams(req: NextRequest): ExperienceParams {
const { ua } = userAgent(req);
return {
geo: {
city: req.geo?.city ?? null,
Expand All @@ -93,7 +94,7 @@ export class PersonalizeMiddleware {
region: req.geo?.region ?? null,
},
referrer: req.referrer,
ua: req.ua?.ua ?? null,
ua: ua ?? null,
utm: {
utm_campaign: req.nextUrl.searchParams.get('utm_campaign'),
utm_content: req.nextUrl.searchParams.get('utm_content'),
Expand All @@ -107,15 +108,16 @@ export class PersonalizeMiddleware {
if (
pathname.includes('.') || // Ignore files
pathname.startsWith('/api/') || // Ignore Next.js API calls
pathname.startsWith('/sitecore/') // Ignore Sitecore API calls
pathname.startsWith('/sitecore/') || // Ignore Sitecore API calls
pathname.startsWith('/_next') // Ignore next service calls
) {
return true;
}
return false;
}

private isPreview(req: NextRequest) {
return req.cookies.__prerender_bypass || req.cookies.__next_preview_data;
return req.cookies.get('__prerender_bypass') || req.cookies.get('__next_preview_data');
}

private handler = async (req: NextRequest, res?: NextResponse): Promise<NextResponse> => {
Expand Down
Loading

0 comments on commit 5fc2e3d

Please sign in to comment.