Skip to content

Commit

Permalink
fix(nuxt): Add e2e-ci and serve-static targets (#22056)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndcunningham authored Feb 28, 2024
1 parent f046c52 commit 287a0e0
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 3 deletions.
26 changes: 25 additions & 1 deletion docs/generated/packages/nuxt/documents/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ The `@nx/nuxt/plugin` is configured in the `plugins` array in `nx.json`.
"options": {
"buildTargetName": "build",
"testTargetName": "test",
"serveTargetName": "serve"
"serveTargetName": "serve",
"buildStaticTargetName": "build-static",
"serveStaticTargetName": "serve-static"
}
}
]
Expand All @@ -65,6 +67,8 @@ The `@nx/nuxt/plugin` is configured in the `plugins` array in `nx.json`.

The `buildTargetName`, `testTargetName` and `serveTargetName` options control the names of the inferred Nuxt tasks. The default names are `build`, `test` and `serve`.

The `buildStaticTargetName` and `serveStaticTargetName` options control the names of the inferred Nuxt static tasks. The default names are `build-static` and `serve-static`.

## Using Nuxt

### Generate a new Nuxt app
Expand All @@ -78,3 +82,23 @@ nx g @nx/nuxt:app my-app
Once you are ready to deploy your Nuxt application, you have absolute freedom to choose any hosting provider that fits your needs.

We have detailed [how to deploy your Nuxt application to Vercel in a separate guide](/recipes/nuxt/deploy-nuxt-to-vercel).

### E2E testing

By default `nuxt` **does not** generate static HTML files when you run the `build` command. However, Nx provides a `build-static` target that you can use to generate static HTML files for your Nuxt application. Essentially, this target runs the `nuxt build --prerender` command to generate static HTML files.

To perform end-to-end (E2E) testing on static HTML files using a test runner like Cypress. When you create a Nuxt application, Nx automatically creates a `serve-static` target. This target is designed to serve the static HTML files produced by the `build-static` command.

This feature is particularly useful for testing in continuous integration (CI) pipelines, where resources may be constrained. Unlike the `serve` target, `serve-static` does not require a Nuxt's Nitro server to operate, making it more efficient and faster by eliminating background processes, such as file change monitoring.

To utilize the `serve-static` target for testing, run the following command:

```shell
nx serve-static my-nuxt-app-e2e
```

This command performs several actions:

1. It will build the Nuxt application and generate the static HTML files.
2. It will serve the static HTML files using a simple HTTP server.
3. It will run the Cypress tests against the served static HTML files.
26 changes: 25 additions & 1 deletion docs/shared/packages/nuxt/nuxt-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ The `@nx/nuxt/plugin` is configured in the `plugins` array in `nx.json`.
"options": {
"buildTargetName": "build",
"testTargetName": "test",
"serveTargetName": "serve"
"serveTargetName": "serve",
"buildStaticTargetName": "build-static",
"serveStaticTargetName": "serve-static"
}
}
]
Expand All @@ -65,6 +67,8 @@ The `@nx/nuxt/plugin` is configured in the `plugins` array in `nx.json`.

The `buildTargetName`, `testTargetName` and `serveTargetName` options control the names of the inferred Nuxt tasks. The default names are `build`, `test` and `serve`.

The `buildStaticTargetName` and `serveStaticTargetName` options control the names of the inferred Nuxt static tasks. The default names are `build-static` and `serve-static`.

## Using Nuxt

### Generate a new Nuxt app
Expand All @@ -78,3 +82,23 @@ nx g @nx/nuxt:app my-app
Once you are ready to deploy your Nuxt application, you have absolute freedom to choose any hosting provider that fits your needs.

We have detailed [how to deploy your Nuxt application to Vercel in a separate guide](/recipes/nuxt/deploy-nuxt-to-vercel).

### E2E testing

By default `nuxt` **does not** generate static HTML files when you run the `build` command. However, Nx provides a `build-static` target that you can use to generate static HTML files for your Nuxt application. Essentially, this target runs the `nuxt build --prerender` command to generate static HTML files.

