feat(remix): add option to create-nx-workspace (#22334)
This commit is contained in:
parent
7390031b7e
commit
d7cb6875f9
@ -145,7 +145,7 @@ Prefix to use for Angular component and directive selectors.
|
||||
|
||||
Type: `string`
|
||||
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "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
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "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
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ Prefix to use for Angular component and directive selectors.
|
||||
|
||||
Type: `string`
|
||||
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "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
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "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
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ interface ReactArguments extends BaseArguments {
|
||||
stack: 'react';
|
||||
workspaceType: 'standalone' | 'integrated';
|
||||
appName: string;
|
||||
framework: 'none' | 'next';
|
||||
framework: 'none' | 'next' | 'remix';
|
||||
style: string;
|
||||
bundler: 'webpack' | 'vite' | 'rspack';
|
||||
nextAppDir: boolean;
|
||||
@ -378,6 +378,8 @@ async function determineStack(
|
||||
case Preset.ReactMonorepo:
|
||||
case Preset.NextJs:
|
||||
case Preset.NextJsStandalone:
|
||||
case Preset.RemixStandalone:
|
||||
case Preset.RemixMonorepo:
|
||||
return 'react';
|
||||
case Preset.Vue:
|
||||
case Preset.VueStandalone:
|
||||
@ -520,7 +522,8 @@ async function determineReactOptions(
|
||||
preset = parsedArgs.preset;
|
||||
if (
|
||||
preset === Preset.ReactStandalone ||
|
||||
preset === Preset.NextJsStandalone
|
||||
preset === Preset.NextJsStandalone ||
|
||||
preset === Preset.RemixStandalone
|
||||
) {
|
||||
appName = parsedArgs.appName ?? parsedArgs.name;
|
||||
} else {
|
||||
@ -548,6 +551,12 @@ async function determineReactOptions(
|
||||
} else {
|
||||
preset = Preset.NextJs;
|
||||
}
|
||||
} else if (framework === 'remix') {
|
||||
if (workspaceType === 'standalone') {
|
||||
preset = Preset.RemixStandalone;
|
||||
} else {
|
||||
preset = Preset.RemixMonorepo;
|
||||
}
|
||||
} else if (framework === 'react-native') {
|
||||
preset = Preset.ReactNative;
|
||||
} else if (framework === 'expo') {
|
||||
@ -568,6 +577,11 @@ async function determineReactOptions(
|
||||
nextAppDir = await determineNextAppDir(parsedArgs);
|
||||
nextSrcDir = await determineNextSrcDir(parsedArgs);
|
||||
e2eTestRunner = await determineE2eTestRunner(parsedArgs);
|
||||
} else if (
|
||||
preset === Preset.RemixMonorepo ||
|
||||
preset === Preset.RemixStandalone
|
||||
) {
|
||||
e2eTestRunner = await determineE2eTestRunner(parsedArgs);
|
||||
}
|
||||
|
||||
if (parsedArgs.style) {
|
||||
@ -1017,9 +1031,9 @@ async function determineAppName(
|
||||
|
||||
async function determineReactFramework(
|
||||
parsedArgs: yargs.Arguments<ReactArguments>
|
||||
): Promise<'none' | 'nextjs' | 'expo' | 'react-native'> {
|
||||
): Promise<'none' | 'nextjs' | 'remix' | 'expo' | 'react-native'> {
|
||||
const reply = await enquirer.prompt<{
|
||||
framework: 'none' | 'nextjs' | 'expo' | 'react-native';
|
||||
framework: 'none' | 'nextjs' | 'remix' | 'expo' | 'react-native';
|
||||
}>([
|
||||
{
|
||||
name: 'framework',
|
||||
@ -1035,6 +1049,10 @@ async function determineReactFramework(
|
||||
name: 'nextjs',
|
||||
message: 'Next.js [ https://nextjs.org/ ]',
|
||||
},
|
||||
{
|
||||
name: 'remix',
|
||||
message: 'Remix [ https://remix.run/ ]',
|
||||
},
|
||||
{
|
||||
name: 'expo',
|
||||
message: 'Expo [ https://expo.io/ ]',
|
||||
|
||||
@ -15,6 +15,8 @@ export enum Preset {
|
||||
NuxtStandalone = 'nuxt-standalone',
|
||||
NextJs = 'next',
|
||||
NextJsStandalone = 'nextjs-standalone',
|
||||
RemixMonorepo = 'remix-monorepo',
|
||||
RemixStandalone = 'remix-standalone',
|
||||
ReactNative = 'react-native',
|
||||
Expo = 'expo',
|
||||
Nest = 'nest',
|
||||
|
||||
@ -1147,8 +1147,7 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: './coverage/test',
|
||||
testMatch: [
|
||||
'<rootDir>/src/**/__tests__/**/*.[jt]s?(x)',
|
||||
'<rootDir>/src/**/*(*.)@(spec|test).[jt]s?(x)',
|
||||
'<rootDir>/tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}',
|
||||
],
|
||||
};
|
||||
"
|
||||
|
||||
@ -35,6 +35,7 @@ import initGenerator from '../init/init';
|
||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/add-build-target-defaults';
|
||||
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
||||
import { updateJestTestMatch } from '../../utils/testing-config-utils';
|
||||
|
||||
export function remixApplicationGenerator(
|
||||
tree: Tree,
|
||||
@ -267,6 +268,28 @@ export async function remixApplicationGeneratorInternal(
|
||||
extractTsConfigBase(tree);
|
||||
}
|
||||
|
||||
if (options.rootProject) {
|
||||
updateJson(tree, `package.json`, (json) => {
|
||||
json.type = 'module';
|
||||
return json;
|
||||
});
|
||||
|
||||
if (options.unitTestRunner === 'jest') {
|
||||
tree.write(
|
||||
'jest.preset.js',
|
||||
`import { nxPreset } from '@nx/jest/preset/jest-preset.js';
|
||||
export default {...nxPreset};
|
||||
`
|
||||
);
|
||||
|
||||
updateJestTestMatch(
|
||||
tree,
|
||||
'jest.config.ts',
|
||||
'<rootDir>/tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
tasks.push(await addE2E(tree, options));
|
||||
|
||||
if (!options.skipFormat) {
|
||||
|
||||
@ -100,6 +100,33 @@ export function updateJestTestSetup(
|
||||
}
|
||||
}
|
||||
|
||||
export function updateJestTestMatch(
|
||||
tree: Tree,
|
||||
pathToJestConfig: string,
|
||||
includesString: string
|
||||
) {
|
||||
if (!tsModule) {
|
||||
tsModule = ensureTypescript();
|
||||
}
|
||||
const { tsquery } = require('@phenomnomnominal/tsquery');
|
||||
const fileContents = tree.read(pathToJestConfig, 'utf-8');
|
||||
|
||||
const ast = tsquery.ast(fileContents);
|
||||
|
||||
const TEST_MATCH_SELECTOR =
|
||||
'PropertyAssignment:has(Identifier[name=testMatch])';
|
||||
const nodes = tsquery(ast, TEST_MATCH_SELECTOR, { visitAllChildren: true });
|
||||
|
||||
if (nodes.length !== 0) {
|
||||
const updatedFileContents = stripIndents`${fileContents.slice(
|
||||
0,
|
||||
nodes[0].getStart()
|
||||
)}testMatch: ["${includesString}"]${fileContents.slice(nodes[0].getEnd())}`;
|
||||
|
||||
tree.write(pathToJestConfig, updatedFileContents);
|
||||
}
|
||||
}
|
||||
|
||||
export function updateVitestTestIncludes(
|
||||
tree: Tree,
|
||||
pathToVitestConfig: string,
|
||||
|
||||
@ -1286,6 +1286,166 @@ It will show tasks that you can run with Nx.
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md 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>
|
||||
|
||||
✨ **This workspace has been generated by [Nx, Smart Monorepos · Fast CI.](https://nx.dev)** ✨
|
||||
|
||||
## Integrate with editors
|
||||
|
||||
Enhance your Nx experience by installing [Nx Console](https://nx.dev/nx-console) for your favorite editor. Nx Console
|
||||
provides an interactive UI to view your projects, run tasks, generate code, and more! Available for VSCode, IntelliJ and
|
||||
comes with a LSP for Vim users.
|
||||
|
||||
## Nx plugins and code generators
|
||||
|
||||
Add Nx plugins to leverage their code generators and automated, inferred tasks.
|
||||
|
||||
\`\`\`
|
||||
# Add plugin
|
||||
npx nx add @nx/react
|
||||
|
||||
# Use code generator
|
||||
npx nx generate @nx/react:app demo
|
||||
|
||||
# Run development server
|
||||
npx nx serve demo
|
||||
|
||||
# View project details
|
||||
npx nx show project demo --web
|
||||
\`\`\`
|
||||
|
||||
Run \`npx nx list\` to get a list of available plugins and whether they have generators. Then run \`npx nx list <plugin-name>\` to see what generators are available.
|
||||
|
||||
Learn more about [code generators](https://nx.dev/features/generate-code) and [inferred tasks](https://nx.dev/concepts/inferred-tasks) in the docs.
|
||||
|
||||
## Running tasks
|
||||
|
||||
To execute tasks with Nx use the following syntax:
|
||||
|
||||
\`\`\`
|
||||
npx nx <target> <project> <...options>
|
||||
\`\`\`
|
||||
|
||||
You can also run multiple targets:
|
||||
|
||||
\`\`\`
|
||||
npx nx run-many -t <target1> <target2>
|
||||
\`\`\`
|
||||
|
||||
..or add \`-p\` to filter specific projects
|
||||
|
||||
\`\`\`
|
||||
npx nx run-many -t <target1> <target2> -p <proj1> <proj2>
|
||||
\`\`\`
|
||||
|
||||
Targets can be defined in the \`package.json\` or \`projects.json\`. Learn more [in the docs](https://nx.dev/features/run-tasks).
|
||||
|
||||
## Set up CI!
|
||||
|
||||
Nx comes with local caching already built-in (check your \`nx.json\`). On CI you might want to go a step further.
|
||||
|
||||
- [Set up remote caching](https://nx.dev/features/share-your-cache)
|
||||
- [Set up task distribution across multiple machines](https://nx.dev/nx-cloud/features/distribute-task-execution)
|
||||
- [Learn more how to setup CI](https://nx.dev/recipes/ci)
|
||||
|
||||
## Explore the project graph
|
||||
|
||||
Run \`npx nx graph\` to show the graph of the workspace.
|
||||
It will show tasks that you can run with Nx.
|
||||
|
||||
- [Learn more about Exploring the Project Graph](https://nx.dev/core-features/explore-graph)
|
||||
|
||||
## Connect with us!
|
||||
|
||||
- [Join the community](https://nx.dev/community)
|
||||
- [Subscribe to the Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Follow us on Twitter](https://twitter.com/nxdevtools)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md 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>
|
||||
|
||||
✨ **This workspace has been generated by [Nx, Smart Monorepos · Fast CI.](https://nx.dev)** ✨
|
||||
|
||||
## Integrate with editors
|
||||
|
||||
Enhance your Nx experience by installing [Nx Console](https://nx.dev/nx-console) for your favorite editor. Nx Console
|
||||
provides an interactive UI to view your projects, run tasks, generate code, and more! Available for VSCode, IntelliJ and
|
||||
comes with a LSP for Vim users.
|
||||
|
||||
## Nx plugins and code generators
|
||||
|
||||
Add Nx plugins to leverage their code generators and automated, inferred tasks.
|
||||
|
||||
\`\`\`
|
||||
# Add plugin
|
||||
npx nx add @nx/react
|
||||
|
||||
# Use code generator
|
||||
npx nx generate @nx/react:app demo
|
||||
|
||||
# Run development server
|
||||
npx nx serve demo
|
||||
|
||||
# View project details
|
||||
npx nx show project demo --web
|
||||
\`\`\`
|
||||
|
||||
Run \`npx nx list\` to get a list of available plugins and whether they have generators. Then run \`npx nx list <plugin-name>\` to see what generators are available.
|
||||
|
||||
Learn more about [code generators](https://nx.dev/features/generate-code) and [inferred tasks](https://nx.dev/concepts/inferred-tasks) in the docs.
|
||||
|
||||
## Running tasks
|
||||
|
||||
To execute tasks with Nx use the following syntax:
|
||||
|
||||
\`\`\`
|
||||
npx nx <target> <project> <...options>
|
||||
\`\`\`
|
||||
|
||||
You can also run multiple targets:
|
||||
|
||||
\`\`\`
|
||||
npx nx run-many -t <target1> <target2>
|
||||
\`\`\`
|
||||
|
||||
..or add \`-p\` to filter specific projects
|
||||
|
||||
\`\`\`
|
||||
npx nx run-many -t <target1> <target2> -p <proj1> <proj2>
|
||||
\`\`\`
|
||||
|
||||
Targets can be defined in the \`package.json\` or \`projects.json\`. Learn more [in the docs](https://nx.dev/features/run-tasks).
|
||||
|
||||
## Set up CI!
|
||||
|
||||
Nx comes with local caching already built-in (check your \`nx.json\`). On CI you might want to go a step further.
|
||||
|
||||
- [Set up remote caching](https://nx.dev/features/share-your-cache)
|
||||
- [Set up task distribution across multiple machines](https://nx.dev/nx-cloud/features/distribute-task-execution)
|
||||
- [Learn more how to setup CI](https://nx.dev/recipes/ci)
|
||||
|
||||
## Explore the project graph
|
||||
|
||||
Run \`npx nx graph\` to show the graph of the workspace.
|
||||
It will show tasks that you can run with Nx.
|
||||
|
||||
- [Learn more about Exploring the Project Graph](https://nx.dev/core-features/explore-graph)
|
||||
|
||||
## Connect with us!
|
||||
|
||||
- [Join the community](https://nx.dev/community)
|
||||
- [Subscribe to the Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||
- [Follow us on Twitter](https://twitter.com/nxdevtools)
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`@nx/workspace:generateWorkspaceFiles README.md should be created for TS preset 1`] = `
|
||||
"# Proj
|
||||
|
||||
|
||||
@ -122,6 +122,10 @@ 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 {
|
||||
|
||||
@ -107,6 +107,7 @@ 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.NPM
|
||||
|
||||
@ -21,9 +21,6 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||
nxJson.useInferencePlugins !== false;
|
||||
|
||||
console.log('Add plugin', addPlugin);
|
||||
console.log(options.preset, Preset.ReactNative);
|
||||
|
||||
if (options.preset === Preset.Apps) {
|
||||
return;
|
||||
} else if (options.preset === Preset.AngularMonorepo) {
|
||||
@ -93,6 +90,33 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
unitTestRunner: options.bundler === 'vite' ? 'vitest' : 'jest',
|
||||
addPlugin,
|
||||
});
|
||||
} else if (options.preset === Preset.RemixMonorepo) {
|
||||
const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
|
||||
'/remix/generators');
|
||||
|
||||
return remixApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: join('apps', options.name),
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'cypress',
|
||||
unitTestRunner: 'vitest',
|
||||
addPlugin,
|
||||
});
|
||||
} else if (options.preset === Preset.RemixStandalone) {
|
||||
const { applicationGenerator: remixApplicationGenerator } = require('@nx' +
|
||||
'/remix/generators');
|
||||
|
||||
return remixApplicationGenerator(tree, {
|
||||
name: options.name,
|
||||
directory: '.',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
linter: options.linter,
|
||||
e2eTestRunner: options.e2eTestRunner ?? 'cypress',
|
||||
rootProject: true,
|
||||
unitTestRunner: 'vitest',
|
||||
addPlugin,
|
||||
});
|
||||
} else if (options.preset === Preset.VueMonorepo) {
|
||||
const { applicationGenerator: vueApplicationGenerator } = require('@nx' +
|
||||
'/vue');
|
||||
|
||||
@ -15,6 +15,8 @@ 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',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user