Skip to content
Draft
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 packages/core/src/config/define-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DeepPartial, SitecoreConfig, SitecoreConfigInput } from './models';
* Provides default initial values for SitecoreConfig
* @returns default config
*/

export const getFallbackConfig = (): SitecoreConfig => ({
api: {
edge: {
Expand All @@ -20,6 +21,7 @@ export const getFallbackConfig = (): SitecoreConfig => ({
},
},
editingSecret: process.env.SITECORE_EDITING_SECRET || 'editing-secret-missing',
isEditingHost: !!process.env.SITECORE_EDITING_SECRET,
retries: {
count: 3,
retryStrategy: new DefaultRetryStrategy({
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/config/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ export type SitecoreConfigInput = {
* Default comes from the SITECORE_EDITING_SECRET environment variable.
*/
editingSecret?: string;
/**
* Indicates whether the app is running as an Editing Host.
* Recommended to be derived from the presence of `editingSecret`.
* Defaults to `!!process.env.SITECORE_EDITING_SECRET`.
*/
isEditingHost?: boolean;
/**
* Retry configuration applied to Layout, Dictionary and ErrorPages services
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
const path = require('path');
const webpack = require('webpack');
const SassAlias = require('sass-alias');
const fs = require('fs');

/**
* @type {import('next').NextConfig}
*/
// Determine host role strictly from env for build-time safety
const isEditingHost = !!process.env.SITECORE_EDITING_SECRET;

// For Rendering Host builds, ensure the editing API folder is removed before Next scans pages
if (!isEditingHost) {
try {
const editingApiDir = path.join(process.cwd(), 'src', 'pages', 'api', 'editing');
if (fs.existsSync(editingApiDir)) {
fs.rmSync(editingApiDir, { recursive: true, force: true });
console.log('next.config: removed editing API routes for Rendering Host');
}
} catch (error) {
console.warn('Failed to remove editing API routes:', error);
}
}

const nextConfig = {
// Default Next.js page extensions
pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
// Allow specifying a distinct distDir when concurrently running app in a container
distDir: process.env.NEXTJS_DIST_DIR || '.next',

Expand Down Expand Up @@ -42,7 +62,7 @@ const nextConfig = {
},

async rewrites() {
return [
const routes = [
// healthz check
{
source: '/healthz',
Expand All @@ -58,21 +78,55 @@ const nextConfig = {
source: '/sitemap:id([\\w-]{0,}).xml',
destination: '/api/sitemap'
},
// feaas api route
{
];

// Only add FEAAS editing route for Editing Host builds
if (isEditingHost) {
routes.push({
source: '/feaas-render',
destination: '/api/editing/feaas/render',
},
];
});
}

return routes;
},

webpack: (config, options) => {
if (!options.isServer) {
// Add a loader to strip out getComponentServerProps from components in the client bundle
config.module.rules.unshift({
test: /src\\components\\.*\.tsx$/,
// reference this for the editing host exclusion task
use: ['@sitecore-content-sdk\\nextjs\\component-props-loader'],
});

// Exclude editing-only imports (DesignLibrary, .sitecore/import-map) from client bundle when not Editing Host
if (!isEditingHost) {
// Reuse the enhanced component-props loader to strip editing-only code across the app
config.module.rules.unshift({
test: /src\\.*\.(ts|tsx)$/,
use: ['@sitecore-content-sdk\\nextjs\\component-props-loader'],
});

// Client-only aliases and ignore rules for editing-only code
config.resolve = config.resolve || {};
config.resolve.alias = {
...config.resolve.alias,
'@sitecore-content-sdk/nextjs/editing': false,
'@sitecore-content-sdk/nextjs/editing/codegen/import-map': false,
// Do NOT alias core editing on server; we strip only client usage
'@sitecore-content-sdk/react/dist/esm/components/DesignLibrary': false,
'.sitecore/import-map': false,
};

config.plugins = config.plugins || [];
config.plugins.push(
new webpack.IgnorePlugin({
resourceRegExp:
/^(?:\.sitecore\/import-map(?:\.ts|\.js)?|@sitecore-content-sdk\/(?:core|nextjs)\/editing(?:\/.*)?|@sitecore-content-sdk\/react\/dist\/esm\/components\/DesignLibrary(?:\.js)?)$/,
})
);
}
} else {
// Force use of CommonJS on the server for FEAAS SDK since Content SDK also uses CommonJS entrypoint to FEAAS SDK.
// This prevents issues arising due to FEAAS SDK's dual CommonJS/ES module support on the server (via conditional exports).
Expand All @@ -86,6 +140,9 @@ const nextConfig = {
...config.externals,
];
}

// Note: server bundle remains untouched; client-only handling above

<%_ if (helper.isDev) { -%>
// monorepo configuration start
if (options.isServer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ export default defineCliConfig({
extractFiles({
scConfig,
}),
writeImportMap({
paths: ['src/components'],
scConfig,
}),
...(scConfig.disableCodeGeneration
? []
: [
writeImportMap({
paths: ['src/components'],
scConfig,
}),
]),
],
},
componentMap: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ import { defineConfig } from '@sitecore-content-sdk/nextjs/config';
* See the documentation for `defineConfig`:
* https://doc.sitecore.com/xmc/en/developers/content-sdk/the-sitecore-configuration-file.html
*/
export default defineConfig({});
// Single source of truth derived from env
const isEditingHost = !!process.env.SITECORE_EDITING_SECRET;

export default defineConfig({
// Persist the flag on config so other parts of the app can read it
isEditingHost,
// Use the flag instead of re-deriving from env
disableCodeGeneration: !isEditingHost,
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/**
// @ts-nocheck
/**
* This Layout is needed for Starter Kit.
*/
import React, { JSX } from 'react';
import Head from 'next/head';
import { Placeholder, Field, DesignLibrary, Page } from '@sitecore-content-sdk/nextjs';
import { Placeholder, Field, Page, DesignLibrary } from '@sitecore-content-sdk/nextjs';
import Scripts from 'src/Scripts';
import SitecoreStyles from 'src/components/content-sdk/SitecoreStyles';

import scConfig from 'sitecore.config';
interface LayoutProps {
page: Page;
}
Expand All @@ -21,7 +22,20 @@ const Layout = ({ page }: LayoutProps): JSX.Element => {
const { route } = layout.sitecore;
const fields = route?.fields as RouteFields;
const mainClassPageEditing = mode.isEditing ? 'editing-mode' : 'prod-mode';
const importMapDynamic = () => import('.sitecore/import-map');

// Use the public flag exposed by next.config.js (derived from SITECORE_EDITING_SECRET)
const isEditingHost = !!scConfig.isEditingHost;
let importMap: any = undefined;
if (isEditingHost) {
try {
importMap = require('.sitecore/import-map').default;
} catch (error) {
console.warn(
'DesignLibrary: failed to load .sitecore/import-map; variant generation may be limited.',
error
);
}
}

return (
<>
Expand All @@ -35,7 +49,7 @@ const Layout = ({ page }: LayoutProps): JSX.Element => {
{/* root placeholder for the app, which we add components to using route data */}
<div className={mainClassPageEditing}>
{mode.isDesignLibrary ? (
<DesignLibrary loadImportMap={importMapDynamic} />
<DesignLibrary importMap={importMap} />
) : (
<>
<header>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FEAASRenderMiddleware } from '@sitecore-content-sdk/nextjs/editing';
import { FEAASRenderMiddleware } from '@sitecore-content-sdk/nextjs/editing';
import type { NextApiRequest, NextApiResponse } from 'next';

/**
* This Next.js API route is used to handle GET requests from Sitecore Component Builder.
Expand All @@ -11,6 +12,8 @@
*/

// Wire up the FEAASRenderMiddleware handler
const handler = new FEAASRenderMiddleware().getHandler();
const baseHandler = new FEAASRenderMiddleware().getHandler();

export default handler;
export default function handler(req: NextApiRequest, res: NextApiResponse) {
return baseHandler(req, res);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { EditingRenderMiddleware } from '@sitecore-content-sdk/nextjs/editing';
import { EditingRenderMiddleware } from '@sitecore-content-sdk/nextjs/editing';
import type { NextApiRequest, NextApiResponse } from 'next';

/**
* This Next.js API route is used to handle GET requests from Sitecore Editor.
Expand All @@ -22,7 +23,8 @@ export const config = {
},
};

// Wire up the EditingRenderMiddleware handler
const handler = new EditingRenderMiddleware().getHandler();
const baseHandler = new EditingRenderMiddleware().getHandler();

export default handler;
export default function handler(req: NextApiRequest, res: NextApiResponse) {
return baseHandler(req as any, res as any);
}
2 changes: 2 additions & 0 deletions packages/nextjs/src/config/define-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export const getNextFallbackConfig = (config?: SitecoreConfigInput): SitecoreCon
process.env.GENERATE_STATIC_PATHS !== undefined
? process.env.GENERATE_STATIC_PATHS.toLowerCase() === 'true'
: config?.generateStaticPaths ?? true,
// propagate editing host flag to Next.js layer based on core config/env
isEditingHost: (config as any)?.isEditingHost ?? !!process.env.SITECORE_EDITING_SECRET,
sitecoreInternalEditingHostUrl:
config?.sitecoreInternalEditingHostUrl || process.env.SITECORE_INTERNAL_EDITING_HOST_URL,
};
Expand Down
Loading