To perform end-to-end (E2E) testing on static HTML files using a test runner like Cypress. When you create a Nuxt application, Nx automatically creates a `serve-static` target. This target is designed to serve the static HTML files produced by the `build-static` command.

This feature is particularly useful for testing in continuous integration (CI) pipelines, where resources may be constrained. Unlike the `serve` target, `serve-static` does not require a Nuxt's Nitro server to operate, making it more efficient and faster by eliminating background processes, such as file change monitoring.

To utilize the `serve-static` target for testing, run the following command:

```shell
nx serve-static my-nuxt-app-e2e
```

This command performs several actions:

1. It will build the Nuxt application and generate the static HTML files.
2. It will serve the static HTML files using a simple HTTP server.
3. It will run the Cypress tests against the served static HTML files.
13 changes: 12 additions & 1 deletion e2e/nuxt/src/nuxt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
cleanupProject,
killPorts,
newProject,
readJson,
runCLI,
uniq,
} from '@nx/e2e/utils';
Expand All @@ -16,7 +17,7 @@ describe('Nuxt Plugin', () => {
unsetProjectNameAndRootFormat: false,
});
runCLI(
`generate @nx/nuxt:app ${app} --unitTestRunner=vitest --projectNameAndRootFormat=as-provided`
`generate @nx/nuxt:app ${app} --unitTestRunner=vitest --projectNameAndRootFormat=as-provided e2eTestRunner=cypress`
);
runCLI(
`generate @nx/nuxt:component --directory=${app}/src/components/one --name=one --nameAndDirectoryFormat=as-provided --unitTestRunner=vitest`
Expand Down Expand Up @@ -54,4 +55,14 @@ describe('Nuxt Plugin', () => {
runCLI(`run ${app}:build-storybook --verbose`);
checkFilesExist(`${app}/storybook-static/index.html`);
}, 300_000);

it('should have build, serve, build-static, server-static targets', () => {
runCLI(`show project ${app} --json > targets.json`);

const targets = readJson('targets.json');
expect(targets.targets['build']).toBeDefined();
expect(targets.targets['serve']).toBeDefined();
expect(targets.targets['serve-static']).toBeDefined();
expect(targets.targets['build-static']).toBeDefined();
});
});
2 changes: 2 additions & 0 deletions packages/nuxt/src/generators/application/application.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ describe('app', () => {
expect(projectConfig.targets.build).toBeUndefined();
expect(projectConfig.targets.serve).toBeUndefined();
expect(projectConfig.targets.test).toBeUndefined();
expect(projectConfig.targets['build-static']).toBeUndefined();
expect(projectConfig.targets['serve-static']).toBeUndefined();
});

