feat(react): Add react-router to create-nx-workspace and react app generator (#30316)
This pull request introduces improvements to React Router integration and removes the Remix preset. ## Key Changes: - Updated `create-nx-workspace` to support React Router. - Removed the Remix option from `create-nx-workspace`, but the package remains to support existing users. ## SSR & React Router Support - New users who want SSR in their React apps can enable it via the React option and select React Router for SSR support. - The ecosystem has shifted to migrating from Remix to React Router for SSR needs. - This option is only available for plain React apps and uses Vite. Other types of React apps (Micro Frontends, Webpack, Rspack, etc.) remain unaffected. ## Default Routing Behavior `--routing` is now enabled by default when creating a React app using `create-nx-workspace`, aligning with Angular’s default behaviour.
This commit is contained in:
parent
50802e7591
commit
363088a8ae
@ -17,38 +17,39 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Type | Description |
|
||||
| -------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--allPrompts`, `--a` | boolean | Show all prompts. (Default: `false`) |
|
||||
| `--appName` | string | The name of the app when using a monorepo with certain stacks. |
|
||||
| `--bundler` | string | Bundler to be used to build the app. |
|
||||
| `--commit.email` | string | E-mail of the committer. |
|
||||
| `--commit.message` | string | Commit message. (Default: `Initial commit`) |
|
||||
| `--commit.name` | string | Name of the committer. |
|
||||
| `--defaultBase` | string | Default base to use for new projects. (Default: `main`) |
|
||||
| `--docker` | boolean | Generate a Dockerfile for the Node API. |
|
||||
| `--e2eTestRunner` | `playwright`, `cypress`, `none` | Test runner to use for end to end (E2E) tests. |
|
||||
| `--formatter` | string | Code formatter to use. |
|
||||
| `--framework` | string | Framework option to be used with certain stacks. |
|
||||
| `--help` | boolean | Show help. |
|
||||
| `--interactive` | boolean | Enable interactive mode with presets. (Default: `true`) |
|
||||
| `--name` | string | Workspace name (e.g. org name). |
|
||||
| `--nextAppDir` | boolean | Enable the App Router for Next.js. |
|
||||
| `--nextSrcDir` | boolean | Generate a 'src/' directory for Next.js. |
|
||||
| `--nxCloud`, `--ci` | `github`, `gitlab`, `azure`, `bitbucket-pipelines`, `circleci`, `skip`, `yes` | Which CI provider would you like to use? |
|
||||
| `--packageManager`, `--pm` | `bun`, `npm`, `pnpm`, `yarn` | Package manager to use. (Default: `npm`) |
|
||||
| `--prefix` | string | Prefix to use for Angular component and directive selectors. |
|
||||
| `--preset` | string | Customizes the initial content of your workspace. Default presets include: ["apps", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "remix-monorepo", "remix-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset. |
|
||||
| `--routing` | boolean | Add a routing setup for an Angular app. (Default: `true`) |
|
||||
| `--skipGit`, `--g` | boolean | Skip initializing a git repository. (Default: `false`) |
|
||||
| `--ssr` | boolean | Enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering) for the Angular application. |
|
||||
| `--standaloneApi` | boolean | Use Standalone Components if generating an Angular app. (Default: `true`) |
|
||||
| `--style` | string | Stylesheet type to be used with certain stacks. |
|
||||
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
|
||||
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
|
||||
| `--version` | boolean | Show version number. |
|
||||
| `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |
|
||||
| `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. |
|
||||
| Option | Type | Description |
|
||||
| -------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--allPrompts`, `--a` | boolean | Show all prompts. (Default: `false`) |
|
||||
| `--appName` | string | The name of the app when using a monorepo with certain stacks. |
|
||||
| `--bundler` | string | Bundler to be used to build the app. |
|
||||
| `--commit.email` | string | E-mail of the committer. |
|
||||
| `--commit.message` | string | Commit message. (Default: `Initial commit`) |
|
||||
| `--commit.name` | string | Name of the committer. |
|
||||
| `--defaultBase` | string | Default base to use for new projects. (Default: `main`) |
|
||||
| `--docker` | boolean | Generate a Dockerfile for the Node API. |
|
||||
| `--e2eTestRunner` | `playwright`, `cypress`, `none` | Test runner to use for end to end (E2E) tests. |
|
||||
| `--formatter` | string | Code formatter to use. |
|
||||
| `--framework` | string | Framework option to be used with certain stacks. |
|
||||
| `--help` | boolean | Show help. |
|
||||
| `--interactive` | boolean | Enable interactive mode with presets. (Default: `true`) |
|
||||
| `--name` | string | Workspace name (e.g. org name). |
|
||||
| `--nextAppDir` | boolean | Enable the App Router for Next.js. |
|
||||
| `--nextSrcDir` | boolean | Generate a 'src/' directory for Next.js. |
|
||||
| `--nxCloud`, `--ci` | `github`, `gitlab`, `azure`, `bitbucket-pipelines`, `circleci`, `skip`, `yes` | Which CI provider would you like to use? |
|
||||
| `--packageManager`, `--pm` | `bun`, `npm`, `pnpm`, `yarn` | Package manager to use. (Default: `npm`) |
|
||||
| `--prefix` | string | Prefix to use for Angular component and directive selectors. |
|
||||
| `--preset` | string | Customizes the initial content of your workspace. Default presets include: ["apps", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset. |
|
||||
| `--routing` | boolean | Add a routing setup for an Angular or React app. (Default: `true`) |
|
||||
| `--skipGit`, `--g` | boolean | Skip initializing a git repository. (Default: `false`) |
|
||||
| `--ssr` | boolean | Enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering) for the Angular application. |
|
||||
| `--standaloneApi` | boolean | Use Standalone Components if generating an Angular app. (Default: `true`) |
|
||||
| `--style` | string | Stylesheet type to be used with certain stacks. |
|
||||
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
|
||||
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
|
||||
| `--useReactRouter` | boolean | Generate a Server-Side Rendered (SSR) React app using React Router. |
|
||||
| `--version` | boolean | Show version number. |
|
||||
| `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |
|
||||
| `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. |
|
||||
|
||||
## Presets
|
||||
|
||||
@ -72,8 +73,6 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
|
||||
| react-monorepo | A React monorepo |
|
||||
| react-native | A monorepo with a React Native application |
|
||||
| react-standalone | A single React application |
|
||||
| remix-monorepo | A Remix monorepo |
|
||||
| remix-standalone | A single Remix application |
|
||||
| ts | A basic integrated style repository starting with TypeScript configured but no projects |
|
||||
| ts-standalone | A single TypeScript application |
|
||||
| vue | Allows you to choose between the vue-standalone or vue-monorepo presets |
|
||||
|
||||
@ -17,38 +17,39 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Type | Description |
|
||||
| -------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--allPrompts`, `--a` | boolean | Show all prompts. (Default: `false`) |
|
||||
| `--appName` | string | The name of the app when using a monorepo with certain stacks. |
|
||||
| `--bundler` | string | Bundler to be used to build the app. |
|
||||
| `--commit.email` | string | E-mail of the committer. |
|
||||
| `--commit.message` | string | Commit message. (Default: `Initial commit`) |
|
||||
| `--commit.name` | string | Name of the committer. |
|
||||
| `--defaultBase` | string | Default base to use for new projects. (Default: `main`) |
|
||||
| `--docker` | boolean | Generate a Dockerfile for the Node API. |
|
||||
| `--e2eTestRunner` | `playwright`, `cypress`, `none` | Test runner to use for end to end (E2E) tests. |
|
||||
| `--formatter` | string | Code formatter to use. |
|
||||
| `--framework` | string | Framework option to be used with certain stacks. |
|
||||
| `--help` | boolean | Show help. |
|
||||
| `--interactive` | boolean | Enable interactive mode with presets. (Default: `true`) |
|
||||
| `--name` | string | Workspace name (e.g. org name). |
|
||||
| `--nextAppDir` | boolean | Enable the App Router for Next.js. |
|
||||
| `--nextSrcDir` | boolean | Generate a 'src/' directory for Next.js. |
|
||||
| `--nxCloud`, `--ci` | `github`, `gitlab`, `azure`, `bitbucket-pipelines`, `circleci`, `skip`, `yes` | Which CI provider would you like to use? |
|
||||
| `--packageManager`, `--pm` | `bun`, `npm`, `pnpm`, `yarn` | Package manager to use. (Default: `npm`) |
|
||||
| `--prefix` | string | Prefix to use for Angular component and directive selectors. |
|
||||
| `--preset` | string | Customizes the initial content of your workspace. Default presets include: ["apps", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "remix-monorepo", "remix-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset. |
|
||||
| `--routing` | boolean | Add a routing setup for an Angular app. (Default: `true`) |
|
||||
| `--skipGit`, `--g` | boolean | Skip initializing a git repository. (Default: `false`) |
|
||||
| `--ssr` | boolean | Enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering) for the Angular application. |
|
||||
| `--standaloneApi` | boolean | Use Standalone Components if generating an Angular app. (Default: `true`) |
|
||||
| `--style` | string | Stylesheet type to be used with certain stacks. |
|
||||
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
|
||||
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
|
||||
| `--version` | boolean | Show version number. |
|
||||
| `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |
|
||||
| `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. |
|
||||
| Option | Type | Description |
|
||||
| -------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--allPrompts`, `--a` | boolean | Show all prompts. (Default: `false`) |
|
||||
| `--appName` | string | The name of the app when using a monorepo with certain stacks. |
|
||||
| `--bundler` | string | Bundler to be used to build the app. |
|
||||
| `--commit.email` | string | E-mail of the committer. |
|
||||
| `--commit.message` | string | Commit message. (Default: `Initial commit`) |
|
||||
| `--commit.name` | string | Name of the committer. |
|
||||
| `--defaultBase` | string | Default base to use for new projects. (Default: `main`) |
|
||||
| `--docker` | boolean | Generate a Dockerfile for the Node API. |
|
||||
| `--e2eTestRunner` | `playwright`, `cypress`, `none` | Test runner to use for end to end (E2E) tests. |
|
||||
| `--formatter` | string | Code formatter to use. |
|
||||
| `--framework` | string | Framework option to be used with certain stacks. |
|
||||
| `--help` | boolean | Show help. |
|
||||
| `--interactive` | boolean | Enable interactive mode with presets. (Default: `true`) |
|
||||
| `--name` | string | Workspace name (e.g. org name). |
|
||||
| `--nextAppDir` | boolean | Enable the App Router for Next.js. |
|
||||
| `--nextSrcDir` | boolean | Generate a 'src/' directory for Next.js. |
|
||||
| `--nxCloud`, `--ci` | `github`, `gitlab`, `azure`, `bitbucket-pipelines`, `circleci`, `skip`, `yes` | Which CI provider would you like to use? |
|
||||
| `--packageManager`, `--pm` | `bun`, `npm`, `pnpm`, `yarn` | Package manager to use. (Default: `npm`) |
|
||||
| `--prefix` | string | Prefix to use for Angular component and directive selectors. |
|
||||
| `--preset` | string | Customizes the initial content of your workspace. Default presets include: ["apps", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset. |
|
||||
| `--routing` | boolean | Add a routing setup for an Angular or React app. (Default: `true`) |
|
||||
| `--skipGit`, `--g` | boolean | Skip initializing a git repository. (Default: `false`) |
|
||||
| `--ssr` | boolean | Enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering) for the Angular application. |
|
||||
| `--standaloneApi` | boolean | Use Standalone Components if generating an Angular app. (Default: `true`) |
|
||||
| `--style` | string | Stylesheet type to be used with certain stacks. |
|
||||
| `--unitTestRunner` | `jest`, `vitest`, `none` | Test runner to use for unit tests. |
|
||||
| `--useGitHub` | boolean | Will you be using GitHub as your git hosting provider? (Default: `false`) |
|
||||
| `--useReactRouter` | boolean | Generate a Server-Side Rendered (SSR) React app using React Router. |
|
||||
| `--version` | boolean | Show version number. |
|
||||
| `--workspaces` | boolean | Use package manager workspaces. (Default: `true`) |
|
||||
| `--workspaceType` | `integrated`, `package-based`, `standalone` | The type of workspace to create. |
|
||||
|
||||
## Presets
|
||||
|
||||
@ -72,8 +73,6 @@ Install `create-nx-workspace` globally to invoke the command directly, or use `n
|
||||
| react-monorepo | A React monorepo |
|
||||
| react-native | A monorepo with a React Native application |
|
||||
| react-standalone | A single React application |
|
||||
| remix-monorepo | A Remix monorepo |
|
||||
| remix-standalone | A single Remix application |
|
||||
| ts | A basic integrated style repository starting with TypeScript configured but no projects |
|
||||
| ts-standalone | A single TypeScript application |
|
||||
| vue | Allows you to choose between the vue-standalone or vue-monorepo presets |
|
||||
|
||||
@ -77,7 +77,12 @@
|
||||
"routing": {
|
||||
"type": "boolean",
|
||||
"description": "Generate application with routes.",
|
||||
"x-prompt": "Would you like to add React Router to this application?",
|
||||
"x-prompt": "Would you like to add routing to this application?",
|
||||
"default": false
|
||||
},
|
||||
"useReactRouter": {
|
||||
"description": "Use React Router for routing.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"skipFormat": {
|
||||
|
||||
@ -25,6 +25,11 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"useReactRouter": {
|
||||
"description": "Use React Router for routing.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"standaloneApi": {
|
||||
"description": "Use Standalone Components if generating an Angular application.",
|
||||
"type": "boolean",
|
||||
|
||||
@ -25,6 +25,11 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"useReactRouter": {
|
||||
"description": "Use React Router for routing.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"style": {
|
||||
"description": "The file extension to be used for style files.",
|
||||
"type": "string",
|
||||
|
||||
68
e2e/react/src/react-router.test.ts
Normal file
68
e2e/react/src/react-router.test.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanupProject,
|
||||
ensureCypressInstallation,
|
||||
newProject,
|
||||
readFile,
|
||||
runCLI,
|
||||
uniq,
|
||||
} from '@nx/e2e/utils';
|
||||
|
||||
describe('React Router Applications', () => {
|
||||
beforeAll(() => {
|
||||
newProject({ packages: ['@nx/react'] });
|
||||
ensureCypressInstallation();
|
||||
});
|
||||
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should generate a react-router application', async () => {
|
||||
const appName = uniq('app');
|
||||
runCLI(
|
||||
`generate @nx/react:app ${appName} --use-react-router --routing --no-interactive`
|
||||
);
|
||||
|
||||
const packageJson = JSON.parse(readFile('package.json'));
|
||||
expect(packageJson.dependencies['react-router']).toBeDefined();
|
||||
expect(packageJson.dependencies['@react-router/node']).toBeDefined();
|
||||
expect(packageJson.dependencies['@react-router/serve']).toBeDefined();
|
||||
expect(packageJson.dependencies['isbot']).toBeDefined();
|
||||
|
||||
checkFilesExist(`${appName}/app/app.tsx`);
|
||||
checkFilesExist(`${appName}/app/entry.client.tsx`);
|
||||
checkFilesExist(`${appName}/app/entry.server.tsx`);
|
||||
checkFilesExist(`${appName}/app/routes.tsx`);
|
||||
checkFilesExist(`${appName}/react-router.config.ts`);
|
||||
checkFilesExist(`${appName}/vite.config.ts`);
|
||||
});
|
||||
|
||||
it('should be able to build a react-router application', async () => {
|
||||
const appName = uniq('app');
|
||||
runCLI(
|
||||
`generate @nx/react:app ${appName} --use-react-router --routing --no-interactive`
|
||||
);
|
||||
|
||||
const buildResult = runCLI(`build ${appName}`);
|
||||
expect(buildResult).toContain('Successfully ran target build');
|
||||
});
|
||||
|
||||
it('should be able to lint a react-router application', async () => {
|
||||
const appName = uniq('app');
|
||||
runCLI(
|
||||
`generate @nx/react:app ${appName} --use-react-router --routing --linter=eslint --no-interactive`
|
||||
);
|
||||
|
||||
const buildResult = runCLI(`lint ${appName}`);
|
||||
expect(buildResult).toContain('Successfully ran target lint');
|
||||
});
|
||||
|
||||
it('should be able to test a react-router application', async () => {
|
||||
const appName = uniq('app');
|
||||
runCLI(
|
||||
`generate @nx/react:app ${appName} --use-react-router --routing --unit-test-runner=vitest --no-interactive`
|
||||
);
|
||||
|
||||
const buildResult = runCLI(`test ${appName}`);
|
||||
expect(buildResult).toContain('Successfully ran target test');
|
||||
});
|
||||
});
|
||||
@ -222,6 +222,7 @@ export function runCreateWorkspace(
|
||||
cwd = e2eCwd,
|
||||
bundler,
|
||||
routing,
|
||||
useReactRouter,
|
||||
standaloneApi,
|
||||
docker,
|
||||
nextAppDir,
|
||||
@ -244,6 +245,7 @@ export function runCreateWorkspace(
|
||||
bundler?: 'webpack' | 'vite';
|
||||
standaloneApi?: boolean;
|
||||
routing?: boolean;
|
||||
useReactRouter?: boolean;
|
||||
docker?: boolean;
|
||||
nextAppDir?: boolean;
|
||||
nextSrcDir?: boolean;
|
||||
@ -295,6 +297,10 @@ export function runCreateWorkspace(
|
||||
command += ` --routing=${routing}`;
|
||||
}
|
||||
|
||||
if (useReactRouter !== undefined) {
|
||||
command += ` --useReactRouter=${useReactRouter}`;
|
||||
}
|
||||
|
||||
if (base) {
|
||||
command += ` --defaultBase="${base}"`;
|
||||
}
|
||||
|
||||
@ -495,7 +495,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
setupFiles: ['src/test-setup.ts'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
|
||||
@ -48,11 +48,13 @@ interface ReactArguments extends BaseArguments {
|
||||
stack: 'react';
|
||||
workspaceType: 'standalone' | 'integrated';
|
||||
appName: string;
|
||||
framework: 'none' | 'next' | 'remix';
|
||||
framework: 'none' | 'next';
|
||||
style: string;
|
||||
bundler: 'webpack' | 'vite' | 'rspack';
|
||||
nextAppDir: boolean;
|
||||
nextSrcDir: boolean;
|
||||
useReactRouter: boolean;
|
||||
routing: boolean;
|
||||
unitTestRunner: 'none' | 'jest' | 'vitest';
|
||||
e2eTestRunner: 'none' | 'cypress' | 'playwright';
|
||||
}
|
||||
@ -156,10 +158,14 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
|
||||
default: true,
|
||||
})
|
||||
.option('routing', {
|
||||
describe: chalk.dim`Add a routing setup for an Angular app.`,
|
||||
describe: chalk.dim`Add a routing setup for an Angular or React app.`,
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
})
|
||||
.option('useReactRouter', {
|
||||
describe: chalk.dim`Generate a Server-Side Rendered (SSR) React app using React Router.`,
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('bundler', {
|
||||
describe: chalk.dim`Bundler to be used to build the app.`,
|
||||
type: 'string',
|
||||
@ -378,8 +384,6 @@ async function determineStack(
|
||||
case Preset.ReactMonorepo:
|
||||
case Preset.NextJs:
|
||||
case Preset.NextJsStandalone:
|
||||
case Preset.RemixStandalone:
|
||||
case Preset.RemixMonorepo:
|
||||
case Preset.ReactNative:
|
||||
case Preset.Expo:
|
||||
return 'react';
|
||||
@ -591,6 +595,8 @@ async function determineReactOptions(
|
||||
let bundler: undefined | 'webpack' | 'vite' | 'rspack' = undefined;
|
||||
let unitTestRunner: undefined | 'none' | 'jest' | 'vitest' = undefined;
|
||||
let e2eTestRunner: undefined | 'none' | 'cypress' | 'playwright' = undefined;
|
||||
let useReactRouter = false;
|
||||
let routing = true;
|
||||
let nextAppDir = false;
|
||||
let nextSrcDir = false;
|
||||
let linter: undefined | 'none' | 'eslint';
|
||||
@ -602,8 +608,7 @@ async function determineReactOptions(
|
||||
preset = parsedArgs.preset;
|
||||
if (
|
||||
preset === Preset.ReactStandalone ||
|
||||
preset === Preset.NextJsStandalone ||
|
||||
preset === Preset.RemixStandalone
|
||||
preset === Preset.NextJsStandalone
|
||||
) {
|
||||
appName = parsedArgs.appName ?? parsedArgs.name;
|
||||
} else {
|
||||
@ -629,17 +634,12 @@ async function determineReactOptions(
|
||||
} else {
|
||||
preset = Preset.NextJs;
|
||||
}
|
||||
} else if (framework === 'remix') {
|
||||
if (isStandalone) {
|
||||
preset = Preset.RemixStandalone;
|
||||
} else {
|
||||
preset = Preset.RemixMonorepo;
|
||||
}
|
||||
} else if (framework === 'react-native') {
|
||||
preset = Preset.ReactNative;
|
||||
} else if (framework === 'expo') {
|
||||
preset = Preset.Expo;
|
||||
} else {
|
||||
useReactRouter = await determineReactRouter(parsedArgs);
|
||||
if (isStandalone) {
|
||||
preset = Preset.ReactStandalone;
|
||||
} else {
|
||||
@ -649,7 +649,7 @@ async function determineReactOptions(
|
||||
}
|
||||
|
||||
if (preset === Preset.ReactStandalone || preset === Preset.ReactMonorepo) {
|
||||
bundler = await determineReactBundler(parsedArgs);
|
||||
bundler = useReactRouter ? 'vite' : await determineReactBundler(parsedArgs);
|
||||
unitTestRunner = await determineUnitTestRunner(parsedArgs, {
|
||||
preferVitest: bundler === 'vite',
|
||||
});
|
||||
@ -661,14 +661,6 @@ async function determineReactOptions(
|
||||
exclude: 'vitest',
|
||||
});
|
||||
e2eTestRunner = await determineE2eTestRunner(parsedArgs);
|
||||
} else if (
|
||||
preset === Preset.RemixMonorepo ||
|
||||
preset === Preset.RemixStandalone
|
||||
) {
|
||||
unitTestRunner = await determineUnitTestRunner(parsedArgs, {
|
||||
preferVitest: true,
|
||||
});
|
||||
e2eTestRunner = await determineE2eTestRunner(parsedArgs);
|
||||
} else if (preset === Preset.ReactNative || preset === Preset.Expo) {
|
||||
unitTestRunner = await determineUnitTestRunner(parsedArgs, {
|
||||
exclude: 'vitest',
|
||||
@ -748,6 +740,8 @@ async function determineReactOptions(
|
||||
nextSrcDir,
|
||||
unitTestRunner,
|
||||
e2eTestRunner,
|
||||
useReactRouter,
|
||||
routing,
|
||||
linter,
|
||||
formatter,
|
||||
workspaces,
|
||||
@ -1221,9 +1215,9 @@ async function determineAppName(
|
||||
|
||||
async function determineReactFramework(
|
||||
parsedArgs: yargs.Arguments<ReactArguments>
|
||||
): Promise<'none' | 'nextjs' | 'remix' | 'expo' | 'react-native'> {
|
||||
): Promise<'none' | 'nextjs' | 'expo' | 'react-native'> {
|
||||
const reply = await enquirer.prompt<{
|
||||
framework: 'none' | 'nextjs' | 'remix' | 'expo' | 'react-native';
|
||||
framework: 'none' | 'nextjs' | 'expo' | 'react-native';
|
||||
}>([
|
||||
{
|
||||
name: 'framework',
|
||||
@ -1233,23 +1227,19 @@ async function determineReactFramework(
|
||||
{
|
||||
name: 'none',
|
||||
message: 'None',
|
||||
hint: ' I only want react and react-dom',
|
||||
hint: ' I only want react, react-dom or react-router',
|
||||
},
|
||||
{
|
||||
name: 'nextjs',
|
||||
message: 'Next.js [ https://nextjs.org/ ]',
|
||||
},
|
||||
{
|
||||
name: 'remix',
|
||||
message: 'Remix [ https://remix.run/ ]',
|
||||
message: 'Next.js [ https://nextjs.org/ ]',
|
||||
},
|
||||
{
|
||||
name: 'expo',
|
||||
message: 'Expo [ https://expo.io/ ]',
|
||||
message: 'Expo [ https://expo.io/ ]',
|
||||
},
|
||||
{
|
||||
name: 'react-native',
|
||||
message: 'React Native [ https://reactnative.dev/ ]',
|
||||
message: 'React Native [ https://reactnative.dev/ ]',
|
||||
},
|
||||
],
|
||||
initial: 0,
|
||||
@ -1494,3 +1484,35 @@ async function determineE2eTestRunner(
|
||||
]);
|
||||
return reply.e2eTestRunner;
|
||||
}
|
||||
|
||||
async function determineReactRouter(
|
||||
parsedArgs: yargs.Arguments<{
|
||||
useReactRouter?: boolean;
|
||||
}>
|
||||
): Promise<boolean> {
|
||||
if (parsedArgs.routing !== undefined && parsedArgs.routing === false)
|
||||
return false;
|
||||
if (parsedArgs.useReactRouter !== undefined) return parsedArgs.useReactRouter;
|
||||
const reply = await enquirer.prompt<{
|
||||
response: 'Yes' | 'No';
|
||||
}>([
|
||||
{
|
||||
message:
|
||||
'Would you like to use React Router for server-side rendering [https://reactrouter.com/]?',
|
||||
type: 'autocomplete',
|
||||
name: 'response',
|
||||
skip: !parsedArgs.interactive || isCI(),
|
||||
choices: [
|
||||
{
|
||||
name: 'Yes',
|
||||
hint: 'I want to use React Router',
|
||||
},
|
||||
{
|
||||
name: 'No',
|
||||
},
|
||||
],
|
||||
initial: 0,
|
||||
},
|
||||
]);
|
||||
return reply.response === 'Yes';
|
||||
}
|
||||
|
||||
@ -112,7 +112,6 @@ function getWorkspaceGlobsFromPreset(preset: string): string[] {
|
||||
case Preset.Nuxt:
|
||||
case Preset.ReactNative:
|
||||
case Preset.ReactMonorepo:
|
||||
case Preset.RemixMonorepo:
|
||||
case Preset.VueMonorepo:
|
||||
case Preset.WebComponents:
|
||||
return ['apps/*'];
|
||||
|
||||
@ -13,8 +13,6 @@ export enum Preset {
|
||||
NuxtStandalone = 'nuxt-standalone',
|
||||
NextJs = 'next',
|
||||
NextJsStandalone = 'nextjs-standalone',
|
||||
RemixMonorepo = 'remix-monorepo',
|
||||
RemixStandalone = 'remix-standalone',
|
||||
ReactNative = 'react-native',
|
||||
Expo = 'expo',
|
||||
Nest = 'nest',
|
||||
|
||||
@ -184,7 +184,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-app',
|
||||
@ -585,7 +585,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/myApp',
|
||||
|
||||
@ -448,7 +448,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-app',
|
||||
@ -511,7 +511,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-app',
|
||||
|
||||
@ -1065,6 +1065,104 @@ describe('app', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('--use-react-router', () => {
|
||||
it('should add react-router to vite.config', async () => {
|
||||
await applicationGenerator(appTree, {
|
||||
...schema,
|
||||
skipFormat: false,
|
||||
useReactRouter: true,
|
||||
routing: true,
|
||||
bundler: 'vite',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
|
||||
expect(appTree.read('my-app/vite.config.ts', 'utf-8'))
|
||||
.toMatchInlineSnapshot(`
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import { reactRouter } from '@react-router/dev/vite';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/my-app',
|
||||
server: {
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
},
|
||||
preview: {
|
||||
port: 4300,
|
||||
host: 'localhost',
|
||||
},
|
||||
plugins: [
|
||||
!process.env.VITEST && reactRouter(),
|
||||
nxViteTsPaths(),
|
||||
nxCopyAssetsPlugin(['*.md']),
|
||||
],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
build: {
|
||||
outDir: '../dist/my-app',
|
||||
emptyOutDir: true,
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-app',
|
||||
provider: 'v8' as const,
|
||||
},
|
||||
},
|
||||
}));
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should add types to tsconfig', async () => {
|
||||
await applicationGenerator(appTree, {
|
||||
...schema,
|
||||
skipFormat: false,
|
||||
useReactRouter: true,
|
||||
routing: true,
|
||||
bundler: 'vite',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
const tsconfigSpec = readJson(appTree, 'my-app/tsconfig.json');
|
||||
expect(tsconfigSpec.compilerOptions.types).toEqual([
|
||||
'vite/client',
|
||||
'vitest',
|
||||
'@react-router/node',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should have a project package.json', async () => {
|
||||
await applicationGenerator(appTree, {
|
||||
...schema,
|
||||
skipFormat: false,
|
||||
useReactRouter: true,
|
||||
routing: true,
|
||||
bundler: 'vite',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
|
||||
const packageJson = readJson(appTree, 'my-app/package.json');
|
||||
expect(packageJson.dependencies['@react-router/node']).toBeDefined();
|
||||
expect(packageJson.dependencies['@react-router/serve']).toBeDefined();
|
||||
expect(packageJson.dependencies['react-router']).toBeDefined();
|
||||
expect(packageJson.devDependencies['@react-router/dev']).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('--directory="." (--root-project)', () => {
|
||||
it('should create files at the root', async () => {
|
||||
await applicationGenerator(appTree, {
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
readNxJson,
|
||||
runTasksInSerial,
|
||||
Tree,
|
||||
updateJson,
|
||||
updateNxJson,
|
||||
} from '@nx/devkit';
|
||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
||||
@ -43,6 +44,7 @@ import {
|
||||
} from './lib/bundlers/add-vite';
|
||||
import { Schema } from './schema';
|
||||
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
||||
import { promptWhenInteractive } from '@nx/devkit/src/generators/prompt';
|
||||
|
||||
export async function applicationGenerator(
|
||||
tree: Tree,
|
||||
@ -73,6 +75,34 @@ export async function applicationGeneratorInternal(
|
||||
|
||||
const options = await normalizeOptions(tree, schema);
|
||||
|
||||
options.useReactRouter = options.routing
|
||||
? options.useReactRouter ??
|
||||
(await promptWhenInteractive<{
|
||||
response: 'Yes' | 'No';
|
||||
}>(
|
||||
{
|
||||
name: 'response',
|
||||
message:
|
||||
'Would you like to use react-router for server-side rendering?',
|
||||
type: 'autocomplete',
|
||||
choices: [
|
||||
{
|
||||
name: 'Yes',
|
||||
message:
|
||||
'I want to use react-router [ https://reactrouter.com/start/framework/routing ]',
|
||||
},
|
||||
{
|
||||
name: 'No',
|
||||
message:
|
||||
'I do not want to use react-router for server-side rendering',
|
||||
},
|
||||
],
|
||||
initial: 0,
|
||||
},
|
||||
{ response: 'No' }
|
||||
).then((r) => r.response === 'Yes'))
|
||||
: false;
|
||||
|
||||
showPossibleWarnings(tree, options);
|
||||
|
||||
const initTask = await reactInitGenerator(tree, {
|
||||
@ -158,18 +188,41 @@ export async function applicationGeneratorInternal(
|
||||
|
||||
// Handle tsconfig.spec.json for jest or vitest
|
||||
updateSpecConfig(tree, options);
|
||||
const stylePreprocessorTask = await installCommonDependencies(tree, options);
|
||||
tasks.push(stylePreprocessorTask);
|
||||
const commonDependencyTask = await installCommonDependencies(tree, options);
|
||||
tasks.push(commonDependencyTask);
|
||||
const styledTask = addStyledModuleDependencies(tree, options);
|
||||
tasks.push(styledTask);
|
||||
const routingTask = addRouting(tree, options);
|
||||
tasks.push(routingTask);
|
||||
if (!options.useReactRouter) {
|
||||
const routingTask = addRouting(tree, options);
|
||||
tasks.push(routingTask);
|
||||
}
|
||||
setDefaults(tree, options);
|
||||
|
||||
if (options.bundler === 'rspack' && options.style === 'styled-jsx') {
|
||||
handleStyledJsxForRspack(tasks, tree, options);
|
||||
}
|
||||
|
||||
if (options.useReactRouter) {
|
||||
updateJson(
|
||||
tree,
|
||||
joinPathFragments(options.appProjectRoot, 'tsconfig.json'),
|
||||
(json) => {
|
||||
const types = new Set(json.compilerOptions?.types || []);
|
||||
types.add('@react-router/node');
|
||||
return {
|
||||
...json,
|
||||
compilerOptions: {
|
||||
...json.compilerOptions,
|
||||
jsx: 'react-jsx',
|
||||
moduleResolution: 'bundler',
|
||||
types: Array.from(types),
|
||||
},
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Only for the new TS solution
|
||||
updateTsconfigFiles(
|
||||
tree,
|
||||
options.appProjectRoot,
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import * as React from "react";
|
||||
import { NavLink } from "react-router";
|
||||
|
||||
export function AppNav() {
|
||||
return (
|
||||
<nav>
|
||||
<NavLink to="/" end>
|
||||
Home
|
||||
</NavLink>
|
||||
<NavLink to="/about" end>
|
||||
About
|
||||
</NavLink>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* By default, React Router will handle hydrating your app on the client for you.
|
||||
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx react-router reveal` ✨
|
||||
* For more information, see https://reactrouter.com/explanation/special-files#entryclienttsx
|
||||
*/
|
||||
|
||||
import { HydratedRouter } from 'react-router/dom';
|
||||
import { startTransition, StrictMode } from "react";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
|
||||
startTransition(() => {
|
||||
hydrateRoot(
|
||||
document,
|
||||
<StrictMode>
|
||||
<HydratedRouter />
|
||||
</StrictMode>
|
||||
);
|
||||
});
|
||||
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* By default, React Router will handle generating the HTTP Response for you.
|
||||
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
|
||||
* For more information, see https://reactrouter.com/explanation/special-files#entryservertsx
|
||||
*/
|
||||
|
||||
import { PassThrough } from "node:stream";
|
||||
|
||||
import type { AppLoadContext, EntryContext } from "react-router";
|
||||
import { createReadableStreamFromReadable } from "@react-router/node";
|
||||
import { ServerRouter } from "react-router";
|
||||
import { isbot } from "isbot";
|
||||
import type { RenderToPipeableStreamOptions } from "react-dom/server";
|
||||
import { renderToPipeableStream } from "react-dom/server";
|
||||
|
||||
export const streamTimeout = 5_000;
|
||||
|
||||
export default function handleRequest(
|
||||
request: Request,
|
||||
responseStatusCode: number,
|
||||
responseHeaders: Headers,
|
||||
routerContext: EntryContext,
|
||||
loadContext: AppLoadContext
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let shellRendered = false;
|
||||
const userAgent = request.headers.get("user-agent");
|
||||
|
||||
// Ensure requests from bots and SPA Mode renders wait for all content to load before responding
|
||||
// https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation
|
||||
const readyOption: keyof RenderToPipeableStreamOptions =
|
||||
(userAgent && isbot(userAgent)) || routerContext.isSpaMode
|
||||
? "onAllReady"
|
||||
: "onShellReady";
|
||||
|
||||
const { pipe, abort } = renderToPipeableStream(
|
||||
<ServerRouter context={routerContext} url={request.url} />,
|
||||
{
|
||||
[readyOption]() {
|
||||
shellRendered = true;
|
||||
const body = new PassThrough();
|
||||
const stream = createReadableStreamFromReadable(body);
|
||||
|
||||
responseHeaders.set("Content-Type", "text/html");
|
||||
|
||||
resolve(
|
||||
new Response(stream, {
|
||||
headers: responseHeaders,
|
||||
status: responseStatusCode,
|
||||
})
|
||||
);
|
||||
|
||||
pipe(body);
|
||||
},
|
||||
onShellError(error: unknown) {
|
||||
reject(error);
|
||||
},
|
||||
onError(error: unknown) {
|
||||
responseStatusCode = 500;
|
||||
// Log streaming rendering errors from inside the shell. Don't log
|
||||
// errors encountered during initial shell rendering since they'll
|
||||
// reject and get logged in handleDocumentRequest.
|
||||
if (shellRendered) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Abort the rendering stream after the `streamTimeout` so it has time to
|
||||
// flush down the rejected boundaries
|
||||
setTimeout(abort, streamTimeout + 1000);
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
import {
|
||||
Links,
|
||||
Meta,
|
||||
Outlet,
|
||||
Scripts,
|
||||
ScrollRestoration,
|
||||
type MetaFunction,
|
||||
type LinksFunction
|
||||
} from "react-router";
|
||||
|
||||
import { AppNav } from './app-nav'
|
||||
|
||||
export const meta: MetaFunction = () => ([{
|
||||
title: "New Nx React Router App",
|
||||
}]);
|
||||
|
||||
export const links: LinksFunction = () => [
|
||||
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
|
||||
{
|
||||
rel: "preconnect",
|
||||
href: "https://fonts.gstatic.com",
|
||||
crossOrigin: "anonymous",
|
||||
},
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
|
||||
},
|
||||
];
|
||||
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<Meta />
|
||||
<Links />
|
||||
</head>
|
||||
<body>
|
||||
<AppNav />
|
||||
{children}
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return <Outlet />;
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
import { type RouteConfig, index, route } from "@react-router/dev/routes";
|
||||
|
||||
export default [
|
||||
index('<%- js ? `./${fileName}.jsx` : `./${fileName}.tsx` %>'),
|
||||
route('about', './routes/about.tsx')
|
||||
] satisfies RouteConfig;
|
||||
@ -0,0 +1,7 @@
|
||||
export default function AboutComponent() {
|
||||
return (
|
||||
<div>
|
||||
<h1>About!!!</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,5 @@
|
||||
import type { Config } from "@react-router/dev/config";
|
||||
|
||||
export default {
|
||||
ssr: true,
|
||||
} satisfies Config;
|
||||
@ -0,0 +1,16 @@
|
||||
import { createRoutesStub } from 'react-router';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import App from '../../app/app';
|
||||
|
||||
test('renders loader data', async () => {
|
||||
const ReactRouterStub = createRoutesStub([
|
||||
{
|
||||
path: '/',
|
||||
Component: App,
|
||||
},
|
||||
]);
|
||||
|
||||
render(<ReactRouterStub />);
|
||||
|
||||
await waitFor(() => screen.findByText('Hello there,'));
|
||||
});
|
||||
@ -0,0 +1,23 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"app/**/*.ts",
|
||||
"app/**/*.tsx",
|
||||
"app/**/*.js",
|
||||
"app/**/*.jsx",
|
||||
"**/.server/**/*.ts",
|
||||
"**/.server/**/*.tsx",
|
||||
"**/.client/**/*.ts",
|
||||
"**/.client/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"tests/**/*.spec.ts",
|
||||
"tests/**/*.test.ts",
|
||||
"tests/**/*.spec.tsx",
|
||||
"tests/**/*.test.tsx",
|
||||
"tests/**/*.spec.js",
|
||||
"tests/**/*.test.js",
|
||||
"tests/**/*.spec.jsx",
|
||||
"tests/**/*.test.jsx"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
{
|
||||
"extends": "<%= offsetFromRoot %>tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
||||
"types": ["@react-router/node", "vite/client"],
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react-jsx",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"target": "ES2022",
|
||||
"strict": true,
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
// Vite takes care of building everything.
|
||||
"noEmit": true
|
||||
},
|
||||
"include": [],
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
.cache
|
||||
build
|
||||
public/build
|
||||
.env
|
||||
.react-router
|
||||
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "<%= projectName %>",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"@react-router/node": "<%= reactRouterVersion %>",
|
||||
"@react-router/serve": "<%= reactRouterVersion %>",
|
||||
"isbot": "<%= reactRouterIsBotVersion %>",
|
||||
"react": "<%= reactVersion %>",
|
||||
"react-dom": "<%= reactVersion %>",
|
||||
"react-router": "<%= reactRouterVersion %>"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-router/dev": "<%= reactRouterVersion %>",
|
||||
"@types/node": "<%= typesNodeVersion %>",
|
||||
"@types/react": "<%= reactVersion %>",
|
||||
"@types/react-dom": "<%= reactVersion %>"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
@ -0,0 +1,866 @@
|
||||
/*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
This is a starter component and can be deleted.
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
Delete this file and get started with your project!
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*/
|
||||
export function NxWelcome({ title }: { title: string }) {
|
||||
return (
|
||||
<>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||
'Noto Color Emoji';
|
||||
line-height: 1.5;
|
||||
tab-size: 4;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
body {
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
p,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: currentColor;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
'Liberation Mono', 'Courier New', monospace;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
shape-rendering: auto;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
pre {
|
||||
background-color: rgba(55, 65, 81, 1);
|
||||
border-radius: 0.25rem;
|
||||
color: rgba(229, 231, 235, 1);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
'Liberation Mono', 'Courier New', monospace;
|
||||
overflow: auto;
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.rounded {
|
||||
border-radius: 1.5rem;
|
||||
}
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 768px;
|
||||
padding-bottom: 3rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
width: 100%;
|
||||
}
|
||||
#welcome {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
#welcome h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1;
|
||||
}
|
||||
#welcome span {
|
||||
display: block;
|
||||
font-size: 1.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 2.25rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
#hero {
|
||||
align-items: center;
|
||||
background-color: hsla(214, 62%, 21%, 1);
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
#hero .text-container {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
padding: 3rem 2rem;
|
||||
}
|
||||
#hero .text-container h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
position: relative;
|
||||
}
|
||||
#hero .text-container h2 svg {
|
||||
color: hsla(162, 47%, 50%, 1);
|
||||
height: 2rem;
|
||||
left: -0.25rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 2rem;
|
||||
}
|
||||
#hero .text-container h2 span {
|
||||
margin-left: 2.5rem;
|
||||
}
|
||||
#hero .text-container a {
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border-radius: 0.75rem;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
display: inline-block;
|
||||
margin-top: 1.5rem;
|
||||
padding: 1rem 2rem;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
#hero .logo-container {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
#hero .logo-container svg {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
width: 66.666667%;
|
||||
}
|
||||
#middle-content {
|
||||
align-items: flex-start;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
|
||||
#middle-content #middle-content-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
#learning-materials {
|
||||
padding: 2.5rem 2rem;
|
||||
}
|
||||
#learning-materials h2 {
|
||||
font-weight: 500;
|
||||
font-size: 1.25rem;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.list-item-link {
|
||||
align-items: center;
|
||||
border-radius: 0.75rem;
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 100%;
|
||||
}
|
||||
.list-item-link svg:first-child {
|
||||
margin-right: 1rem;
|
||||
height: 1.5rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 1.5rem;
|
||||
}
|
||||
.list-item-link > span {
|
||||
flex-grow: 1;
|
||||
font-weight: 400;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.list-item-link > span > span {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 300;
|
||||
line-height: 1rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.list-item-link svg:last-child {
|
||||
height: 1rem;
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 1rem;
|
||||
}
|
||||
.list-item-link:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background-color: hsla(162, 55%, 33%, 1);
|
||||
}
|
||||
.list-item-link:hover > span {}
|
||||
.list-item-link:hover > span > span {
|
||||
color: rgba(243, 244, 246, 1);
|
||||
}
|
||||
.list-item-link:hover svg:last-child {
|
||||
transform: translateX(0.25rem);
|
||||
}
|
||||
#other-links {}
|
||||
.button-pill {
|
||||
padding: 1.5rem 2rem;
|
||||
margin-bottom: 2rem;
|
||||
transition-duration: 300ms;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
.button-pill svg {
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
flex-shrink: 0;
|
||||
width: 3rem;
|
||||
}
|
||||
.button-pill > span {
|
||||
letter-spacing: -0.025em;
|
||||
font-weight: 400;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.button-pill span span {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
.button-pill:hover svg,
|
||||
.button-pill:hover {
|
||||
color: rgba(255, 255, 255, 1) !important;
|
||||
}
|
||||
#nx-console:hover {
|
||||
background-color: rgba(0, 122, 204, 1);
|
||||
}
|
||||
#nx-console svg {
|
||||
color: rgba(0, 122, 204, 1);
|
||||
}
|
||||
#nx-console-jetbrains {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
#nx-console-jetbrains:hover {
|
||||
background-color: rgba(255, 49, 140, 1);
|
||||
}
|
||||
#nx-console-jetbrains svg {
|
||||
color: rgba(255, 49, 140, 1);
|
||||
}
|
||||
#nx-repo:hover {
|
||||
background-color: rgba(24, 23, 23, 1);
|
||||
}
|
||||
#nx-repo svg {
|
||||
color: rgba(24, 23, 23, 1);
|
||||
}
|
||||
#nx-cloud {
|
||||
margin-bottom: 2rem;
|
||||
margin-top: 2rem;
|
||||
padding: 2.5rem 2rem;
|
||||
}
|
||||
#nx-cloud > div {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
#nx-cloud > div svg {
|
||||
border-radius: 0.375rem;
|
||||
flex-shrink: 0;
|
||||
width: 3rem;
|
||||
}
|
||||
#nx-cloud > div h2 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#nx-cloud > div h2 span {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
#nx-cloud p {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#nx-cloud pre {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#nx-cloud a {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
margin-top: 1.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
#nx-cloud a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#commands {
|
||||
padding: 2.5rem 2rem;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
#commands h2 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#commands p {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
details {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
details pre > span {
|
||||
color: rgba(181, 181, 181, 1);
|
||||
display: block;
|
||||
}
|
||||
summary {
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
font-weight: 400;
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
summary:hover {
|
||||
background-color: rgba(243, 244, 246, 1);
|
||||
}
|
||||
summary svg {
|
||||
height: 1.5rem;
|
||||
margin-right: 1rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
#love {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
margin-top: 3.5rem;
|
||||
opacity: 0.6;
|
||||
text-align: center;
|
||||
}
|
||||
#love svg {
|
||||
color: rgba(252, 165, 165, 1);
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: inline;
|
||||
margin-top: -0.25rem;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
#hero {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
#hero .logo-container {
|
||||
display: flex;
|
||||
}
|
||||
#middle-content {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 4rem;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<div className="wrapper">
|
||||
<div className="container">
|
||||
<div id="welcome">
|
||||
<h1>
|
||||
<span> Hello there, </span>
|
||||
Welcome {title} 👋
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div id="hero" className="rounded">
|
||||
<div className="text-container">
|
||||
<h2>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"
|
||||
/>
|
||||
</svg>
|
||||
<span>You're up and running</span>
|
||||
</h2>
|
||||
<a href="#commands"> What's next? </a>
|
||||
</div>
|
||||
<div className="logo-container">
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="middle-content">
|
||||
<div id="middle-content-container">
|
||||
<div id="learning-materials" className="rounded shadow">
|
||||
<h2>Learning materials</h2>
|
||||
<a
|
||||
href="https://nx.dev/getting-started/intro?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Documentation
|
||||
<span> Everything is in there </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://nx.dev/blog/?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Blog
|
||||
<span> Changelog, features & events </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.youtube.com/@NxDevtools/videos?utm_source=nx-project&sub_confirmation=1"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>YouTube</title>
|
||||
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
|
||||
</svg>
|
||||
<span>
|
||||
YouTube channel
|
||||
<span> Nx Show, talks & tutorials </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://nx.dev/recipes/react/remix#remix-with-nx"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Interactive tutorials
|
||||
<span> Create an app, step-by-step </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<a
|
||||
id="nx-repo"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://github.com/nrwl/nx?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
<span>
|
||||
Nx is open source
|
||||
<span> Love Nx? Give us a star! </span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div id="other-links">
|
||||
<a
|
||||
id="nx-console"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console&utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Visual Studio Code</title>
|
||||
<path d="M23.15 2.587L18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z" />
|
||||
</svg>
|
||||
<span>
|
||||
Install Nx Console for VSCode
|
||||
<span>The official VSCode extension for Nx.</span>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
id="nx-console-jetbrains"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://plugins.jetbrains.com/plugin/21060-nx-console"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
height="48"
|
||||
width="48"
|
||||
viewBox="20 20 60 60"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="m22.5 22.5h60v60h-60z" />
|
||||
<g fill="#fff">
|
||||
<path d="m29.03 71.25h22.5v3.75h-22.5z" />
|
||||
<path d="m28.09 38 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.44 1.06-1.31v-5.98h2.58v6a3.48 3.48 0 0 1 -.87 2.6 3.56 3.56 0 0 1 -2.57.95 3.84 3.84 0 0 1 -3.34-1.55z" />
|
||||
<path d="m36 30h7.53v2.19h-5v1.44h4.49v2h-4.42v1.49h5v2.21h-7.6z" />
|
||||
<path d="m47.23 32.29h-2.8v-2.29h8.21v2.27h-2.81v7.1h-2.6z" />
|
||||
<path d="m29.13 43.08h4.42a3.53 3.53 0 0 1 2.55.83 2.09 2.09 0 0 1 .6 1.53 2.16 2.16 0 0 1 -1.44 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.61-1.31 2.59-3.55 2.59h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.24c.79 0 1.25-.26 1.25-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86 0-.5-.4-.87-1.27-.87z" />
|
||||
<path d="m38 43.08h4.1a4.19 4.19 0 0 1 3 1 2.93 2.93 0 0 1 .9 2.19 3 3 0 0 1 -1.93 2.89l2.24 3.27h-3l-1.88-2.84h-.87v2.84h-2.56zm4 4.5c.87 0 1.39-.43 1.39-1.11 0-.75-.54-1.12-1.4-1.12h-1.44v2.26z" />
|
||||
<path d="m49.59 43h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.69h-2.71zm2.27 5.73-1-2.65-1.06 2.65z" />
|
||||
<path d="m56.46 43.05h2.6v9.37h-2.6z" />
|
||||
<path d="m60.06 43.05h2.42l3.37 5v-5h2.57v9.37h-2.26l-3.53-5.14v5.14h-2.57z" />
|
||||
<path d="m68.86 51 1.45-1.73a4.84 4.84 0 0 0 3 1.13c.71 0 1.08-.24 1.08-.65 0-.4-.31-.6-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.37-3 3.62-3a5.89 5.89 0 0 1 3.86 1.25l-1.26 1.84a4.63 4.63 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .42.32.61 1.63.91 2.14.46 3.44 1.16 3.44 2.91 0 1.91-1.51 3-3.79 3a6.58 6.58 0 0 1 -4.35-1.5z" />
|
||||
</g>
|
||||
</svg>
|
||||
<span>
|
||||
Install Nx Console for JetBrains
|
||||
<span>
|
||||
Available for WebStorm, Intellij IDEA Ultimate and more!
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<div id="nx-cloud" className="rounded shadow">
|
||||
<div>
|
||||
<svg
|
||||
id="nx-cloud-logo"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
stroke="currentColor"
|
||||
fill="transparent"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeWidth="2"
|
||||
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||
/>
|
||||
<path
|
||||
strokeWidth="2"
|
||||
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||
/>
|
||||
</svg>
|
||||
<h2>
|
||||
Nx Cloud
|
||||
<span>Enable faster CI & better DX</span>
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
You can activate distributed tasks executions and caching by
|
||||
running:
|
||||
</p>
|
||||
<pre>nx connect</pre>
|
||||
<a
|
||||
href="https://nx.dev/nx-cloud?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{' '}
|
||||
What is Nx Cloud?{' '}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="commands" className="rounded shadow">
|
||||
<h2>Next steps</h2>
|
||||
<p>Here are some things you can do with Nx:</p>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Build, test and lint your app
|
||||
</summary>
|
||||
<pre><% if ( rootProject ) { %>
|
||||
<span># Build</span>
|
||||
nx build
|
||||
<span># Test</span>
|
||||
nx test
|
||||
<span># Lint</span>
|
||||
nx lint
|
||||
<span># Run them together!</span>
|
||||
nx run-many -t build test lint
|
||||
<% } else { %>
|
||||
<span># Build</span>
|
||||
nx build {title}
|
||||
<span># Test</span>
|
||||
nx test {title}
|
||||
<span># Lint</span>
|
||||
nx lint {title}
|
||||
<span># Run them together!</span>
|
||||
nx run-many -p {title} -t build test lint
|
||||
<% } %>
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
View project details
|
||||
</summary>
|
||||
<pre>nx show project {title}</pre>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
View interactive project graph
|
||||
</summary>
|
||||
<pre>nx graph</pre>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Add UI library
|
||||
</summary>
|
||||
<pre>
|
||||
<span># Generate UI lib</span>
|
||||
nx g @nx/react:lib ui
|
||||
<span># Add a component</span>
|
||||
nx g @nx/react:component ui/src/lib/button
|
||||
</pre>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<p id="love">
|
||||
Carefully crafted with
|
||||
<svg
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default NxWelcome;
|
||||
@ -0,0 +1,866 @@
|
||||
/*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
This is a starter component and can be deleted.
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
Delete this file and get started with your project!
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*/
|
||||
export function NxWelcome({ title }: { title: string }) {
|
||||
return (
|
||||
<>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||
'Noto Color Emoji';
|
||||
line-height: 1.5;
|
||||
tab-size: 4;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
body {
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
p,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: currentColor;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
'Liberation Mono', 'Courier New', monospace;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
shape-rendering: auto;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
pre {
|
||||
background-color: rgba(55, 65, 81, 1);
|
||||
border-radius: 0.25rem;
|
||||
color: rgba(229, 231, 235, 1);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
'Liberation Mono', 'Courier New', monospace;
|
||||
overflow: auto;
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.rounded {
|
||||
border-radius: 1.5rem;
|
||||
}
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 768px;
|
||||
padding-bottom: 3rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
width: 100%;
|
||||
}
|
||||
#welcome {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
#welcome h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1;
|
||||
}
|
||||
#welcome span {
|
||||
display: block;
|
||||
font-size: 1.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 2.25rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
#hero {
|
||||
align-items: center;
|
||||
background-color: hsla(214, 62%, 21%, 1);
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
#hero .text-container {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
padding: 3rem 2rem;
|
||||
}
|
||||
#hero .text-container h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
position: relative;
|
||||
}
|
||||
#hero .text-container h2 svg {
|
||||
color: hsla(162, 47%, 50%, 1);
|
||||
height: 2rem;
|
||||
left: -0.25rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 2rem;
|
||||
}
|
||||
#hero .text-container h2 span {
|
||||
margin-left: 2.5rem;
|
||||
}
|
||||
#hero .text-container a {
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border-radius: 0.75rem;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
display: inline-block;
|
||||
margin-top: 1.5rem;
|
||||
padding: 1rem 2rem;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
#hero .logo-container {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
#hero .logo-container svg {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
width: 66.666667%;
|
||||
}
|
||||
#middle-content {
|
||||
align-items: flex-start;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
|
||||
#middle-content #middle-content-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
#learning-materials {
|
||||
padding: 2.5rem 2rem;
|
||||
}
|
||||
#learning-materials h2 {
|
||||
font-weight: 500;
|
||||
font-size: 1.25rem;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.list-item-link {
|
||||
align-items: center;
|
||||
border-radius: 0.75rem;
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 100%;
|
||||
}
|
||||
.list-item-link svg:first-child {
|
||||
margin-right: 1rem;
|
||||
height: 1.5rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 1.5rem;
|
||||
}
|
||||
.list-item-link > span {
|
||||
flex-grow: 1;
|
||||
font-weight: 400;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.list-item-link > span > span {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 300;
|
||||
line-height: 1rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.list-item-link svg:last-child {
|
||||
height: 1rem;
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 1rem;
|
||||
}
|
||||
.list-item-link:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background-color: hsla(162, 55%, 33%, 1);
|
||||
}
|
||||
.list-item-link:hover > span {}
|
||||
.list-item-link:hover > span > span {
|
||||
color: rgba(243, 244, 246, 1);
|
||||
}
|
||||
.list-item-link:hover svg:last-child {
|
||||
transform: translateX(0.25rem);
|
||||
}
|
||||
#other-links {}
|
||||
.button-pill {
|
||||
padding: 1.5rem 2rem;
|
||||
margin-bottom: 2rem;
|
||||
transition-duration: 300ms;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
.button-pill svg {
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
flex-shrink: 0;
|
||||
width: 3rem;
|
||||
}
|
||||
.button-pill > span {
|
||||
letter-spacing: -0.025em;
|
||||
font-weight: 400;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.button-pill span span {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
.button-pill:hover svg,
|
||||
.button-pill:hover {
|
||||
color: rgba(255, 255, 255, 1) !important;
|
||||
}
|
||||
#nx-console:hover {
|
||||
background-color: rgba(0, 122, 204, 1);
|
||||
}
|
||||
#nx-console svg {
|
||||
color: rgba(0, 122, 204, 1);
|
||||
}
|
||||
#nx-console-jetbrains {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
#nx-console-jetbrains:hover {
|
||||
background-color: rgba(255, 49, 140, 1);
|
||||
}
|
||||
#nx-console-jetbrains svg {
|
||||
color: rgba(255, 49, 140, 1);
|
||||
}
|
||||
#nx-repo:hover {
|
||||
background-color: rgba(24, 23, 23, 1);
|
||||
}
|
||||
#nx-repo svg {
|
||||
color: rgba(24, 23, 23, 1);
|
||||
}
|
||||
#nx-cloud {
|
||||
margin-bottom: 2rem;
|
||||
margin-top: 2rem;
|
||||
padding: 2.5rem 2rem;
|
||||
}
|
||||
#nx-cloud > div {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
#nx-cloud > div svg {
|
||||
border-radius: 0.375rem;
|
||||
flex-shrink: 0;
|
||||
width: 3rem;
|
||||
}
|
||||
#nx-cloud > div h2 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#nx-cloud > div h2 span {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
#nx-cloud p {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#nx-cloud pre {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#nx-cloud a {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
margin-top: 1.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
#nx-cloud a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#commands {
|
||||
padding: 2.5rem 2rem;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
#commands h2 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#commands p {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
details {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
details pre > span {
|
||||
color: rgba(181, 181, 181, 1);
|
||||
display: block;
|
||||
}
|
||||
summary {
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
font-weight: 400;
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
summary:hover {
|
||||
background-color: rgba(243, 244, 246, 1);
|
||||
}
|
||||
summary svg {
|
||||
height: 1.5rem;
|
||||
margin-right: 1rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
#love {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
margin-top: 3.5rem;
|
||||
opacity: 0.6;
|
||||
text-align: center;
|
||||
}
|
||||
#love svg {
|
||||
color: rgba(252, 165, 165, 1);
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: inline;
|
||||
margin-top: -0.25rem;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
#hero {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
#hero .logo-container {
|
||||
display: flex;
|
||||
}
|
||||
#middle-content {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 4rem;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<div className="wrapper">
|
||||
<div className="container">
|
||||
<div id="welcome">
|
||||
<h1>
|
||||
<span> Hello there, </span>
|
||||
Welcome {title} 👋
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div id="hero" className="rounded">
|
||||
<div className="text-container">
|
||||
<h2>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"
|
||||
/>
|
||||
</svg>
|
||||
<span>You're up and running</span>
|
||||
</h2>
|
||||
<a href="#commands"> What's next? </a>
|
||||
</div>
|
||||
<div className="logo-container">
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="middle-content">
|
||||
<div id="middle-content-container">
|
||||
<div id="learning-materials" className="rounded shadow">
|
||||
<h2>Learning materials</h2>
|
||||
<a
|
||||
href="https://nx.dev/getting-started/intro?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Documentation
|
||||
<span> Everything is in there </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://nx.dev/blog/?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Blog
|
||||
<span> Changelog, features & events </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.youtube.com/@NxDevtools/videos?utm_source=nx-project&sub_confirmation=1"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>YouTube</title>
|
||||
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
|
||||
</svg>
|
||||
<span>
|
||||
YouTube channel
|
||||
<span> Nx Show, talks & tutorials </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://nx.dev/recipes/react/remix#remix-with-nx"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Interactive tutorials
|
||||
<span> Create an app, step-by-step </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<a
|
||||
id="nx-repo"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://github.com/nrwl/nx?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
<span>
|
||||
Nx is open source
|
||||
<span> Love Nx? Give us a star! </span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div id="other-links">
|
||||
<a
|
||||
id="nx-console"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console&utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Visual Studio Code</title>
|
||||
<path d="M23.15 2.587L18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z" />
|
||||
</svg>
|
||||
<span>
|
||||
Install Nx Console for VSCode
|
||||
<span>The official VSCode extension for Nx.</span>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
id="nx-console-jetbrains"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://plugins.jetbrains.com/plugin/21060-nx-console"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
height="48"
|
||||
width="48"
|
||||
viewBox="20 20 60 60"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="m22.5 22.5h60v60h-60z" />
|
||||
<g fill="#fff">
|
||||
<path d="m29.03 71.25h22.5v3.75h-22.5z" />
|
||||
<path d="m28.09 38 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.44 1.06-1.31v-5.98h2.58v6a3.48 3.48 0 0 1 -.87 2.6 3.56 3.56 0 0 1 -2.57.95 3.84 3.84 0 0 1 -3.34-1.55z" />
|
||||
<path d="m36 30h7.53v2.19h-5v1.44h4.49v2h-4.42v1.49h5v2.21h-7.6z" />
|
||||
<path d="m47.23 32.29h-2.8v-2.29h8.21v2.27h-2.81v7.1h-2.6z" />
|
||||
<path d="m29.13 43.08h4.42a3.53 3.53 0 0 1 2.55.83 2.09 2.09 0 0 1 .6 1.53 2.16 2.16 0 0 1 -1.44 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.61-1.31 2.59-3.55 2.59h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.24c.79 0 1.25-.26 1.25-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86 0-.5-.4-.87-1.27-.87z" />
|
||||
<path d="m38 43.08h4.1a4.19 4.19 0 0 1 3 1 2.93 2.93 0 0 1 .9 2.19 3 3 0 0 1 -1.93 2.89l2.24 3.27h-3l-1.88-2.84h-.87v2.84h-2.56zm4 4.5c.87 0 1.39-.43 1.39-1.11 0-.75-.54-1.12-1.4-1.12h-1.44v2.26z" />
|
||||
<path d="m49.59 43h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.69h-2.71zm2.27 5.73-1-2.65-1.06 2.65z" />
|
||||
<path d="m56.46 43.05h2.6v9.37h-2.6z" />
|
||||
<path d="m60.06 43.05h2.42l3.37 5v-5h2.57v9.37h-2.26l-3.53-5.14v5.14h-2.57z" />
|
||||
<path d="m68.86 51 1.45-1.73a4.84 4.84 0 0 0 3 1.13c.71 0 1.08-.24 1.08-.65 0-.4-.31-.6-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.37-3 3.62-3a5.89 5.89 0 0 1 3.86 1.25l-1.26 1.84a4.63 4.63 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .42.32.61 1.63.91 2.14.46 3.44 1.16 3.44 2.91 0 1.91-1.51 3-3.79 3a6.58 6.58 0 0 1 -4.35-1.5z" />
|
||||
</g>
|
||||
</svg>
|
||||
<span>
|
||||
Install Nx Console for JetBrains
|
||||
<span>
|
||||
Available for WebStorm, Intellij IDEA Ultimate and more!
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<div id="nx-cloud" className="rounded shadow">
|
||||
<div>
|
||||
<svg
|
||||
id="nx-cloud-logo"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
stroke="currentColor"
|
||||
fill="transparent"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeWidth="2"
|
||||
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||
/>
|
||||
<path
|
||||
strokeWidth="2"
|
||||
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||
/>
|
||||
</svg>
|
||||
<h2>
|
||||
Nx Cloud
|
||||
<span>Enable faster CI & better DX</span>
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
You can activate distributed tasks executions and caching by
|
||||
running:
|
||||
</p>
|
||||
<pre>nx connect</pre>
|
||||
<a
|
||||
href="https://nx.dev/nx-cloud?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{' '}
|
||||
What is Nx Cloud?{' '}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="commands" className="rounded shadow">
|
||||
<h2>Next steps</h2>
|
||||
<p>Here are some things you can do with Nx:</p>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Build, test and lint your app
|
||||
</summary>
|
||||
<pre><% if ( rootProject ) { %>
|
||||
<span># Build</span>
|
||||
nx build
|
||||
<span># Test</span>
|
||||
nx test
|
||||
<span># Lint</span>
|
||||
nx lint
|
||||
<span># Run them together!</span>
|
||||
nx run-many -t build test lint
|
||||
<% } else { %>
|
||||
<span># Build</span>
|
||||
nx build {title}
|
||||
<span># Test</span>
|
||||
nx test {title}
|
||||
<span># Lint</span>
|
||||
nx lint {title}
|
||||
<span># Run them together!</span>
|
||||
nx run-many -p {title} -t build test lint
|
||||
<% } %>
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
View project details
|
||||
</summary>
|
||||
<pre>nx show project {title}</pre>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
View interactive project graph
|
||||
</summary>
|
||||
<pre>nx graph</pre>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Add UI library
|
||||
</summary>
|
||||
<pre>
|
||||
<span># Generate UI lib</span>
|
||||
nx g @nx/react:lib ui
|
||||
<span># Add a component</span>
|
||||
nx g @nx/react:component ui/src/lib/button
|
||||
</pre>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<p id="love">
|
||||
Carefully crafted with
|
||||
<svg
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default NxWelcome;
|
||||
@ -0,0 +1,864 @@
|
||||
/*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
This is a starter component and can be deleted.
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
Delete this file and get started with your project!
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*/
|
||||
export function NxWelcome({ title }: { title: string }) {
|
||||
return (
|
||||
<>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||
'Noto Color Emoji';
|
||||
line-height: 1.5;
|
||||
tab-size: 4;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
body {
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
p,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: currentColor;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
'Liberation Mono', 'Courier New', monospace;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
shape-rendering: auto;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
pre {
|
||||
background-color: rgba(55, 65, 81, 1);
|
||||
border-radius: 0.25rem;
|
||||
color: rgba(229, 231, 235, 1);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
'Liberation Mono', 'Courier New', monospace;
|
||||
overflow: auto;
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.rounded {
|
||||
border-radius: 1.5rem;
|
||||
}
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 768px;
|
||||
padding-bottom: 3rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
width: 100%;
|
||||
}
|
||||
#welcome {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
#welcome h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1;
|
||||
}
|
||||
#welcome span {
|
||||
display: block;
|
||||
font-size: 1.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 2.25rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
#hero {
|
||||
align-items: center;
|
||||
background-color: hsla(214, 62%, 21%, 1);
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
#hero .text-container {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
padding: 3rem 2rem;
|
||||
}
|
||||
#hero .text-container h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
position: relative;
|
||||
}
|
||||
#hero .text-container h2 svg {
|
||||
color: hsla(162, 47%, 50%, 1);
|
||||
height: 2rem;
|
||||
left: -0.25rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 2rem;
|
||||
}
|
||||
#hero .text-container h2 span {
|
||||
margin-left: 2.5rem;
|
||||
}
|
||||
#hero .text-container a {
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border-radius: 0.75rem;
|
||||
color: rgba(55, 65, 81, 1);
|
||||
display: inline-block;
|
||||
margin-top: 1.5rem;
|
||||
padding: 1rem 2rem;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
#hero .logo-container {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
#hero .logo-container svg {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
width: 66.666667%;
|
||||
}
|
||||
#middle-content {
|
||||
align-items: flex-start;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
|
||||
#middle-content #middle-content-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
#learning-materials {
|
||||
padding: 2.5rem 2rem;
|
||||
}
|
||||
#learning-materials h2 {
|
||||
font-weight: 500;
|
||||
font-size: 1.25rem;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.list-item-link {
|
||||
align-items: center;
|
||||
border-radius: 0.75rem;
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 100%;
|
||||
}
|
||||
.list-item-link svg:first-child {
|
||||
margin-right: 1rem;
|
||||
height: 1.5rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 1.5rem;
|
||||
}
|
||||
.list-item-link > span {
|
||||
flex-grow: 1;
|
||||
font-weight: 400;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.list-item-link > span > span {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 300;
|
||||
line-height: 1rem;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.list-item-link svg:last-child {
|
||||
height: 1rem;
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
width: 1rem;
|
||||
}
|
||||
.list-item-link:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background-color: hsla(162, 55%, 33%, 1);
|
||||
}
|
||||
.list-item-link:hover > span {}
|
||||
.list-item-link:hover > span > span {
|
||||
color: rgba(243, 244, 246, 1);
|
||||
}
|
||||
.list-item-link:hover svg:last-child {
|
||||
transform: translateX(0.25rem);
|
||||
}
|
||||
#other-links {}
|
||||
.button-pill {
|
||||
padding: 1.5rem 2rem;
|
||||
margin-bottom: 2rem;
|
||||
transition-duration: 300ms;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
.button-pill svg {
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
flex-shrink: 0;
|
||||
width: 3rem;
|
||||
}
|
||||
.button-pill > span {
|
||||
letter-spacing: -0.025em;
|
||||
font-weight: 400;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.button-pill span span {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
.button-pill:hover svg,
|
||||
.button-pill:hover {
|
||||
color: rgba(255, 255, 255, 1) !important;
|
||||
}
|
||||
#nx-console:hover {
|
||||
background-color: rgba(0, 122, 204, 1);
|
||||
}
|
||||
#nx-console svg {
|
||||
color: rgba(0, 122, 204, 1);
|
||||
}
|
||||
#nx-console-jetbrains {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
#nx-console-jetbrains:hover {
|
||||
background-color: rgba(255, 49, 140, 1);
|
||||
}
|
||||
#nx-console-jetbrains svg {
|
||||
color: rgba(255, 49, 140, 1);
|
||||
}
|
||||
#nx-repo:hover {
|
||||
background-color: rgba(24, 23, 23, 1);
|
||||
}
|
||||
#nx-repo svg {
|
||||
color: rgba(24, 23, 23, 1);
|
||||
}
|
||||
#nx-cloud {
|
||||
margin-bottom: 2rem;
|
||||
margin-top: 2rem;
|
||||
padding: 2.5rem 2rem;
|
||||
}
|
||||
#nx-cloud > div {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
#nx-cloud > div svg {
|
||||
border-radius: 0.375rem;
|
||||
flex-shrink: 0;
|
||||
width: 3rem;
|
||||
}
|
||||
#nx-cloud > div h2 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#nx-cloud > div h2 span {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
#nx-cloud p {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#nx-cloud pre {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#nx-cloud a {
|
||||
border-radius: 0.75rem;
|
||||
color: white;
|
||||
background-color: hsla(214, 62%, 21%, 1);
|
||||
display: inline-block;
|
||||
margin-top: 1.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
text-align:left;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
#commands {
|
||||
padding: 2.5rem 2rem;
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
#commands h2 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.025em;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#commands p {
|
||||
font-size: 1rem;
|
||||
font-weight: 300;
|
||||
line-height: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
details {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
details pre > span {
|
||||
color: rgba(181, 181, 181, 1);
|
||||
display: block;
|
||||
}
|
||||
summary {
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
font-weight: 400;
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
transition-property: background-color, border-color, color, fill, stroke,
|
||||
opacity, box-shadow, transform, filter, backdrop-filter,
|
||||
-webkit-backdrop-filter;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
summary:hover {
|
||||
background-color: rgba(243, 244, 246, 1);
|
||||
}
|
||||
summary svg {
|
||||
height: 1.5rem;
|
||||
margin-right: 1rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
#love {
|
||||
color: rgba(107, 114, 128, 1);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
margin-top: 3.5rem;
|
||||
opacity: 0.6;
|
||||
text-align: center;
|
||||
}
|
||||
#love svg {
|
||||
color: rgba(252, 165, 165, 1);
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: inline;
|
||||
margin-top: -0.25rem;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
#hero {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
#hero .logo-container {
|
||||
display: flex;
|
||||
}
|
||||
#middle-content {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 4rem;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<div className="wrapper">
|
||||
<div className="container">
|
||||
<div id="welcome">
|
||||
<h1>
|
||||
<span> Hello there, </span>
|
||||
Welcome {title} 👋
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div id="hero" className="rounded">
|
||||
<div className="text-container">
|
||||
<h2>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"
|
||||
/>
|
||||
</svg>
|
||||
<span>You're up and running</span>
|
||||
</h2>
|
||||
<a href="#commands"> What's next? </a>
|
||||
</div>
|
||||
<div className="logo-container">
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="middle-content">
|
||||
<div id="middle-content-container">
|
||||
<div id="learning-materials" className="rounded shadow">
|
||||
<h2>Learning materials</h2>
|
||||
<a
|
||||
href="https://nx.dev/getting-started/intro?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Documentation
|
||||
<span> Everything is in there </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://nx.dev/blog/?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Blog
|
||||
<span> Changelog, features & events </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.youtube.com/@NxDevtools/videos?utm_source=nx-project&sub_confirmation=1"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>YouTube</title>
|
||||
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
|
||||
</svg>
|
||||
<span>
|
||||
YouTube channel
|
||||
<span> Nx Show, talks & tutorials </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://nx.dev/recipes/react/remix#remix-with-nx"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="list-item-link"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Interactive tutorials
|
||||
<span> Create an app, step-by-step </span>
|
||||
</span>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<a
|
||||
id="nx-repo"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://github.com/nrwl/nx?utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
<span>
|
||||
Nx is open source
|
||||
<span> Love Nx? Give us a star! </span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div id="other-links">
|
||||
<a
|
||||
id="nx-console"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console&utm_source=nx-project"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Visual Studio Code</title>
|
||||
<path d="M23.15 2.587L18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z" />
|
||||
</svg>
|
||||
<span>
|
||||
Install Nx Console for VSCode
|
||||
<span>The official VSCode extension for Nx.</span>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
id="nx-console-jetbrains"
|
||||
className="button-pill rounded shadow"
|
||||
href="https://plugins.jetbrains.com/plugin/21060-nx-console"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
height="48"
|
||||
width="48"
|
||||
viewBox="20 20 60 60"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="m22.5 22.5h60v60h-60z" />
|
||||
<g fill="#fff">
|
||||
<path d="m29.03 71.25h22.5v3.75h-22.5z" />
|
||||
<path d="m28.09 38 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.44 1.06-1.31v-5.98h2.58v6a3.48 3.48 0 0 1 -.87 2.6 3.56 3.56 0 0 1 -2.57.95 3.84 3.84 0 0 1 -3.34-1.55z" />
|
||||
<path d="m36 30h7.53v2.19h-5v1.44h4.49v2h-4.42v1.49h5v2.21h-7.6z" />
|
||||
<path d="m47.23 32.29h-2.8v-2.29h8.21v2.27h-2.81v7.1h-2.6z" />
|
||||
<path d="m29.13 43.08h4.42a3.53 3.53 0 0 1 2.55.83 2.09 2.09 0 0 1 .6 1.53 2.16 2.16 0 0 1 -1.44 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.61-1.31 2.59-3.55 2.59h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.24c.79 0 1.25-.26 1.25-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86 0-.5-.4-.87-1.27-.87z" />
|
||||
<path d="m38 43.08h4.1a4.19 4.19 0 0 1 3 1 2.93 2.93 0 0 1 .9 2.19 3 3 0 0 1 -1.93 2.89l2.24 3.27h-3l-1.88-2.84h-.87v2.84h-2.56zm4 4.5c.87 0 1.39-.43 1.39-1.11 0-.75-.54-1.12-1.4-1.12h-1.44v2.26z" />
|
||||
<path d="m49.59 43h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.69h-2.71zm2.27 5.73-1-2.65-1.06 2.65z" />
|
||||
<path d="m56.46 43.05h2.6v9.37h-2.6z" />
|
||||
<path d="m60.06 43.05h2.42l3.37 5v-5h2.57v9.37h-2.26l-3.53-5.14v5.14h-2.57z" />
|
||||
<path d="m68.86 51 1.45-1.73a4.84 4.84 0 0 0 3 1.13c.71 0 1.08-.24 1.08-.65 0-.4-.31-.6-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.37-3 3.62-3a5.89 5.89 0 0 1 3.86 1.25l-1.26 1.84a4.63 4.63 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .42.32.61 1.63.91 2.14.46 3.44 1.16 3.44 2.91 0 1.91-1.51 3-3.79 3a6.58 6.58 0 0 1 -4.35-1.5z" />
|
||||
</g>
|
||||
</svg>
|
||||
<span>
|
||||
Install Nx Console for JetBrains
|
||||
<span>
|
||||
Available for WebStorm, Intellij IDEA Ultimate and more!
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<div id="nx-cloud" className="rounded shadow">
|
||||
<div>
|
||||
<svg
|
||||
id="nx-cloud-logo"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
stroke="currentColor"
|
||||
fill="transparent"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeWidth="2"
|
||||
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||
/>
|
||||
<path
|
||||
strokeWidth="2"
|
||||
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||
/>
|
||||
</svg>
|
||||
<h2>
|
||||
Nx Cloud
|
||||
<span>Enable faster CI & better DX</span>
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
Your Nx Cloud remote cache setup is almost complete.
|
||||
</p>
|
||||
|
||||
<a
|
||||
href="<%= connectCloudUrl %>"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Click here to finish
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="commands" className="rounded shadow">
|
||||
<h2>Next steps</h2>
|
||||
<p>Here are some things you can do with Nx:</p>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Build, test and lint your app
|
||||
</summary>
|
||||
<pre><% if ( rootProject ) { %>
|
||||
<span># Build</span>
|
||||
nx build
|
||||
<span># Test</span>
|
||||
nx test
|
||||
<span># Lint</span>
|
||||
nx lint
|
||||
<span># Run them together!</span>
|
||||
nx run-many -t build test lint
|
||||
<% } else { %>
|
||||
<span># Build</span>
|
||||
nx build {title}
|
||||
<span># Test</span>
|
||||
nx test {title}
|
||||
<span># Lint</span>
|
||||
nx lint {title}
|
||||
<span># Run them together!</span>
|
||||
nx run-many -p {title} -t build test lint
|
||||
<% } %>
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
View project details
|
||||
</summary>
|
||||
<pre>nx show project {title}</pre>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
View interactive project graph
|
||||
</summary>
|
||||
<pre>nx graph</pre>
|
||||
</details>
|
||||
<details>
|
||||
<summary>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Add UI library
|
||||
</summary>
|
||||
<pre>
|
||||
<span># Generate UI lib</span>
|
||||
nx g @nx/react:lib ui
|
||||
<span># Add a component</span>
|
||||
nx g @nx/react:component ui/src/lib/button
|
||||
</pre>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<p id="love">
|
||||
Carefully crafted with
|
||||
<svg
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default NxWelcome;
|
||||
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "<%= projectName %>",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"@react-router/node": "<%= reactRouterVersion %>",
|
||||
"@react-router/serve": "<%= reactRouterVersion %>",
|
||||
"isbot": "<%= reactRouterIsBotVersion %>",
|
||||
"react": "<%= reactVersion %>",
|
||||
"react-dom": "<%= reactVersion %>",
|
||||
"react-router": "<%= reactRouterVersion %>"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-router/dev": "<%= reactRouterVersion %>",
|
||||
"@types/node": "<%= typesNodeVersion %>",
|
||||
"@types/react": "<%= reactVersion %>",
|
||||
"@types/react-dom": "<%= reactVersion %>"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"sideEffects": false,
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
{
|
||||
"extends": "<%= offsetFromRoot %>tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
||||
"types": ["@react-router/node", "vite/client"],
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react-jsx",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"target": "ES2022",
|
||||
"strict": true,
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": [
|
||||
"app/**/*.ts",
|
||||
"app/**/*.tsx",
|
||||
"app/**/*.js",
|
||||
"app/**/*.jsx",
|
||||
"**/.server/**/*.ts",
|
||||
"**/.server/**/*.tsx",
|
||||
"**/.client/**/*.ts",
|
||||
"**/.client/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"tests/**/*.spec.ts",
|
||||
"tests/**/*.test.ts",
|
||||
"tests/**/*.spec.tsx",
|
||||
"tests/**/*.test.tsx",
|
||||
"tests/**/*.spec.js",
|
||||
"tests/**/*.test.js",
|
||||
"tests/**/*.spec.jsx",
|
||||
"tests/**/*.test.jsx"
|
||||
]
|
||||
}
|
||||
@ -59,19 +59,29 @@ export async function addE2e(
|
||||
options.devServerPort ?? 4200
|
||||
);
|
||||
} else if (options.bundler === 'vite') {
|
||||
const { getViteE2EWebServerInfo } = ensurePackage<
|
||||
typeof import('@nx/vite')
|
||||
>('@nx/vite', nxVersion);
|
||||
e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(
|
||||
options.appProjectRoot,
|
||||
`vite.config.${options.js ? 'js' : 'ts'}`
|
||||
),
|
||||
options.addPlugin,
|
||||
options.devServerPort ?? 4200
|
||||
);
|
||||
const { getViteE2EWebServerInfo, getReactRouterE2EWebServerInfo } =
|
||||
ensurePackage<typeof import('@nx/vite')>('@nx/vite', nxVersion);
|
||||
e2eWebServerInfo = options.useReactRouter
|
||||
? await getReactRouterE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(
|
||||
options.appProjectRoot,
|
||||
`vite.config.${options.js ? 'js' : 'ts'}`
|
||||
),
|
||||
options.addPlugin,
|
||||
options.devServerPort ?? 4200
|
||||
)
|
||||
: await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(
|
||||
options.appProjectRoot,
|
||||
`vite.config.${options.js ? 'js' : 'ts'}`
|
||||
),
|
||||
options.addPlugin,
|
||||
options.devServerPort ?? 4200
|
||||
);
|
||||
} else if (options.bundler === 'rsbuild') {
|
||||
ensurePackage('@nx/rsbuild', nxVersion);
|
||||
const { getRsbuildE2EWebServerInfo } = await import(
|
||||
|
||||
@ -2,6 +2,8 @@ import {
|
||||
type Tree,
|
||||
type GeneratorCallback,
|
||||
joinPathFragments,
|
||||
ensurePackage,
|
||||
readJson,
|
||||
} from '@nx/devkit';
|
||||
import { Linter, lintProjectGenerator } from '@nx/eslint';
|
||||
import {
|
||||
@ -15,6 +17,7 @@ import { addDependenciesToPackageJson, runTasksInSerial } from '@nx/devkit';
|
||||
import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies';
|
||||
import { extraEslintDependencies } from '../../../utils/lint';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import { nxVersion } from '../../../utils/versions';
|
||||
|
||||
export async function addLinting(host: Tree, options: NormalizedSchema) {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
@ -64,6 +67,54 @@ export async function addLinting(host: Tree, options: NormalizedSchema) {
|
||||
const addSwcTask = addSwcDependencies(host);
|
||||
tasks.push(installTask, addSwcTask);
|
||||
}
|
||||
if (options.useReactRouter) {
|
||||
await ignoreReactRouterFilesInEslintConfig(host, options.appProjectRoot);
|
||||
}
|
||||
}
|
||||
return runTasksInSerial(...tasks);
|
||||
}
|
||||
|
||||
async function ignoreReactRouterFilesInEslintConfig(
|
||||
tree: Tree,
|
||||
projectRoot: string | undefined
|
||||
): Promise<void> {
|
||||
if (!isEslintInstalled(tree)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ensurePackage('@nx/eslint', nxVersion);
|
||||
const { addIgnoresToLintConfig, isEslintConfigSupported } = await import(
|
||||
'@nx/eslint/src/generators/utils/eslint-file'
|
||||
);
|
||||
if (!isEslintConfigSupported(tree)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { useFlatConfig } = await import('@nx/eslint/src/utils/flat-config');
|
||||
const isUsingFlatConfig = useFlatConfig(tree);
|
||||
if (!projectRoot && !isUsingFlatConfig) {
|
||||
// root eslintrc files ignore all files and the root eslintrc files add
|
||||
// back all the project files, so we only add the ignores to the project
|
||||
// eslintrc files
|
||||
return;
|
||||
}
|
||||
|
||||
// for flat config, we update the root config file
|
||||
const directory = isUsingFlatConfig ? '' : projectRoot ?? '';
|
||||
|
||||
addIgnoresToLintConfig(tree, directory, ['**/build', '**/.react-router']);
|
||||
}
|
||||
|
||||
export function isEslintInstalled(tree: Tree): boolean {
|
||||
try {
|
||||
require('eslint');
|
||||
return true;
|
||||
} catch {}
|
||||
|
||||
// it might not be installed yet, but it might be in the tree pending install
|
||||
const { devDependencies, dependencies } = tree.exists('package.json')
|
||||
? readJson(tree, 'package.json')
|
||||
: {};
|
||||
|
||||
return !!devDependencies?.['eslint'] || !!dependencies?.['eslint'];
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
ProjectConfiguration,
|
||||
TargetConfiguration,
|
||||
Tree,
|
||||
updateJson,
|
||||
writeJson,
|
||||
} from '@nx/devkit';
|
||||
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
|
||||
@ -63,11 +64,25 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
||||
}
|
||||
|
||||
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||
writeJson(
|
||||
host,
|
||||
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||
packageJson
|
||||
);
|
||||
// React Router already adds a package.json to the project root
|
||||
if (options.useReactRouter) {
|
||||
updateJson(
|
||||
host,
|
||||
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||
(json) => {
|
||||
return {
|
||||
name: packageJson.name,
|
||||
...json,
|
||||
};
|
||||
}
|
||||
);
|
||||
} else {
|
||||
writeJson(
|
||||
host,
|
||||
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||
packageJson
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ export function addRouting(host: Tree, options: NormalizedSchema) {
|
||||
|
||||
const changes = applyChangesToString(
|
||||
appFileContent,
|
||||
addInitialRoutes(appPath, appSource)
|
||||
addInitialRoutes(appPath, appSource, options.inSourceTests)
|
||||
);
|
||||
host.write(appPath, changes);
|
||||
|
||||
|
||||
@ -18,6 +18,20 @@ export async function setupViteConfiguration(
|
||||
tree.delete(joinPathFragments(options.appProjectRoot, 'src/environments'));
|
||||
}
|
||||
|
||||
const reactRouterFrameworkConfig = {
|
||||
imports: [`import { reactRouter } from '@react-router/dev/vite'`],
|
||||
plugins: ['!process.env.VITEST && reactRouter()'],
|
||||
};
|
||||
|
||||
const baseReactConfig = {
|
||||
imports: [
|
||||
options.compiler === 'swc'
|
||||
? `import react from '@vitejs/plugin-react-swc'`
|
||||
: `import react from '@vitejs/plugin-react'`,
|
||||
],
|
||||
plugins: ['react()'],
|
||||
};
|
||||
|
||||
const viteTask = await viteConfigurationGenerator(tree, {
|
||||
uiFramework: 'react',
|
||||
project: options.projectName,
|
||||
@ -38,12 +52,9 @@ export async function setupViteConfiguration(
|
||||
includeVitest: options.unitTestRunner === 'vitest',
|
||||
inSourceTests: options.inSourceTests,
|
||||
rollupOptionsExternal: ["'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()'],
|
||||
...(options.useReactRouter
|
||||
? reactRouterFrameworkConfig
|
||||
: baseReactConfig),
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
offsetFromRoot,
|
||||
toJS,
|
||||
Tree,
|
||||
updateJson,
|
||||
writeJson,
|
||||
} from '@nx/devkit';
|
||||
import { WithNxOptions } from '@nx/webpack';
|
||||
@ -22,6 +23,15 @@ import {
|
||||
} from 'nx/src/nx-cloud/utilities/onboarding';
|
||||
import { hasRspackPlugin } from '../../../utils/has-rspack-plugin';
|
||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||
import {
|
||||
reactDomVersion,
|
||||
reactRouterIsBotVersion,
|
||||
reactRouterVersion,
|
||||
reactVersion,
|
||||
typesReactDomVersion,
|
||||
typesNodeVersion,
|
||||
typesReactVersion,
|
||||
} from '../../../utils/versions';
|
||||
|
||||
export async function createApplicationFiles(
|
||||
host: Tree,
|
||||
@ -60,6 +70,13 @@ export async function createApplicationFiles(
|
||||
const templateVariables = {
|
||||
...options.names,
|
||||
...options,
|
||||
typesNodeVersion,
|
||||
typesReactDomVersion,
|
||||
reactRouterVersion,
|
||||
typesReactVersion,
|
||||
reactDomVersion,
|
||||
reactVersion,
|
||||
reactRouterIsBotVersion,
|
||||
js: !!options.js, // Ensure this is defined in template
|
||||
tmpl: '',
|
||||
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
|
||||
@ -70,13 +87,15 @@ export async function createApplicationFiles(
|
||||
isUsingTsSolutionSetup: isUsingTsSolutionSetup(host),
|
||||
};
|
||||
|
||||
if (options.bundler === 'vite') {
|
||||
if (options.bundler === 'vite' && !options.useReactRouter) {
|
||||
generateFiles(
|
||||
host,
|
||||
join(__dirname, '../files/base-vite'),
|
||||
options.appProjectRoot,
|
||||
templateVariables
|
||||
);
|
||||
} else if (options.bundler === 'vite' && options.useReactRouter) {
|
||||
generateReactRouterFiles(host, options, templateVariables);
|
||||
} else if (options.bundler === 'webpack') {
|
||||
generateFiles(
|
||||
host,
|
||||
@ -185,9 +204,12 @@ export async function createApplicationFiles(
|
||||
? 'https://nx.dev/getting-started/tutorials/react-standalone-tutorial'
|
||||
: 'https://nx.dev/react-tutorial/1-code-generation?utm_source=nx-project';
|
||||
|
||||
const path = options.useReactRouter
|
||||
? '../files/react-router-ssr/nx-welcome'
|
||||
: '../files/nx-welcome';
|
||||
generateFiles(
|
||||
host,
|
||||
join(__dirname, '../files/nx-welcome', onBoardingStatus),
|
||||
join(__dirname, path, onBoardingStatus),
|
||||
options.appProjectRoot,
|
||||
{ ...templateVariables, connectCloudUrl, tutorialUrl }
|
||||
);
|
||||
@ -195,7 +217,11 @@ export async function createApplicationFiles(
|
||||
|
||||
generateFiles(
|
||||
host,
|
||||
join(__dirname, styleSolutionSpecificAppFiles),
|
||||
join(
|
||||
__dirname,
|
||||
styleSolutionSpecificAppFiles,
|
||||
options.useReactRouter ? 'src' : ''
|
||||
),
|
||||
options.appProjectRoot,
|
||||
templateVariables
|
||||
);
|
||||
@ -289,3 +315,55 @@ function createNxRspackPluginOptions(
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function generateReactRouterFiles(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema,
|
||||
templateVariables
|
||||
) {
|
||||
generateFiles(
|
||||
tree,
|
||||
join(__dirname, '../files/react-router-ssr/common'),
|
||||
options.appProjectRoot,
|
||||
templateVariables
|
||||
);
|
||||
|
||||
if (options.rootProject) {
|
||||
const gitignore = tree.read('.gitignore', 'utf-8');
|
||||
tree.write(
|
||||
'.gitignore',
|
||||
`${gitignore}\n.cache\nbuild\npublic/build\n.env\n\.react-router\n`
|
||||
);
|
||||
} else {
|
||||
generateFiles(
|
||||
tree,
|
||||
joinPathFragments(__dirname, '../files/react-router-ssr/non-root'),
|
||||
options.appProjectRoot,
|
||||
templateVariables
|
||||
);
|
||||
}
|
||||
|
||||
if (options.isUsingTsSolutionConfig) {
|
||||
generateFiles(
|
||||
tree,
|
||||
joinPathFragments(__dirname, '../files/react-router-ssr/ts-solution'),
|
||||
options.appProjectRoot,
|
||||
templateVariables
|
||||
);
|
||||
|
||||
updateJson(
|
||||
tree,
|
||||
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||
(json) => {
|
||||
if (options.projectName !== options.importPath) {
|
||||
json.nx = { name: options.projectName };
|
||||
}
|
||||
if (options.parsedTags?.length) {
|
||||
json.nx ??= {};
|
||||
json.nx.tags = options.parsedTags;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,8 @@ import {
|
||||
testingLibraryDomVersion,
|
||||
tsLibVersion,
|
||||
typesNodeVersion,
|
||||
typesReactDomVersion,
|
||||
typesReactVersion,
|
||||
reactRouterVersion,
|
||||
reactRouterIsBotVersion,
|
||||
} from '../../../utils/versions';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import { getReactDependenciesVersionsToInstall } from '../../../utils/version-utils';
|
||||
@ -27,15 +27,27 @@ export async function installCommonDependencies(
|
||||
|
||||
const dependencies: Record<string, string> = {};
|
||||
const devDependencies: Record<string, string> = {
|
||||
'@types/node': typesNodeVersion,
|
||||
'@types/react': reactDeps['@types/react'],
|
||||
'@types/react-dom': reactDeps['@types/react-dom'],
|
||||
'@types/node': typesNodeVersion,
|
||||
...(options.useReactRouter
|
||||
? {
|
||||
'@react-router/dev': reactRouterVersion,
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
if (options.bundler !== 'vite') {
|
||||
dependencies['tslib'] = tsLibVersion;
|
||||
}
|
||||
|
||||
if (options.useReactRouter) {
|
||||
dependencies['react-router'] = reactRouterVersion;
|
||||
dependencies['@react-router/node'] = reactRouterVersion;
|
||||
dependencies['@react-router/serve'] = reactRouterVersion;
|
||||
dependencies['isbot'] = reactRouterIsBotVersion;
|
||||
}
|
||||
|
||||
// Vite requires style preprocessors to be installed manually.
|
||||
// `@nx/webpack` installs them automatically for now.
|
||||
if (options.bundler === 'vite' || options.unitTestRunner === 'vitest') {
|
||||
@ -65,5 +77,5 @@ export async function installCommonDependencies(
|
||||
devDependencies['@testing-library/dom'] = testingLibraryDomVersion;
|
||||
}
|
||||
|
||||
return addDependenciesToPackageJson(host, {}, devDependencies);
|
||||
return addDependenciesToPackageJson(host, dependencies, devDependencies);
|
||||
}
|
||||
|
||||
@ -53,6 +53,9 @@ export async function normalizeOptions<T extends Schema = Schema>(
|
||||
|
||||
assertValidStyle(options.style);
|
||||
|
||||
options.bundler = options.useReactRouter ? 'vite' : options.bundler;
|
||||
options.useReactRouter = options.routing ? options.useReactRouter : false;
|
||||
|
||||
const normalized = {
|
||||
...options,
|
||||
projectName: appProjectName,
|
||||
@ -70,6 +73,7 @@ export async function normalizeOptions<T extends Schema = Schema>(
|
||||
} as NormalizedSchema;
|
||||
|
||||
normalized.routing = normalized.routing ?? false;
|
||||
normalized.useReactRouter = normalized.useReactRouter ?? false;
|
||||
normalized.strict = normalized.strict ?? true;
|
||||
normalized.classComponent = normalized.classComponent ?? false;
|
||||
normalized.compiler = normalized.compiler ?? 'babel';
|
||||
|
||||
@ -14,6 +14,7 @@ export interface Schema {
|
||||
linter: Linter | LinterType;
|
||||
classComponent?: boolean;
|
||||
routing?: boolean;
|
||||
useReactRouter?: boolean;
|
||||
skipNxJson?: boolean;
|
||||
js?: boolean;
|
||||
globalCss?: boolean;
|
||||
|
||||
@ -83,7 +83,12 @@
|
||||
"routing": {
|
||||
"type": "boolean",
|
||||
"description": "Generate application with routes.",
|
||||
"x-prompt": "Would you like to add React Router to this application?",
|
||||
"x-prompt": "Would you like to add routing to this application?",
|
||||
"default": false
|
||||
},
|
||||
"useReactRouter": {
|
||||
"description": "Use React Router for routing.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"skipFormat": {
|
||||
|
||||
@ -137,7 +137,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-lib',
|
||||
|
||||
@ -1000,7 +1000,7 @@ module.exports = withNx(
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './test-output/vitest/coverage',
|
||||
|
||||
@ -348,7 +348,8 @@ export function isTag(tagName: string, node: ts.Node) {
|
||||
|
||||
export function addInitialRoutes(
|
||||
sourcePath: string,
|
||||
source: ts.SourceFile
|
||||
source: ts.SourceFile,
|
||||
addBrowserRouter?: boolean
|
||||
): StringChange[] {
|
||||
if (!tsModule) {
|
||||
tsModule = ensureTypescript();
|
||||
@ -404,7 +405,9 @@ export function addInitialRoutes(
|
||||
return [
|
||||
...addImport(
|
||||
source,
|
||||
`import { Route, Routes, Link } from 'react-router-dom';`
|
||||
`import { Route, Routes, Link ${
|
||||
addBrowserRouter ? ', BrowserRouter ' : ''
|
||||
}} from 'react-router-dom';`
|
||||
),
|
||||
insertRoutes,
|
||||
];
|
||||
|
||||
@ -16,7 +16,8 @@ export const typesReactIsV18Version = '18.3.0';
|
||||
export const typesReactIsVersion = '19.0.0';
|
||||
export const reactViteVersion = '^4.2.0';
|
||||
|
||||
export const typesNodeVersion = '18.16.9';
|
||||
// Needed for React-Router
|
||||
export const typesNodeVersion = '^20.0.0';
|
||||
|
||||
export const babelPresetReactVersion = '^7.14.5';
|
||||
export const babelCoreVersion = '^7.14.5';
|
||||
@ -32,7 +33,8 @@ export const emotionBabelPlugin = '11.11.0';
|
||||
export const styledJsxVersion = '5.1.2';
|
||||
|
||||
export const reactRouterDomVersion = '6.29.0';
|
||||
export const reactRouterVersion = '7.1.5';
|
||||
export const reactRouterVersion = '^7.2.0';
|
||||
export const reactRouterIsBotVersion = '^4.4.0';
|
||||
|
||||
export const testingLibraryReactVersion = '16.1.0';
|
||||
export const testingLibraryDomVersion = '10.4.0';
|
||||
|
||||
@ -50,7 +50,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-lib',
|
||||
@ -273,7 +273,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
||||
@ -483,7 +483,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||
|
||||
@ -35,7 +35,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
setupFiles: ['src/test-setup.ts'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
@ -69,7 +69,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
@ -108,7 +108,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
||||
@ -138,7 +138,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||
|
||||
@ -41,3 +41,32 @@ export async function getViteE2EWebServerInfo(
|
||||
isPluginBeingAdded
|
||||
);
|
||||
}
|
||||
|
||||
export async function getReactRouterE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
configFilePath: string,
|
||||
isPluginBeingAdded: boolean,
|
||||
e2ePortOverride?: number
|
||||
) {
|
||||
const e2ePort = e2ePortOverride ?? parseInt(process.env.PORT) ?? 4200;
|
||||
|
||||
return await getE2EWebServerInfo(
|
||||
tree,
|
||||
projectName,
|
||||
{
|
||||
plugin: '@nx/react/router-plugin',
|
||||
serveTargetName: 'devTargetName',
|
||||
serveStaticTargetName: 'devTargetName',
|
||||
configFilePath,
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'dev',
|
||||
defaultServeStaticTargetName: 'dev',
|
||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
||||
defaultE2EPort: e2ePort,
|
||||
},
|
||||
isPluginBeingAdded
|
||||
);
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ describe('generator utils', () => {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
|
||||
@ -471,7 +471,7 @@ export function createOrEditViteConfig(
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: '${options.testEnvironment ?? 'jsdom'}',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
${options.setupFile ? ` setupFiles: ['${options.setupFile}'],\n` : ''}\
|
||||
${
|
||||
options.inSourceTests
|
||||
|
||||
@ -74,7 +74,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/test',
|
||||
@ -284,7 +284,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/test',
|
||||
|
||||
@ -225,7 +225,7 @@ describe('application generator', () => {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './test-output/vitest/coverage',
|
||||
|
||||
@ -52,7 +52,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-lib',
|
||||
@ -143,7 +143,7 @@ export default defineConfig(() => ({
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/my-lib',
|
||||
|
||||
@ -1352,168 +1352,6 @@ And join the Nx community:
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (github) should be created for RemixMonorepo preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
|
||||
|
||||
✨ Your new, shiny [Nx workspace](https://nx.dev) is almost ready ✨.
|
||||
|
||||
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
||||
|
||||
## Finish your CI setup
|
||||
|
||||
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
||||
|
||||
## Run tasks
|
||||
|
||||
To run tasks with Nx use:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx <target> <project-name>
|
||||
\`\`\`
|
||||
|
||||
For example:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx build myproject
|
||||
\`\`\`
|
||||
|
||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||
|
||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Add new projects
|
||||
|
||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||
|
||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx add @nx/react
|
||||
\`\`\`
|
||||
|
||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
||||
|
||||
\`\`\`sh
|
||||
# Generate an app
|
||||
npx nx g @nx/react:app demo
|
||||
|
||||
# Generate a library
|
||||
npx nx g @nx/react:lib some-lib
|
||||
\`\`\`
|
||||
|
||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
||||
|
||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Install Nx Console
|
||||
|
||||
Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
|
||||
|
||||
[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Useful links
|
||||
|
||||
Learn more:
|
||||
|
||||
- [Learn more about this workspace setup](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
And join the Nx community:
|
||||
|
||||
- [Discord](https://go.nx.dev/community)
|
||||
- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
|
||||
- [Our Youtube channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (github) should be created for RemixStandalone preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
|
||||
|
||||
✨ Your new, shiny [Nx workspace](https://nx.dev) is almost ready ✨.
|
||||
|
||||
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
||||
|
||||
## Finish your CI setup
|
||||
|
||||
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
||||
|
||||
## Run tasks
|
||||
|
||||
To run tasks with Nx use:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx <target> <project-name>
|
||||
\`\`\`
|
||||
|
||||
For example:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx build myproject
|
||||
\`\`\`
|
||||
|
||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||
|
||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Add new projects
|
||||
|
||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||
|
||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx add @nx/react
|
||||
\`\`\`
|
||||
|
||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
||||
|
||||
\`\`\`sh
|
||||
# Generate an app
|
||||
npx nx g @nx/react:app demo
|
||||
|
||||
# Generate a library
|
||||
npx nx g @nx/react:lib some-lib
|
||||
\`\`\`
|
||||
|
||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
||||
|
||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Install Nx Console
|
||||
|
||||
Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
|
||||
|
||||
[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Useful links
|
||||
|
||||
Learn more:
|
||||
|
||||
- [Learn more about this workspace setup](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
And join the Nx community:
|
||||
|
||||
- [Discord](https://go.nx.dev/community)
|
||||
- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
|
||||
- [Our Youtube channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (github) should be created for TS preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
@ -3601,210 +3439,6 @@ And join the Nx community:
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (skip) should be created for RemixMonorepo preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
|
||||
|
||||
✨ Your new, shiny [Nx workspace](https://nx.dev) is ready ✨.
|
||||
|
||||
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
||||
|
||||
## Run tasks
|
||||
|
||||
To run tasks with Nx use:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx <target> <project-name>
|
||||
\`\`\`
|
||||
|
||||
For example:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx build myproject
|
||||
\`\`\`
|
||||
|
||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||
|
||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Add new projects
|
||||
|
||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||
|
||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx add @nx/react
|
||||
\`\`\`
|
||||
|
||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
||||
|
||||
\`\`\`sh
|
||||
# Generate an app
|
||||
npx nx g @nx/react:app demo
|
||||
|
||||
# Generate a library
|
||||
npx nx g @nx/react:lib some-lib
|
||||
\`\`\`
|
||||
|
||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
||||
|
||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Set up CI!
|
||||
|
||||
### Step 1
|
||||
|
||||
To connect to Nx Cloud, run the following command:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx connect
|
||||
\`\`\`
|
||||
|
||||
Connecting to Nx Cloud ensures a [fast and scalable CI](https://nx.dev/ci/intro/why-nx-cloud?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) pipeline. It includes features such as:
|
||||
|
||||
- [Remote caching](https://nx.dev/ci/features/remote-cache?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Task distribution across multiple machines](https://nx.dev/ci/features/distribute-task-execution?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Automated e2e test splitting](https://nx.dev/ci/features/split-e2e-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Task flakiness detection and rerunning](https://nx.dev/ci/features/flaky-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
### Step 2
|
||||
|
||||
Use the following command to configure a CI workflow for your workspace:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx g ci-workflow
|
||||
\`\`\`
|
||||
|
||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Install Nx Console
|
||||
|
||||
Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
|
||||
|
||||
[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Useful links
|
||||
|
||||
Learn more:
|
||||
|
||||
- [Learn more about this workspace setup](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
And join the Nx community:
|
||||
|
||||
- [Discord](https://go.nx.dev/community)
|
||||
- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
|
||||
- [Our Youtube channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (skip) should be created for RemixStandalone preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
|
||||
|
||||
✨ Your new, shiny [Nx workspace](https://nx.dev) is ready ✨.
|
||||
|
||||
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
||||
|
||||
## Run tasks
|
||||
|
||||
To run tasks with Nx use:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx <target> <project-name>
|
||||
\`\`\`
|
||||
|
||||
For example:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx build myproject
|
||||
\`\`\`
|
||||
|
||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||
|
||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Add new projects
|
||||
|
||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||
|
||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx add @nx/react
|
||||
\`\`\`
|
||||
|
||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
||||
|
||||
\`\`\`sh
|
||||
# Generate an app
|
||||
npx nx g @nx/react:app demo
|
||||
|
||||
# Generate a library
|
||||
npx nx g @nx/react:lib some-lib
|
||||
\`\`\`
|
||||
|
||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
||||
|
||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Set up CI!
|
||||
|
||||
### Step 1
|
||||
|
||||
To connect to Nx Cloud, run the following command:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx connect
|
||||
\`\`\`
|
||||
|
||||
Connecting to Nx Cloud ensures a [fast and scalable CI](https://nx.dev/ci/intro/why-nx-cloud?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) pipeline. It includes features such as:
|
||||
|
||||
- [Remote caching](https://nx.dev/ci/features/remote-cache?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Task distribution across multiple machines](https://nx.dev/ci/features/distribute-task-execution?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Automated e2e test splitting](https://nx.dev/ci/features/split-e2e-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Task flakiness detection and rerunning](https://nx.dev/ci/features/flaky-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
### Step 2
|
||||
|
||||
Use the following command to configure a CI workflow for your workspace:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx g ci-workflow
|
||||
\`\`\`
|
||||
|
||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Install Nx Console
|
||||
|
||||
Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
|
||||
|
||||
[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Useful links
|
||||
|
||||
Learn more:
|
||||
|
||||
- [Learn more about this workspace setup](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
And join the Nx community:
|
||||
|
||||
- [Discord](https://go.nx.dev/community)
|
||||
- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
|
||||
- [Our Youtube channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (skip) should be created for TS preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
@ -5661,168 +5295,6 @@ And join the Nx community:
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (yes) should be created for RemixMonorepo preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
|
||||
|
||||
✨ Your new, shiny [Nx workspace](https://nx.dev) is almost ready ✨.
|
||||
|
||||
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
||||
|
||||
## Finish your remote caching setup
|
||||
|
||||
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
||||
|
||||
## Run tasks
|
||||
|
||||
To run tasks with Nx use:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx <target> <project-name>
|
||||
\`\`\`
|
||||
|
||||
For example:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx build myproject
|
||||
\`\`\`
|
||||
|
||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||
|
||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Add new projects
|
||||
|
||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||
|
||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx add @nx/react
|
||||
\`\`\`
|
||||
|
||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
||||
|
||||
\`\`\`sh
|
||||
# Generate an app
|
||||
npx nx g @nx/react:app demo
|
||||
|
||||
# Generate a library
|
||||
npx nx g @nx/react:lib some-lib
|
||||
\`\`\`
|
||||
|
||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
||||
|
||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Install Nx Console
|
||||
|
||||
Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
|
||||
|
||||
[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Useful links
|
||||
|
||||
Learn more:
|
||||
|
||||
- [Learn more about this workspace setup](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
And join the Nx community:
|
||||
|
||||
- [Discord](https://go.nx.dev/community)
|
||||
- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
|
||||
- [Our Youtube channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (yes) should be created for RemixStandalone preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
|
||||
|
||||
✨ Your new, shiny [Nx workspace](https://nx.dev) is almost ready ✨.
|
||||
|
||||
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
||||
|
||||
## Finish your remote caching setup
|
||||
|
||||
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
||||
|
||||
## Run tasks
|
||||
|
||||
To run tasks with Nx use:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx <target> <project-name>
|
||||
\`\`\`
|
||||
|
||||
For example:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx build myproject
|
||||
\`\`\`
|
||||
|
||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||
|
||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Add new projects
|
||||
|
||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||
|
||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
||||
|
||||
\`\`\`sh
|
||||
npx nx add @nx/react
|
||||
\`\`\`
|
||||
|
||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
||||
|
||||
\`\`\`sh
|
||||
# Generate an app
|
||||
npx nx g @nx/react:app demo
|
||||
|
||||
# Generate a library
|
||||
npx nx g @nx/react:lib some-lib
|
||||
\`\`\`
|
||||
|
||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
||||
|
||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Install Nx Console
|
||||
|
||||
Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
|
||||
|
||||
[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
## Useful links
|
||||
|
||||
Learn more:
|
||||
|
||||
- [Learn more about this workspace setup](https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
|
||||
And join the Nx community:
|
||||
|
||||
- [Discord](https://go.nx.dev/community)
|
||||
- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
|
||||
- [Our Youtube channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (yes) should be created for TS preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
|
||||
@ -88,6 +88,9 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
|
||||
: null,
|
||||
parsedArgs.interactive ? '--interactive=true' : '--interactive=false',
|
||||
opts.routing !== undefined ? `--routing=${opts.routing}` : null,
|
||||
opts.useReactRouter !== undefined
|
||||
? `--useReactRouter=${opts.useReactRouter}`
|
||||
: null,
|
||||
opts.unitTestRunner !== undefined
|
||||
? `--unitTestRunner=${opts.unitTestRunner}`
|
||||
: null,
|
||||
@ -141,10 +144,6 @@ function getPresetDependencies({
|
||||
case Preset.NextJsStandalone:
|
||||
return { dependencies: { '@nx/next': nxVersion }, dev: {} };
|
||||
|
||||
case Preset.RemixStandalone:
|
||||
case Preset.RemixMonorepo:
|
||||
return { dependencies: { '@nx/remix': nxVersion }, dev: {} };
|
||||
|
||||
case Preset.VueMonorepo:
|
||||
case Preset.VueStandalone:
|
||||
return {
|
||||
|
||||
@ -76,18 +76,6 @@ const presetToPluginMap: { [key in Preset]: PresetInfo } = {
|
||||
learnMoreLink:
|
||||
'https://nx.dev/nx-api/next?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects',
|
||||
},
|
||||
[Preset.RemixMonorepo]: {
|
||||
generateAppCmd: '@nx/remix',
|
||||
generateLibCmd: '@nx/react',
|
||||
learnMoreLink:
|
||||
'https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects',
|
||||
},
|
||||
[Preset.RemixStandalone]: {
|
||||
generateAppCmd: '@nx/remix',
|
||||
generateLibCmd: '@nx/react',
|
||||
learnMoreLink:
|
||||
'https://nx.dev/nx-api/remix?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects',
|
||||
},
|
||||
[Preset.ReactNative]: {
|
||||
generateAppCmd: '@nx/react-native',
|
||||
generateLibCmd: '@nx/react',
|
||||
@ -271,7 +259,6 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
options.preset === Preset.NuxtStandalone ||
|
||||
options.preset === Preset.NodeStandalone ||
|
||||
options.preset === Preset.NextJsStandalone ||
|
||||
options.preset === Preset.RemixStandalone ||
|
||||
options.preset === Preset.TsStandalone
|
||||
? './files-root-app'
|
||||
: (options.preset === Preset.TS &&
|
||||
@ -420,7 +407,6 @@ function setUpWorkspacesInPackageJson(tree: Tree, options: NormalizedSchema) {
|
||||
options.preset === Preset.NextJs ||
|
||||
options.preset === Preset.ReactMonorepo ||
|
||||
options.preset === Preset.ReactNative ||
|
||||
options.preset === Preset.RemixMonorepo ||
|
||||
options.preset === Preset.VueMonorepo ||
|
||||
options.preset === Preset.Nuxt ||
|
||||
options.preset === Preset.NodeMonorepo ||
|
||||
|
||||
@ -31,6 +31,7 @@ interface Schema {
|
||||
bundler?: 'vite' | 'webpack';
|
||||
standaloneApi?: boolean;
|
||||
routing?: boolean;
|
||||
useReactRouter?: boolean;
|
||||
packageManager?: PackageManager;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
e2eTestRunner?: 'cypress' | 'playwright' | 'detox' | 'jest' | 'none';
|
||||
|
||||
@ -25,6 +25,11 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"useReactRouter": {
|
||||
"description": "Use React Router for routing.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"standaloneApi": {
|
||||
"description": "Use Standalone Components if generating an Angular application.",
|
||||
"type": "boolean",
|
||||
|
||||
@ -158,7 +158,7 @@ describe('preset', () => {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/apps/vue-preset-monorepo',
|
||||
@ -311,7 +311,7 @@ describe('preset', () => {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './coverage/react-standalone-preset-vite',
|
||||
@ -367,7 +367,7 @@ describe('preset', () => {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './coverage/vue-standalone-preset',
|
||||
|
||||
@ -77,6 +77,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
options.unitTestRunner ??
|
||||
(options.bundler === 'vite' ? 'vitest' : 'jest'),
|
||||
addPlugin,
|
||||
routing: options.routing,
|
||||
useReactRouter: options.useReactRouter,
|
||||
nxCloudToken: options.nxCloudToken,
|
||||
useTsSolution: options.workspaces,
|
||||
formatter: options.formatter,
|
||||
@ -95,6 +97,8 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
linter: options.linter,
|
||||
rootProject: true,
|
||||
bundler,
|
||||
routing: options.routing,
|
||||
useReactRouter: options.useReactRouter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'playwright',
|
||||
unitTestRunner:
|
||||
options.unitTestRunner ?? (bundler === 'vite' ? 'vitest' : 'jest'),
|
||||
@ -102,37 +106,6 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
nxCloudToken: options.nxCloudToken,
|
||||
formatter: options.formatter,
|
||||
});
|
||||
} else if (options.preset === Preset.RemixMonorepo) {
|
||||
const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
|
||||
'/remix/generators');
|
||||
|
||||
return remixApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'playwright',
|
||||
unitTestRunner: options.unitTestRunner ?? 'vitest',
|
||||
addPlugin,
|
||||
nxCloudToken: options.nxCloudToken,
|
||||
useTsSolution: options.workspaces,
|
||||
formatter: options.formatter,
|
||||
useProjectJson: !options.workspaces,
|
||||
});
|
||||
} else if (options.preset === Preset.RemixStandalone) {
|
||||
const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
|
||||
'/remix/generators');
|
||||
|
||||
return remixApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: '.',
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'playwright',
|
||||
rootProject: true,
|
||||
unitTestRunner: options.unitTestRunner ?? 'vitest',
|
||||
addPlugin,
|
||||
nxCloudToken: options.nxCloudToken,
|
||||
formatter: options.formatter,
|
||||
});
|
||||
} else if (options.preset === Preset.VueMonorepo) {
|
||||
const { applicationGenerator: vueApplicationGenerator } = require('@nx' +
|
||||
'/vue');
|
||||
|
||||
@ -16,6 +16,7 @@ export interface Schema {
|
||||
nextAppDir?: boolean;
|
||||
nextSrcDir?: boolean;
|
||||
routing?: boolean;
|
||||
useReactRouter?: boolean;
|
||||
standaloneApi?: boolean;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
e2eTestRunner?: 'cypress' | 'playwright' | 'jest' | 'detox' | 'none';
|
||||
|
||||
@ -25,6 +25,11 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"useReactRouter": {
|
||||
"description": "Use React Router for routing.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"style": {
|
||||
"description": "The file extension to be used for style files.",
|
||||
"type": "string",
|
||||
|
||||
@ -8,8 +8,6 @@ export enum Preset {
|
||||
ReactMonorepo = 'react-monorepo',
|
||||
ReactStandalone = 'react-standalone',
|
||||
NextJsStandalone = 'nextjs-standalone',
|
||||
RemixMonorepo = 'remix-monorepo',
|
||||
RemixStandalone = 'remix-standalone',
|
||||
ReactNative = 'react-native',
|
||||
VueMonorepo = 'vue-monorepo',
|
||||
VueStandalone = 'vue-standalone',
|
||||
|
||||
@ -95,8 +95,6 @@ function generatePresetsMarkdown(): string {
|
||||
[Preset.NuxtStandalone]: 'A single Nuxt application',
|
||||
[Preset.NextJs]: 'A Next monorepo',
|
||||
[Preset.NextJsStandalone]: 'A single Next application',
|
||||
[Preset.RemixMonorepo]: 'A Remix monorepo',
|
||||
[Preset.RemixStandalone]: 'A single Remix application',
|
||||
[Preset.ReactNative]: 'A monorepo with a React Native application',
|
||||
[Preset.Expo]: 'A monorepo with an Expo application',
|
||||
[Preset.Nest]: 'A monorepo with a Nest application',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user