fix(nextjs): Custom server should work with Crystal (#21736)
This commit is contained in:
parent
70ea82d58c
commit
9683ebca24
@ -149,6 +149,40 @@ describe('Next.js Applications', () => {
|
|||||||
checkExport: false,
|
checkExport: false,
|
||||||
});
|
});
|
||||||
}, 300_000);
|
}, 300_000);
|
||||||
|
|
||||||
|
it('should support --custom-server flag (swc)', async () => {
|
||||||
|
const appName = uniq('app');
|
||||||
|
|
||||||
|
runCLI(`generate @nx/next:app ${appName} --no-interactive --custom-server`);
|
||||||
|
|
||||||
|
checkFilesExist(`apps/${appName}/server/main.ts`);
|
||||||
|
|
||||||
|
const result = runCLI(`build ${appName}`);
|
||||||
|
|
||||||
|
checkFilesExist(`dist/apps/${appName}/server/main.js`);
|
||||||
|
|
||||||
|
expect(result).toContain(
|
||||||
|
`Successfully ran target build for project ${appName}`
|
||||||
|
);
|
||||||
|
}, 300_000);
|
||||||
|
|
||||||
|
it('should support --custom-server flag (tsc)', async () => {
|
||||||
|
const appName = uniq('app');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/next:app ${appName} --swc=false --no-interactive --custom-server`
|
||||||
|
);
|
||||||
|
|
||||||
|
checkFilesExist(`apps/${appName}/server/main.ts`);
|
||||||
|
|
||||||
|
const result = runCLI(`build ${appName}`);
|
||||||
|
|
||||||
|
checkFilesExist(`dist/apps/${appName}/server/main.js`);
|
||||||
|
|
||||||
|
expect(result).toContain(
|
||||||
|
`Successfully ran target build for project ${appName}`
|
||||||
|
);
|
||||||
|
}, 300_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
function getData(port, path = ''): Promise<any> {
|
function getData(port, path = ''): Promise<any> {
|
||||||
|
|||||||
@ -5,16 +5,7 @@ import { applicationGenerator } from '../application/application';
|
|||||||
describe('app', () => {
|
describe('app', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
|
|
||||||
let originalEnv: string;
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
originalEnv = process.env.NX_ADD_PLUGINS;
|
|
||||||
process.env.NX_ADD_PLUGINS = 'false';
|
|
||||||
});
|
|
||||||
afterAll(() => {
|
|
||||||
process.env.NX_ADD_PLUGINS = originalEnv;
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
tree = createTreeWithEmptyWorkspace();
|
tree = createTreeWithEmptyWorkspace();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import {
|
|||||||
offsetFromRoot,
|
offsetFromRoot,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
updateProjectConfiguration,
|
updateProjectConfiguration,
|
||||||
|
readNxJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { CustomServerSchema } from './schema';
|
import { CustomServerSchema } from './schema';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@ -17,9 +18,17 @@ export async function customServerGenerator(
|
|||||||
) {
|
) {
|
||||||
const project = readProjectConfiguration(host, options.project);
|
const project = readProjectConfiguration(host, options.project);
|
||||||
|
|
||||||
|
const nxJson = readNxJson(host);
|
||||||
|
const hasPlugin = nxJson.plugins?.some((p) =>
|
||||||
|
typeof p === 'string'
|
||||||
|
? p === '@nx/next/plugin'
|
||||||
|
: p.plugin === '@nx/next/plugin'
|
||||||
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
project.targets?.build?.executor !== '@nx/next:build' &&
|
project.targets?.build?.executor !== '@nx/next:build' &&
|
||||||
project.targets?.build?.executor !== '@nrwl/next:build'
|
project.targets?.build?.executor !== '@nrwl/next:build' &&
|
||||||
|
!hasPlugin
|
||||||
) {
|
) {
|
||||||
logger.error(
|
logger.error(
|
||||||
`Project ${options.project} is not a Next.js project. Did you generate it with "nx g @nx/next:app"?`
|
`Project ${options.project} is not a Next.js project. Did you generate it with "nx g @nx/next:app"?`
|
||||||
@ -27,14 +36,18 @@ export async function customServerGenerator(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const outputPath = project.targets?.build?.options?.outputPath;
|
// In Nx 18 next artifacts are inside the project root .next/ & dist/ (for custom server)
|
||||||
|
const outputPath = hasPlugin
|
||||||
|
? `dist/${project.root}`
|
||||||
|
: project.targets?.build?.options?.outputPath;
|
||||||
const root = project.root;
|
const root = project.root;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!root ||
|
(!root ||
|
||||||
!outputPath ||
|
!outputPath ||
|
||||||
!project.targets?.build?.configurations?.development ||
|
!project.targets?.build?.configurations?.development ||
|
||||||
!project.targets?.build?.configurations?.production
|
!project.targets?.build?.configurations?.production) &&
|
||||||
|
!hasPlugin
|
||||||
) {
|
) {
|
||||||
logger.error(
|
logger.error(
|
||||||
`Project ${options.project} has invalid config. Did you generate it with "nx g @nx/next:app"?`
|
`Project ${options.project} has invalid config. Did you generate it with "nx g @nx/next:app"?`
|
||||||
@ -52,17 +65,31 @@ export async function customServerGenerator(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In Nx 18 next artifacts are inside the project root .next/ & dist/ (for custom server)
|
||||||
|
// So we need ensure the mapping is correct from dist to the project root
|
||||||
|
const projectPathFromDist = `../../${offsetFromRoot(project.root)}${
|
||||||
|
project.root
|
||||||
|
}`;
|
||||||
|
|
||||||
generateFiles(host, join(__dirname, 'files'), project.root, {
|
generateFiles(host, join(__dirname, 'files'), project.root, {
|
||||||
...options,
|
...options,
|
||||||
|
hasPlugin,
|
||||||
|
projectPathFromDist,
|
||||||
offsetFromRoot: offsetFromRoot(project.root),
|
offsetFromRoot: offsetFromRoot(project.root),
|
||||||
projectRoot: project.root,
|
projectRoot: project.root,
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
project.targets.build.dependsOn = ['build-custom-server'];
|
if (!hasPlugin) {
|
||||||
project.targets.serve.options.customServerTarget = `${options.project}:serve-custom-server`;
|
project.targets.build.dependsOn = ['build-custom-server'];
|
||||||
project.targets.serve.configurations.development.customServerTarget = `${options.project}:serve-custom-server:development`;
|
project.targets.serve.options.customServerTarget = `${options.project}:serve-custom-server`;
|
||||||
project.targets.serve.configurations.production.customServerTarget = `${options.project}:serve-custom-server:production`;
|
project.targets.serve.configurations.development.customServerTarget = `${options.project}:serve-custom-server:development`;
|
||||||
|
project.targets.serve.configurations.production.customServerTarget = `${options.project}:serve-custom-server:production`;
|
||||||
|
} else {
|
||||||
|
project.targets['build'] = {
|
||||||
|
dependsOn: ['^build', 'build-custom-server'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
project.targets['build-custom-server'] = {
|
project.targets['build-custom-server'] = {
|
||||||
executor: options.compiler === 'tsc' ? '@nx/js:tsc' : '@nx/js:swc',
|
executor: options.compiler === 'tsc' ? '@nx/js:tsc' : '@nx/js:swc',
|
||||||
|
|||||||
@ -2,9 +2,8 @@
|
|||||||
* This is only a minimal custom server to get started.
|
* This is only a minimal custom server to get started.
|
||||||
* You may want to consider using Express or another server framework, and enable security features such as CORS.
|
* You may want to consider using Express or another server framework, and enable security features such as CORS.
|
||||||
*
|
*
|
||||||
* For more examples, see the Next.js repo:
|
* For an example, see the Next.js repo:
|
||||||
* - Express: https://github.com/vercel/next.js/tree/canary/examples/custom-server-express
|
* Node - https://github.com/vercel/next.js/blob/canary/examples/custom-server
|
||||||
* - Hapi: https://github.com/vercel/next.js/tree/canary/examples/custom-server-hapi
|
|
||||||
*/
|
*/
|
||||||
import { createServer } from 'http';
|
import { createServer } from 'http';
|
||||||
import { parse } from 'node:url';
|
import { parse } from 'node:url';
|
||||||
@ -15,7 +14,8 @@ import next from 'next';
|
|||||||
// - The environment variable is set by `@nx/next:server` when running the dev server.
|
// - The environment variable is set by `@nx/next:server` when running the dev server.
|
||||||
// - The fallback `__dirname` is for production builds.
|
// - The fallback `__dirname` is for production builds.
|
||||||
// - Feel free to change this to suit your needs.
|
// - Feel free to change this to suit your needs.
|
||||||
const dir = process.env.NX_NEXT_DIR || path.join(__dirname, '..');
|
|
||||||
|
const dir = process.env.NX_NEXT_DIR || <%- hasPlugin ? `path.join(__dirname, '${projectPathFromDist}')` : `path.join(__dirname, '..')`; %>
|
||||||
const dev = process.env.NODE_ENV === 'development';
|
const dev = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
// HTTP Server options:
|
// HTTP Server options:
|
||||||
|
|||||||
@ -4,7 +4,9 @@
|
|||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"noEmit": false,
|
"noEmit": false,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
|
<% if(hasPlugin && compiler === 'tsc') { %>
|
||||||
"tsBuildInfoFile": "<%= offsetFromRoot %>tmp/buildcache/<%= projectRoot %>/server",
|
"tsBuildInfoFile": "<%= offsetFromRoot %>tmp/buildcache/<%= projectRoot %>/server",
|
||||||
|
<% } %>
|
||||||
"types": [
|
"types": [
|
||||||
"node"
|
"node"
|
||||||
]
|
]
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
installPackagesTask,
|
installPackagesTask,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
readJson,
|
readJson,
|
||||||
|
updateJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { swcCliVersion, swcCoreVersion, swcNodeVersion } from './versions';
|
import { swcCliVersion, swcCoreVersion, swcNodeVersion } from './versions';
|
||||||
import { addSwcConfig } from '@nx/js/src/utils/swc/add-swc-config';
|
import { addSwcConfig } from '@nx/js/src/utils/swc/add-swc-config';
|
||||||
@ -21,7 +22,16 @@ export function configureForSwc(tree: Tree, projectRoot: string) {
|
|||||||
rootPackageJson.devDependencies?.['@swc/cli'];
|
rootPackageJson.devDependencies?.['@swc/cli'];
|
||||||
|
|
||||||
if (!tree.exists(swcConfigPath)) {
|
if (!tree.exists(swcConfigPath)) {
|
||||||
addSwcConfig(tree, swcConfigPath);
|
addSwcConfig(tree, projectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tree.exists(swcConfigPath)) {
|
||||||
|
updateJson(tree, swcConfigPath, (json) => {
|
||||||
|
return {
|
||||||
|
...json,
|
||||||
|
exclude: [...json.exclude, '.*.d.ts$'],
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasSwcDepedency || !hasSwcCliDependency) {
|
if (!hasSwcDepedency || !hasSwcCliDependency) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user