Skip to content

Commit

Permalink
feat(nuxt): nodes for build, serve targets
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini committed Nov 9, 2023
1 parent b4faf2d commit 5db7a2a
Show file tree
Hide file tree
Showing 17 changed files with 628 additions and 63 deletions.
7 changes: 7 additions & 0 deletions docs/map.json
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,13 @@
"name": "Overview of the Nx Nuxt Plugin",
"description": "The Nx Plugin for Nuxt contains generators for managing Nuxt applications within a Nx workspace. This page also explains how to configure Nuxt on your Nx workspace.",
"file": "shared/packages/nuxt/nuxt-plugin"
},
{
"id": "nuxt-nodes-plugin",
"path": "/nx-api/nuxt-nodes-plugin",
"name": "Overview of the @nx/nuxt/plugin",
"description": "The @nx/nuxt/plugin adds Nuxt targets/projects to the Nx project graph. This allows you to run Nuxt for projects that have a nuxt.config.ts file without creating a project.json file.",
"file": "shared/packages/nuxt/nuxt-nodes-plugin"
}
]
},
Expand Down
58 changes: 58 additions & 0 deletions docs/shared/packages/nuxt/nuxt-nodes-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Overview of the @nx/nuxt/plugin
description: The @nx/nuxt/plugin adds Nuxt targets/projects to the Nx project graph. This allows you to run Nuxt for projects that have a nuxt.config.ts file without creating a project.json file.
---

{% callout type="note" title="Still in beta" %}
This feature is still in beta. To use it you must have the `NX_PCV3` environment variable set to `"true"`.
{% /callout %}

## What is the @nx/nuxt/plugin?

The `@nx/nuxt/plugin` adds Nuxt targets/projects to the Nx project graph. This allows you to run Nuxt for projects that have a `nuxt.config.ts` file without creating a `project.json` file.

This is an effort to reduce duplicate code and configurations for your projects that use Nuxt.

## How it works

The `@nx/nuxt:init` generator which is called through the `@nx/nuxt:application` generator the following entry is added in the `plugins` array of your `nx.json`:

```json
...
plugins: [
{
"plugin": "@nx/nuxt/plugin",
"options": {
"buildTargetName": "build",
"serveTargetName": "serve",
},
},
...
]
```

This will create targets for `build` and `serve` in your project graph, so that you can run `nx build my-app`, `nx serve my-app` etc, without manually defining these targets in each of your projects' `project.json` files. This will work for every single project in your workspace that has a `nuxt.config.ts|js` file.

## How to configure

The plugin generates these targets with bare minimum (no extra) options configuration. Any options you need for your Nuxt app, you can add in your project's `nuxt.config.ts`.

