fix(nuxt): Add e2e-ci and serve-static targets (#22056)

This commit is contained in:
Nicholas Cunningham 2024-02-28 13:53:20 -07:00 committed by GitHub
parent f046c52e5c
commit 287a0e0616
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 188 additions and 3 deletions

View File

@ -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"
}
}
]
@ -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
@ -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.

View File

@ -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"
}
}
]
@ -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
@ -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.

View File

@ -3,6 +3,7 @@ import {
cleanupProject,
killPorts,
newProject,
readJson,
runCLI,
uniq,
} from '@nx/e2e/utils';
@ -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`
@ -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();
});
});

View File

@ -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 () => {

View File

@ -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,

View File

@ -67,6 +67,7 @@ export function addPlugin(tree: Tree) {
options: {
buildTargetName: 'build',
serveTargetName: 'serve',
serveStaticTargetName: 'serve-static',
},
});
}

View File

@ -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",
@ -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",
},
},
},
},
},

View File

@ -51,6 +51,8 @@ describe('@nx/nuxt/plugin', () => {
{
buildTargetName: 'build',
serveTargetName: 'serve',
buildStaticTargetName: 'build-static',
serveStaticTargetName: 'serve-static',
},
context
);
@ -89,6 +91,8 @@ describe('@nx/nuxt/plugin', () => {
{
buildTargetName: 'build-something',
serveTargetName: 'my-serve',
buildStaticTargetName: 'acme-build-static',
serveStaticTargetName: 'acme-serve-static',
},
context
);

View File

@ -46,6 +46,8 @@ export const createDependencies: CreateDependencies = () => {
export interface NuxtPluginOptions {
buildTargetName?: string;
serveTargetName?: string;
serveStaticTargetName?: string;
buildStaticTargetName?: string;
}
export const createNodes: CreateNodes<NuxtPluginOptions> = [
@ -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;
}
@ -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,
@ -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;
}