Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix(rspack): should be inferred by default #29736

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion e2e/react/src/react.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
listFiles,
newProject,
readFile,
readJson,
runCLI,
runCLIAsync,
runE2ETests,
Expand Down
284 changes: 281 additions & 3 deletions e2e/rspack/tests/rspack.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import {
updateFile,
runCLI,
runCommand,
createFile,
readJson,
} from '@nx/e2e/utils';
import { execSync } from 'child_process';

import { writeFileSync } from 'fs';
import { join } from 'path';

Expand All @@ -24,12 +26,28 @@ describe('rspack e2e', () => {
// on a unique project in the workspace, such that they
// are not dependant on one another.
beforeAll(() => {
proj = newProject({ packages: ['@nx/rspack'] });
proj = newProject({ packages: ['@nx/rspack', '@nx/react'] });
});

afterAll(() => cleanupProject());

it('should create rspack root project and additional apps', async () => {
it('should be inferred (crystal) by default', async () => {
const appName = uniq('app');

runCLI(
`generate @nx/react:application --directory=apps/${appName} --bundler=rspack --e2eTestRunner=none`
);

const nxJSON = readJson('nx.json');
const rspackPlugin = nxJSON.plugins.find(
(plugin) => plugin.plugin === '@nx/rspack/plugin'
);

expect(rspackPlugin).toBeDefined();
});

// This is disabled as the generator is no longer relevant
xit('should create rspack root project and additional apps', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of just skipping this test, can we actually remove it?

const project = uniq('myapp');
runCLI(
`generate @nx/rspack:preset ${project} --framework=react --unitTestRunner=jest --e2eTestRunner=cypress --verbose`
Expand Down Expand Up @@ -146,4 +164,264 @@ describe('rspack e2e', () => {
// Make sure expected files are present.
expect(listFiles(`dist/${app3}`)).toHaveLength(4);
}, 200_000);

describe('config types', () => {
it('should support a standard config object', () => {
const appName = uniq('app');

runCLI(
`generate @nx/react:application --directory=apps/${appName} --bundler=rspack --e2eTestRunner=none`
);

updateFile(
`apps/${appName}/rspack.config.js`,
`
const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
const { join } = require('path');

module.exports = {
output: {
path: join(__dirname, '../../dist/${appName}'),
},
devServer: {
port: 4200,
historyApiFallback: {
index: '/index.html',
disableDotRule: true,
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
},
},
plugins: [
new NxAppRspackPlugin({
tsConfig: './tsconfig.app.json',
main: './src/main.tsx',
index: './src/index.html',
baseHref: '/',
assets: ['./src/favicon.ico', './src/assets'],
styles: ['./src/styles.scss'],
outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
optimization: process.env['NODE_ENV'] === 'production',
}),
new NxReactRspackPlugin({
// Uncomment this line if you don't want to use SVGR
// See: https://react-svgr.com/
// svgr: false
}),
],
};`
);

const result = runCLI(`build ${appName}`);

expect(result).toContain(
`Successfully ran target build for project ${appName}`
);
});

it('should support a standard function that returns a config object', () => {
const appName = uniq('app');

runCLI(
`generate @nx/react:application --directory=apps/${appName} --bundler=rspack --e2eTestRunner=none`
);

updateFile(
`apps/${appName}/rspack.config.js`,
`
const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
const { join } = require('path');

module.exports = () => {
return {
output: {
path: join(__dirname, '../../dist/${appName}'),
},
devServer: {
port: 4200,
historyApiFallback: {
index: '/index.html',
disableDotRule: true,
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
},
},
plugins: [
new NxAppRspackPlugin({
tsConfig: './tsconfig.app.json',
main: './src/main.tsx',
index: './src/index.html',
baseHref: '/',
assets: ['./src/favicon.ico', './src/assets'],
styles: ['./src/styles.scss'],
outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
optimization: process.env['NODE_ENV'] === 'production',
}),
new NxReactRspackPlugin({
// Uncomment this line if you don't want to use SVGR
// See: https://react-svgr.com/
// svgr: false
}),
],
};
};`
);

const result = runCLI(`build ${appName}`);
expect(result).toContain(
`Successfully ran target build for project ${appName}`
);
});

it('should support an array of standard config objects', () => {
const appName = uniq('app');
const serverName = uniq('server');

runCLI(
`generate @nx/react:application --directory=apps/${appName} --bundler=rspack --e2eTestRunner=none`
);

// Create server index file
createFile(
`apps/${serverName}/index.js`,
`console.log('Hello from ${serverName}');\n`
);

updateFile(
`apps/${appName}/rspack.config.js`,
`
const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
const { join } = require('path');

module.exports = [
{
name: 'client',
output: {
path: join(__dirname, '../../dist/${appName}'),
},
devServer: {
port: 4200,
historyApiFallback: {
index: '/index.html',
disableDotRule: true,
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
},
},
plugins: [
new NxAppRspackPlugin({
tsConfig: './tsconfig.app.json',
main: './src/main.tsx',
index: './src/index.html',
baseHref: '/',
assets: ['./src/favicon.ico', './src/assets'],
styles: ['./src/styles.scss'],
outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
optimization: process.env['NODE_ENV'] === 'production',
}),
new NxReactRspackPlugin({
// Uncomment this line if you don't want to use SVGR
// See: https://react-svgr.com/
// svgr: false
}),
],
}, {
name: 'server',
target: 'node',
entry: '../${serverName}/index.js',
output: {
path: join(__dirname, '../../dist/${serverName}'),
filename: 'index.js',
},
}
];
`
);

const result = runCLI(`build ${appName}`);

checkFilesExist(`dist/${appName}/main.js`);
checkFilesExist(`dist/${serverName}/index.js`);

expect(result).toContain(
`Successfully ran target build for project ${appName}`
);
});

it('should support a function that returns an array of standard config objects', () => {
const appName = uniq('app');
const serverName = uniq('server');

runCLI(
`generate @nx/react:application --directory=apps/${appName} --bundler=rspack --e2eTestRunner=none`
);

// Create server index file
createFile(
`apps/${serverName}/index.js`,
`console.log('Hello from ${serverName}');\n`
);

updateFile(
`apps/${appName}/rspack.config.js`,
`
const { NxAppRspackPlugin } = require('@nx/rspack/app-plugin');
const { NxReactRspackPlugin } = require('@nx/rspack/react-plugin');
const { join } = require('path');

module.exports = () => {
return [
{
name: 'client',
output: {
path: join(__dirname, '../../dist/${appName}'),
},
devServer: {
port: 4200,
historyApiFallback: {
index: '/index.html',
disableDotRule: true,
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'],
},
},
plugins: [
new NxAppRspackPlugin({
tsConfig: './tsconfig.app.json',
main: './src/main.tsx',
index: './src/index.html',
baseHref: '/',
assets: ['./src/favicon.ico', './src/assets'],
styles: ['./src/styles.scss'],
outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
optimization: process.env['NODE_ENV'] === 'production',
}),
new NxReactRspackPlugin({
// Uncomment this line if you don't want to use SVGR
// See: https://react-svgr.com/
// svgr: false
}),
],
},
{
name: 'server',
target: 'node',
entry: '../${serverName}/index.js',
output: {
path: join(__dirname, '../../dist/${serverName}'),
filename: 'index.js',
}
}
];
};`
);
const result = runCLI(`build ${appName}`);

checkFilesExist(`dist/${serverName}/index.js`);
checkFilesExist(`dist/${appName}/main.js`);

expect(result).toContain(
`Successfully ran target build for project ${appName}`
);
});
});
});
3 changes: 0 additions & 3 deletions packages/react/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import { initWebpack } from './lib/bundlers/add-webpack';
import {
handleStyledJsxForRspack,
initRspack,
setupRspackConfiguration,
} from './lib/bundlers/add-rspack';
import {
initRsbuild,
Expand Down Expand Up @@ -118,8 +117,6 @@ export async function applicationGeneratorInternal(

if (options.bundler === 'vite') {
await setupViteConfiguration(tree, options, tasks);
} else if (options.bundler === 'rspack') {
await setupRspackConfiguration(tree, options, tasks);
} else if (options.bundler === 'rsbuild') {
await setupRsbuildConfiguration(tree, options, tasks);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
} from '@nx/devkit';
import * as pc from 'picocolors';
import { babelLoaderVersion, nxVersion } from '../../../../utils/versions';
import { maybeJs } from '../../../../utils/maybe-js';
import { NormalizedSchema, Schema } from '../../schema';

export async function initRspack(
Expand All @@ -19,38 +18,11 @@ export async function initRspack(
const { rspackInitGenerator } = ensurePackage('@nx/rspack', nxVersion);
const rspackInitTask = await rspackInitGenerator(tree, {
...options,
addPlugin: false,
skipFormat: true,
});
tasks.push(rspackInitTask);
}

export async function setupRspackConfiguration(
tree: Tree,
options: NormalizedSchema<Schema>,
tasks: any[]
) {
const { configurationGenerator } = ensurePackage('@nx/rspack', nxVersion);
const rspackTask = await configurationGenerator(tree, {
project: options.projectName,
main: joinPathFragments(
options.appProjectRoot,
maybeJs(
{
js: options.js,
useJsx: true,
},
`src/main.tsx`
)
),
tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
target: 'web',
newProject: true,
framework: 'react',
});
tasks.push(rspackTask);
}

Comment on lines -28 to -53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone decides they dont want crystal - or their workspace already has useInferencePlugins: false what would happen with this missing?

Copy link
Contributor Author

@ndcunningham ndcunningham Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will behave the same as Webpack. This should be working unless I missed something during my tests.

export function handleStyledJsxForRspack(
tasks: any[],
tree: Tree,
Expand Down
3 changes: 0 additions & 3 deletions packages/rspack/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export default async function (
const tasks = [];
const initTask = await rspackInitGenerator(tree, {
..._options,
// TODO: Crystalize the default rspack.config.js file.
// The default setup isn't crystalized so don't add plugin.
addPlugin: false,
});
tasks.push(initTask);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ export async function configurationGenerator(
) {
const task = await rspackInitGenerator(tree, {
...options,
// TODO: Crystalize the default rspack.config.js file.
// The default setup isn't crystalized so don't add plugin.
addPlugin: false,
});
const { targets, root, projectType } = readProjectConfiguration(
tree,
Expand Down
Loading