Skip to content

Commit

Permalink
feat(nextjs): improve support for custom server (#11325)
Browse files Browse the repository at this point in the history
- Add new generator for custom server
- Add @nrwl/js:node executor for serving custom server
- Deprecate @nrwl/node:node in favor of the above
  • Loading branch information
jaysoo committed Aug 2, 2022
1 parent 355dc54 commit e45c2f2
Show file tree
Hide file tree
Showing 28 changed files with 958 additions and 314 deletions.
70 changes: 70 additions & 0 deletions docs/generated/packages/js.json
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,76 @@
"aliases": [],
"hidden": false,
"path": "/packages/js/src/executors/swc/schema.json"
},
{
"name": "node",
"implementation": "/packages/js/src/executors/node/node.impl.ts",
"schema": {
"$schema": "http://json-schema.org/schema",
"cli": "nx",
"title": "Node executor",
"description": "Execute Nodejs applications.",
"type": "object",
"properties": {
"buildTarget": {
"type": "string",
"description": "The target to run to build you the app."
},
"buildTargetOptions": {
"type": "object",
"description": "Additional options to pass into the build target.",
"default": {}
},
"waitUntilTargets": {
"type": "array",
"description": "The targets to run to before starting the node app.",
"default": [],
"items": { "type": "string" }
},
"host": {
"type": "string",
"default": "localhost",
"description": "The host to inspect the process on."
},
"port": {
"type": "number",
"default": 9229,
"description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes."
},
"inspect": {
"oneOf": [
{ "type": "string", "enum": ["inspect", "inspect-brk"] },
{ "type": "boolean" }
],
"description": "Ensures the app is starting with debugging.",
"default": "inspect"
},
"runtimeArgs": {
"type": "array",
"description": "Extra args passed to the node process.",
"default": [],
"items": { "type": "string" }
},
"args": {
"type": "array",
"description": "Extra args when starting the app.",
"default": [],
"items": { "type": "string" }
},
"watch": {
"type": "boolean",
"description": "Enable re-building when files change.",
"default": true
}
},
"additionalProperties": false,
"required": ["buildTarget"],
"presets": []
},
"description": "Execute a Node application.",
"aliases": [],
"hidden": false,
"path": "/packages/js/src/executors/node/schema.json"
}
]
}
48 changes: 47 additions & 1 deletion docs/generated/packages/next.json
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,47 @@
"implementation": "/packages/next/src/generators/library/library#libraryGenerator.ts",
"hidden": false,
"path": "/packages/next/src/generators/library/schema.json"
},
{
"name": "custom-server",
"factory": "./src/generators/custom-server/custom-server#customServerGenerator",
"schema": {
"$schema": "http://json-schema.org/schema",
"cli": "nx",
"$id": "NxNextCustomServer",
"title": "Add custom server",
"description": "Add a custom server to existing Next.js application.",
"examples": [
{
"command": "nx g custom-server my-app",
"description": "Add a custom server to existing Next.js app."
}
],
"type": "object",
"properties": {
"project": {
"type": "string",
"description": "The name of the project.",
"alias": "p",
"$default": { "$source": "argv", "index": 0 },
"x-dropdown": "project",
"x-prompt": "What is the name of the project to set up a custom server for?"
},
"compiler": {
"type": "string",
"enum": ["tsc", "swc"],
"default": "tsc",
"description": "The compiler used to build the custom server."
}
},
"required": ["project"],
"presets": []
},
"description": "Set up a custom server.",
"implementation": "/packages/next/src/generators/custom-server/custom-server#customServerGenerator.ts",
"aliases": [],
"hidden": false,
"path": "/packages/next/src/generators/custom-server/schema.json"
}
],
"executors": [
Expand Down Expand Up @@ -655,9 +696,14 @@
"description": "Hide error messages containing server information.",
"default": false
},
"customServerTarget": {
"type": "string",
"description": "Target which builds the custom server."
},
"customServerPath": {
"type": "string",
"description": "Use a custom server script."
"description": "Use a custom server script. (Use `customServerTarget` instead)",
"x-deprecated": true
},
"hostname": {
"type": "string",
Expand Down
11 changes: 9 additions & 2 deletions docs/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"name": "js",
"path": "generated/packages/js.json",
"schemas": {
"executors": ["tsc", "swc"],
"executors": ["tsc", "swc", "node"],
"generators": ["library", "init", "convert-to-swc"]
}
},
Expand Down Expand Up @@ -159,7 +159,14 @@
"path": "generated/packages/next.json",
"schemas": {
"executors": ["build", "server", "export"],
"generators": ["init", "application", "page", "component", "library"]
"generators": [
"init",
"application",
"page",
"component",
"library",
"custom-server"
]
}
},
{
Expand Down
74 changes: 18 additions & 56 deletions e2e/next/src/next.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
checkFilesExist,
cleanupProject,
createFile,
expectJestTestsToPass,
isNotWindows,
killPorts,
Expand All @@ -22,11 +21,20 @@ import * as http from 'http';

describe('Next.js Applications', () => {
let proj: string;
let originalEnv: string;

beforeAll(() => (proj = newProject()));

afterAll(() => cleanupProject());

beforeEach(() => {
originalEnv = process.env.NODE_ENV;
});

afterEach(() => {
process.env.NODE_ENV = originalEnv;
});

it('should generate app + libs', async () => {
const appName = uniq('app');
const reactLib = uniq('reactlib');
Expand Down Expand Up @@ -310,66 +318,20 @@ describe('Next.js Applications', () => {
});
}, 300000);

it('should allow using a custom server implementation in TypeScript', async () => {
it('should allow using a custom server implementation', async () => {
const appName = uniq('app');
const port = 4202;

// generate next.js app
runCLI(`generate @nrwl/next:app ${appName} --no-interactive`);

// create custom server
createFile(
'tools/custom-next-server.ts',
`
const express = require('express');
const path = require('path');
export default async function nextCustomServer(app, settings, proxyConfig) {
const handle = app.getRequestHandler();
await app.prepare();
const x: string = 'custom typescript server running';
console.log(x);

const server = express();
server.disable('x-powered-by');
runCLI(`generate @nrwl/next:app ${appName} --style=css --no-interactive`);
runCLI(`generate @nrwl/next:custom-server ${appName} --no-interactive`);

server.use(
express.static(path.resolve(settings.dir, 'public'))
);
checkFilesExist(`apps/${appName}/server/main.ts`);

// Default catch-all handler to allow Next.js to handle all other routes
server.all('*', (req, res) => handle(req, res));
server.listen(settings.port, settings.hostname);
}
`
);

updateProjectConfig(appName, (config) => {
config.targets.serve.options.customServerPath =
'../../tools/custom-next-server.ts';

return config;
await checkApp(appName, {
checkUnitTest: false,
checkLint: false,
checkE2E: true,
checkExport: false,
});

// serve Next.js
const p = await runCommandUntil(
`run ${appName}:serve --port=${port}`,
(output) => {
return output.indexOf(`[ ready ] on http://localhost:${port}`) > -1;
}
);

const data = await getData(port);
expect(data).toContain(`Welcome`);

try {
await promisifiedTreeKill(p.pid, 'SIGKILL');
await killPorts(port);
} catch (err) {
expect(err).toBeFalsy();
}
}, 300000);

it('should support different --style options', async () => {
Expand Down
10 changes: 10 additions & 0 deletions packages/js/executors.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"implementation": "./src/executors/swc/swc.impl",
"schema": "./src/executors/swc/schema.json",
"description": "Build a project using SWC."
},
"node": {
"implementation": "./src/executors/node/node.impl",
"schema": "./src/executors/node/schema.json",
"description": "Execute a Node application."
}
},
"builders": {
Expand All @@ -22,6 +27,11 @@
"implementation": "./src/executors/swc/compat",
"schema": "./src/executors/swc/schema.json",
"description": "Build a project using SWC."
},
"node": {
"implementation": "./src/executors/node/compat",
"schema": "./src/executors/node/schema.json",
"description": "Execute a Node application."
}
}
}
4 changes: 4 additions & 0 deletions packages/js/src/executors/node/compat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { convertNxExecutor } from '@nrwl/devkit';
import nodeExecutor from './node.impl';

export default convertNxExecutor(nodeExecutor);
Loading

1 comment on commit e45c2f2

@vercel
Copy link

@vercel vercel bot commented on e45c2f2 Aug 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-five.vercel.app
nx-dev-nrwl.vercel.app
nx.dev
nx-dev-git-master-nrwl.vercel.app

Please sign in to comment.