Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vue): init, app, component and lib generators #19018

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ tmp
*.log
jest.debug.config.js
.tool-versions
/.nx
/.nx-cache
/.verdaccio/build/local-registry
/graph/client/src/assets/environment.js
Expand All @@ -19,7 +20,6 @@ jest.debug.config.js
/graph/client/src/assets/generated-task-graphs
/nx-dev/nx-dev/public/documentation
/nx-dev/nx-dev/public/images/open-graph

# Issues scraper creates these files, stored by github's cache
/scripts/issues-scraper/cached

Expand Down
14 changes: 14 additions & 0 deletions docs/map.json
Original file line number Diff line number Diff line change
Expand Up @@ -2079,6 +2079,20 @@
}
]
},
{
"name": "vue",
"id": "vue",
"description": "Vue package.",
"itemList": [
{
"id": "overview",
"path": "/packages/vue",
"name": "Overview of the Nx Vue Plugin",
"description": "The Nx Plugin for Vue contains generators for managing Vue applications and libraries within an Nx workspace. This page also explains how to configure Vue on your Nx workspace.",
"file": "shared/packages/vue/vue-plugin"
}
]
},
{
"name": "webpack",
"id": "webpack",
Expand Down
10 changes: 10 additions & 0 deletions docs/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,16 @@
"generators": ["init", "configuration", "vitest"]
}
},
{
"name": "vue",
"packageName": "vue",
"description": "The Vue plugin for Nx contains executors and generators for managing Vue applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Cypress, and Storybook.\n\n- Generators for applications, libraries, components, hooks, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.",
"path": "generated/packages/vite.json",
"schemas": {
"executors": [],
"generators": ["init", "library", "application", "component"]
}
},
{
"name": "web",
"packageName": "web",
Expand Down
60 changes: 60 additions & 0 deletions docs/shared/packages/vue/vue-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: Overview of the Nx Vue Plugin
description: The Nx Plugin for Vue contains generators for managing Vue applications and libraries within an Nx workspace. This page also explains how to configure Vue on your Nx workspace.
---

The Nx plugin for [Vue](https://vuejs.org/).

## Setting up a new Nx workspace with Vue

You can create a new workspace that uses Vue with one of the following commands:

- Generate a new monorepo with a Vue app set up with Vue

```shell
npx create-nx-workspace@latest --preset=vue
```

## Add Vue to an existing workspace

There are a number of ways to use Vue in your existing workspace.

### Install the `@nx/vue` plugin

{% tabs %}
{% tab label="npm" %}

```shell
npm install -D @nx/vue
```

{% /tab %}
{% tab label="yarn" %}

```shell
yarn add -D @nx/vue
```

{% /tab %}
{% tab label="pnpm" %}

```shell
pnpm install -D @nx/vue
```

{% /tab %}
{% /tabs %}

### Generate a new project using Vue

To generate a Vue application, run the following:

```bash
nx g @nx/vue:app my-app
```

To generate a Vue library, run the following:

```bash
nx g @nx/vue:lib my-lib
```
63 changes: 63 additions & 0 deletions e2e/vue/src/vue.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {
cleanupProject,
killPorts,
newProject,
promisifiedTreeKill,
runCLI,
runCLIAsync,
runCommandUntil,
uniq,
} from '@nx/e2e/utils';

const myApp = uniq('my-app');
const myLib = uniq('my-lib');

describe('Vue Plugin', () => {
let proj: string;

describe('Vite on React apps', () => {
describe('successfully create and serve a vue app', () => {
beforeEach(() => {
proj = newProject({
unsetProjectNameAndRootFormat: false,
});
runCLI(`generate @nx/vue:app ${myApp}`);
runCLI(`generate @nx/vue:lib ${myLib} --bundler=vite`);
});
afterEach(() => cleanupProject());

it('should serve application in dev mode', async () => {
const p = await runCommandUntil(`run ${myApp}:serve`, (output) => {
return output.includes('Local:');
});
try {
await promisifiedTreeKill(p.pid, 'SIGKILL');
await killPorts(4200);
} catch (e) {
// ignore
}
}, 200_000);

it('should test application', async () => {
const result = await runCLIAsync(`test ${myApp}`);
expect(result.combinedOutput).toContain(
`Successfully ran target test for project ${myApp}`
);
});

it('should build application', async () => {
const result = await runCLIAsync(`build ${myApp}`);
expect(result.combinedOutput).toContain(
`Successfully ran target build for project ${myApp}`
);
});

it('should build library', async () => {
const result = await runCLIAsync(`build ${myLib}`);
expect(result.combinedOutput).toContain(
`Successfully ran target build for project ${myLib}`
);
});
});
});
});
1 change: 1 addition & 0 deletions packages/linter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export { lintInitGenerator } from './src/generators/init/init';
export { Linter } from './src/generators/utils/linter';
/** @deprecated This will be removed in v17 */
export * from './src/utils/convert-tslint-to-eslint';
export * from './src/utils/versions';

// @nx/angular needs it for the Angular CLI workspace migration to Nx to
// infer whether a config is using type aware rules and set the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ describe('app', () => {
'vitest/importMeta',
'vite/client',
'node',
'vitest',
]);
});

