Skip to content

Commit

Permalink
feat(vue): init, app, component and lib generators
Browse files Browse the repository at this point in the history
Co-Authored-By: Jack Hsu <[email protected]>
  • Loading branch information
mandarini and jaysoo committed Sep 12, 2023
1 parent fdbf000 commit ff82842
Show file tree
Hide file tree
Showing 85 changed files with 4,844 additions and 399 deletions.
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

0 comments on commit ff82842

Please sign in to comment.