If you want to add some universal options for all your `build` targets, for example, you can still do so in the [`targetDefaults`](/recipes/running-tasks/reduce-repetitive-configuration#reduce-configuration-with-targetdefaults).

You can edit the name of your targets if you want to use a different name. For example, you can have this configuration:

```json
...
plugins: [
{
"plugin": "@nx/nuxt/plugin",
"options": {
"buildTargetName": "build-core",
"serveTargetName": "serve",
},
},
...
]
```

and this will create `build-core` and `serve` targets in your project graph. You can then call `nx build-core my-app` for all your projects that have a `nuxt.config.ts|js` file.
2 changes: 1 addition & 1 deletion packages/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"migrations": "./migrations.json"
},
"dependencies": {
"@nx/devkit": "file:../devkit",
"nuxi": "npm:nuxi-nightly@3.9.2-1699007958.251cab5",
"tslib": "^2.3.0",
"@nx/devkit": "file:../devkit",
"@nx/js": "file:../js",
"@nx/eslint": "file:../eslint",
"@nx/vue": "file:../vue"
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { createNodes, NuxtPluginOptions } from './src/plugins/plugin';
3 changes: 2 additions & 1 deletion packages/nuxt/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"main": "packages/nuxt/index.ts",
"generateExportsField": true,
"additionalEntryPoints": [
"{projectRoot}/{executors,generators,migrations}.json"
"{projectRoot}/{executors,generators,migrations}.json",
"{projectRoot}/plugin.ts"
],
"assets": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,11 @@ exports[`app generated files content - as-provided general application should co
"targets": {
"serve": {
"executor": "@nx/nuxt:serve",
"outputs": ["{options.outputFile}"],
"options": {}
},
"build": {
"executor": "@nx/nuxt:build",
"outputs": ["{options.outputFile}"],
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/my-app"
}
Expand Down
38 changes: 37 additions & 1 deletion packages/nuxt/src/generators/application/application.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { Tree, readJson } from '@nx/devkit';
import {
Tree,
getProjects,
readJson,
readProjectConfiguration,
} from '@nx/devkit';
import { applicationGenerator } from './application';

describe('app', () => {
Expand Down Expand Up @@ -98,5 +103,36 @@ describe('app', () => {
expect(tree.read('myapp4/nuxt.config.ts', 'utf-8')).toMatchSnapshot();
});
});

describe('pcv3', () => {
let originalValue: string | undefined;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
originalValue = process.env['NX_PCV3'];
process.env['NX_PCV3'] = 'true';
});

afterEach(() => {
if (originalValue) {
process.env['NX_PCV3'] = originalValue;
} else {
delete process.env['NX_PCV3'];
}
});

it('should not add targets', async () => {
await applicationGenerator(tree, {
name,
projectNameAndRootFormat: 'as-provided',
unitTestRunner: 'vitest',
});

const projectConfi = readProjectConfiguration(tree, name);
expect(projectConfi.targets.build).toBeUndefined();
expect(projectConfi.targets.serve).toBeUndefined();
// TODO(katerina): Enable once `@nx/vite/plugin` is released
// expect(projectConfi.targets.test).toBeUndefined();
});
});
});
});
14 changes: 12 additions & 2 deletions packages/nuxt/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
GeneratorCallback,
joinPathFragments,
offsetFromRoot,
readNxJson,
runTasksInSerial,
toJS,
Tree,
Expand Down Expand Up @@ -74,8 +75,17 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
getRelativePathToRootTsConfig(tree, options.appProjectRoot)
);

addServeTarget(tree, options.name);
addBuildTarget(tree, options.name, outputPath);
const nxJson = readNxJson(tree);
const hasPlugin = nxJson.plugins?.some((p) =>
typeof p === 'string'
? p === '@nx/nuxt/plugin'
: p.plugin === '@nx/nuxt/plugin'
);

if (!hasPlugin) {
addServeTarget(tree, options.name);
addBuildTarget(tree, options.name, outputPath);
}

updateGitIgnore(tree);

Expand Down
3 changes: 1 addition & 2 deletions packages/nuxt/src/generators/application/lib/add-targets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export function addServeTarget(tree: Tree, projectName: string) {
const projectConfig = readProjectConfiguration(tree, projectName);
projectConfig.targets['serve'] = {
executor: '@nx/nuxt:serve',
outputs: ['{options.outputFile}'],
options: {},
};
updateProjectConfiguration(tree, projectName, projectConfig);
Expand All @@ -22,7 +21,7 @@ export function addBuildTarget(
const projectConfig = readProjectConfiguration(tree, projectName);
projectConfig.targets['build'] = {
executor: '@nx/nuxt:build',
outputs: ['{options.outputFile}'],
outputs: ['{options.outputPath}'],
options: {
outputPath: outputPath,
},
Expand Down
33 changes: 22 additions & 11 deletions packages/nuxt/src/generators/application/lib/add-vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Tree,
addDependenciesToPackageJson,
joinPathFragments,
readNxJson,
readProjectConfiguration,
updateProjectConfiguration,
writeJson,
Expand Down Expand Up @@ -33,17 +34,27 @@ export function addVitest(
}
);

const projectConfig = readProjectConfiguration(tree, options.name);
projectConfig.targets['test'] = {
executor: '@nx/vite:test',
outputs: ['{options.reportsDirectory}'],
options: {
passWithNoTests: true,
reportsDirectory: `${projectOffsetFromRoot}coverage/${projectRoot}`,
config: `${projectRoot}/vitest.config.ts`,
},
};
updateProjectConfiguration(tree, options.name, projectConfig);
const nxJson = readNxJson(tree);
const hasPlugin = nxJson.plugins?.some((p) =>
typeof p === 'string'
? p === '@nx/nuxt/plugin'
: p.plugin === '@nx/nuxt/plugin' &&
p?.options?.['testTargetName'] === undefined
);

if (!hasPlugin) {
const projectConfig = readProjectConfiguration(tree, options.name);
projectConfig.targets['test'] = {
executor: '@nx/vite:test',
outputs: ['{options.reportsDirectory}'],
options: {
passWithNoTests: true,
reportsDirectory: `${projectOffsetFromRoot}coverage/${projectRoot}`,
config: `${projectRoot}/vitest.config.ts`,
},
};
updateProjectConfiguration(tree, options.name, projectConfig);
}

tree.write(
joinPathFragments(projectRoot, 'vitest.config.ts'),
Expand Down
32 changes: 31 additions & 1 deletion packages/nuxt/src/generators/init/init.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { readJson, Tree } from '@nx/devkit';
import { readJson, readNxJson, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { nuxtInitGenerator } from './init';

Expand All @@ -16,4 +16,34 @@ describe('init', () => {
const packageJson = readJson(tree, 'package.json');
expect(packageJson).toMatchSnapshot();
});

describe('pcv3', () => {
let originalValue: string | undefined;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
originalValue = process.env['NX_PCV3'];
process.env['NX_PCV3'] = 'true';
});

afterEach(() => {
if (originalValue) {
process.env['NX_PCV3'] = originalValue;
} else {
delete process.env['NX_PCV3'];
}
});

it('should not add targets', async () => {
await nuxtInitGenerator(tree, {
skipFormat: false,
});
const nxJson = readNxJson(tree);
expect(nxJson.plugins).toMatchObject([
{
options: { buildTargetName: 'build', serveTargetName: 'serve' },
plugin: '@nx/nuxt/plugin',
},
]);
});
});
});
50 changes: 8 additions & 42 deletions packages/nuxt/src/generators/init/init.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,8 @@
import {
addDependenciesToPackageJson,
GeneratorCallback,
runTasksInSerial,
Tree,
} from '@nx/devkit';
import { GeneratorCallback, runTasksInSerial, Tree } from '@nx/devkit';
import { initGenerator as jsInitGenerator } from '@nx/js';
import {
nxVersion,
nuxtDevtoolsVersion,
nuxtVersion,
h3Version,
nuxtUiTemplatesVersion,
} from '../../utils/versions';
import {
lessVersion,
sassVersion,
vueRouterVersion,
vueVersion,
vueTscVersion,
} from '@nx/vue';
import { InitSchema } from './schema';

function updateDependencies(host: Tree, schema: InitSchema) {
let devDependencies: { [key: string]: string } = {
'@nx/nuxt': nxVersion,
'@nx/vite': nxVersion, // needed for the nxViteTsPaths plugin
'@nuxt/devtools': nuxtDevtoolsVersion,
'@nuxt/ui-templates': nuxtUiTemplatesVersion,
nuxt: nuxtVersion,
h3: h3Version,
vue: vueVersion,
'vue-router': vueRouterVersion,
'vue-tsc': vueTscVersion,
};

if (schema.style === 'scss') {
devDependencies['sass'] = sassVersion;
} else if (schema.style === 'less') {
devDependencies['less'] = lessVersion;
}

return addDependenciesToPackageJson(host, {}, devDependencies);
}
import { InitSchema } from './schema';
import { addPlugin, updateDependencies } from './lib/utils';

export async function nuxtInitGenerator(host: Tree, schema: InitSchema) {
const tasks: GeneratorCallback[] = [];
Expand All @@ -59,6 +20,11 @@ export async function nuxtInitGenerator(host: Tree, schema: InitSchema) {
tasks.push(installTask);
}

const addPlugins = process.env.NX_PCV3 === 'true';
if (addPlugins) {
addPlugin(host);
}

return runTasksInSerial(...tasks);
}

Expand Down

0 comments on commit 5db7a2a

Please sign in to comment.