Expand Down
45 changes: 45 additions & 0 deletions packages/react/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
addExtendsToLintConfig,
isEslintConfigSupported,
} from '@nx/linter/src/generators/utils/eslint-file';
import { createOrEditViteConfig } from '@nx/vite';

async function addLinting(host: Tree, options: NormalizedSchema) {
const tasks: GeneratorCallback[] = [];
Expand Down Expand Up @@ -138,6 +139,28 @@ export async function applicationGeneratorInternal(
skipFormat: true,
});
tasks.push(viteTask);
createOrEditViteConfig(
host,
{
project: options.projectName,
includeLib: false,
includeVitest: options.unitTestRunner === 'vitest',
inSourceTests: options.inSourceTests,
rollupOptionsExternal: [
`'react'`,
`'react-dom'`,
`'react/jsx-runtime'`,
],
rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
imports: [
options.compiler === 'swc'
? `import react from '@vitejs/plugin-react-swc'`
: `import react from '@vitejs/plugin-react'`,
],
plugins: ['react()'],
},
false
);
} else if (options.bundler === 'webpack') {
const { webpackInitGenerator } = ensurePackage<
typeof import('@nx/webpack')
Expand Down Expand Up @@ -180,6 +203,28 @@ export async function applicationGeneratorInternal(
skipFormat: true,
});
tasks.push(vitestTask);
createOrEditViteConfig(
host,
{
project: options.projectName,
includeLib: false,
includeVitest: true,
inSourceTests: options.inSourceTests,
rollupOptionsExternal: [
`'react'`,
`'react-dom'`,
`'react/jsx-runtime'`,
],
rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
imports: [
options.compiler === 'swc'
? `import react from '@vitejs/plugin-react-swc'`
: `import react from '@vitejs/plugin-react'`,
],
plugins: ['react()'],
},
true
);
}

if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { findFreePort } from './find-free-port';

describe('findFreePort', () => {
it('should return the largest port + 1', () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
const tree = createTreeWithEmptyWorkspace();
addProject(tree, 'app1', 4200);
addProject(tree, 'app2', 4201);
addProject(tree, 'no-serve');
Expand All @@ -16,7 +16,7 @@ describe('findFreePort', () => {
});

it('should default to port 4200', () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
const tree = createTreeWithEmptyWorkspace();
addProject(tree, 'no-serve');

const port = findFreePort(tree);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Tree } from 'nx/src/generators/tree';
import { getProjects } from '@nx/devkit';
import { getProjects, Tree } from '@nx/devkit';

export function findFreePort(host: Tree) {
const projects = getProjects(host);
export function findFreePort(tree: Tree) {
const projects = getProjects(tree);
let port = -Infinity;
for (const [, p] of projects.entries()) {
const curr = p.targets?.serve?.options?.port;
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/generators/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ describe('lib', () => {
'vitest/importMeta',
'vite/client',
'node',
'vitest',
]);
});

Expand Down
52 changes: 45 additions & 7 deletions packages/react/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,8 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {

// Set up build target
if (options.buildable && options.bundler === 'vite') {
const { viteConfigurationGenerator } = ensurePackage<
typeof import('@nx/vite')
>('@nx/vite', nxVersion);
const { viteConfigurationGenerator, createOrEditViteConfig } =
ensurePackage<typeof import('@nx/vite')>('@nx/vite', nxVersion);
const viteTask = await viteConfigurationGenerator(host, {
uiFramework: 'react',
project: options.name,
Expand All @@ -84,6 +83,28 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
testEnvironment: 'jsdom',
});
tasks.push(viteTask);
createOrEditViteConfig(
host,
{
project: options.name,
includeLib: true,
includeVitest: options.unitTestRunner === 'vitest',
inSourceTests: options.inSourceTests,
rollupOptionsExternal: [
`'react'`,
`'react-dom'`,
`'react/jsx-runtime'`,
],
rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
imports: [
options.compiler === 'swc'
? `import react from '@vitejs/plugin-react-swc'`
: `import react from '@vitejs/plugin-react'`,
],
plugins: ['react()'],
},
false
);
} else if (options.buildable && options.bundler === 'rollup') {
const rollupTask = await addRollupBuildTarget(host, options);
tasks.push(rollupTask);
Expand Down Expand Up @@ -120,10 +141,9 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
options.unitTestRunner === 'vitest' &&
options.bundler !== 'vite' // tests are already configured if bundler is vite
) {
const { vitestGenerator } = ensurePackage<typeof import('@nx/vite')>(
'@nx/vite',
nxVersion
);
const { vitestGenerator, createOrEditViteConfig } = ensurePackage<
typeof import('@nx/vite')
>('@nx/vite', nxVersion);
const vitestTask = await vitestGenerator(host, {
uiFramework: 'react',
project: options.name,
Expand All @@ -133,6 +153,24 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
testEnvironment: 'jsdom',
});
tasks.push(vitestTask);
createOrEditViteConfig(
host,
{
project: options.name,
includeLib: true,
includeVitest: true,
inSourceTests: options.inSourceTests,
rollupOptionsExternal: [
`'react'`,
`'react-dom'`,
`'react/jsx-runtime'`,
],
rollupOptionsExternalString: `"'react', 'react-dom', 'react/jsx-runtime'"`,
imports: [`import react from '@vitejs/plugin-react'`],
plugins: ['react()'],
},
true
);
}

if (options.component) {
Expand Down
Loading