it('should create all new files in the correct location', async () => {
Expand Down
6 changes: 6 additions & 0 deletions packages/nuxt/src/generators/application/lib/add-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
bundler: 'vite',
skipFormat: true,
devServerTarget: `${options.projectName}:serve`,
webServerCommands: {
default: `${getPackageManagerCommand().exec} nx serve ${
options.projectName
}`,
},
ciWebServerCommand: `nx run ${options.projectName}:serve-static`,
baseUrl: 'http://localhost:4200',
jsx: true,
addPlugin: true,
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/src/generators/init/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function addPlugin(tree: Tree) {
options: {
buildTargetName: 'build',
serveTargetName: 'serve',
serveStaticTargetName: 'serve-static',
},
});
}
Expand Down
60 changes: 60 additions & 0 deletions packages/nuxt/src/plugins/__snapshots__/plugin.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,36 @@ exports[`@nx/nuxt/plugin not root project should create nodes 1`] = `
"my-app": {
"root": "my-app",
"targets": {
"acme-build-static": {
"cache": true,
"command": "nuxt build --prerender",
"dependsOn": [
"^acme-build-static",
],
"inputs": [
"production",
"^production",
{
"externalDependencies": [
"nuxt",
],
},
],
"options": {
"cwd": "my-app",
},
"outputs": [
"{workspaceRoot}/dist/my-app/",
],
},
"acme-serve-static": {
"executor": "@nx/web:file-server",
"options": {
"buildTarget": "acme-build-static",
"port": 4200,
"staticFilePath": "{projectRoot}/dist",
},
},
"build-something": {
"cache": true,
"command": "nuxt build",
Expand Down Expand Up @@ -68,12 +98,42 @@ exports[`@nx/nuxt/plugin root project should create nodes 1`] = `
"dist/my-app/",
],
},
"build-static": {
"cache": true,
"command": "nuxt build --prerender",
"dependsOn": [
"^build-static",
],
"inputs": [
"production",
"^production",
{
"externalDependencies": [
"nuxt",
],
},
],
"options": {
"cwd": ".",
},
"outputs": [
"dist/my-app/",
],
},
"serve": {
"command": "nuxt dev",
"options": {
"cwd": ".",
},
},
"serve-static": {
"executor": "@nx/web:file-server",
"options": {
"buildTarget": "build-static",
"port": 4200,
"staticFilePath": "{projectRoot}/dist",
},
},
},
},
},
Expand Down
4 changes: 4 additions & 0 deletions packages/nuxt/src/plugins/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ describe('@nx/nuxt/plugin', () => {
{
buildTargetName: 'build',
serveTargetName: 'serve',
buildStaticTargetName: 'build-static',
serveStaticTargetName: 'serve-static',
},
context
);
Expand Down Expand Up @@ -89,6 +91,8 @@ describe('@nx/nuxt/plugin', () => {
{
buildTargetName: 'build-something',
serveTargetName: 'my-serve',
buildStaticTargetName: 'acme-build-static',
serveStaticTargetName: 'acme-serve-static',
},
context
);
Expand Down
53 changes: 53 additions & 0 deletions packages/nuxt/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const createDependencies: CreateDependencies = () => {
export interface NuxtPluginOptions {
buildTargetName?: string;
serveTargetName?: string;
serveStaticTargetName?: string;
buildStaticTargetName?: string;
}

export const createNodes: CreateNodes<NuxtPluginOptions> = [
Expand Down Expand Up @@ -108,6 +110,15 @@ async function buildNuxtTargets(

targets[options.serveTargetName] = serveTarget(projectRoot);

targets[options.serveStaticTargetName] = serveStaticTarget(options);

targets[options.buildStaticTargetName] = buildStaticTarget(
options.buildStaticTargetName,
namedInputs,
buildOutputs,
projectRoot
);

return targets;
}

Expand Down Expand Up @@ -148,6 +159,46 @@ function serveTarget(projectRoot: string) {
return targetConfig;
}

function serveStaticTarget(options: NuxtPluginOptions) {
const targetConfig: TargetConfiguration = {
executor: '@nx/web:file-server',
options: {
buildTarget: `${options.buildStaticTargetName}`,
staticFilePath: '{projectRoot}/dist',
port: 4200,
},
};

return targetConfig;
}

function buildStaticTarget(
buildStaticTargetName: string,
namedInputs: {
[inputName: string]: any[];
},
buildOutputs: string[],
projectRoot: string
) {
const targetConfig: TargetConfiguration = {
command: `nuxt build --prerender`,
options: { cwd: projectRoot },
cache: true,
dependsOn: [`^${buildStaticTargetName}`],
inputs: [
...('production' in namedInputs
? ['production', '^production']
: ['default', '^default']),

{
externalDependencies: ['nuxt'],
},
],
outputs: buildOutputs,
};
return targetConfig;
}

async function getInfoFromNuxtConfig(
configFilePath: string,
context: CreateNodesContext,
Expand Down Expand Up @@ -216,5 +267,7 @@ function normalizeOptions(options: NuxtPluginOptions): NuxtPluginOptions {
options ??= {};
options.buildTargetName ??= 'build';
options.serveTargetName ??= 'serve';
options.serveStaticTargetName ??= 'serve-static';
options.buildStaticTargetName ??= 'build-static';
return options;
}

0 comments on commit 287a0e0

Please sign in to comment.