Skip to content

Commit

Permalink
feat(rspack): update withReact plugin for parity with webpack plugin (#…
Browse files Browse the repository at this point in the history
…28812)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
  • Loading branch information
ndcunningham authored Nov 12, 2024
1 parent f7f26d8 commit cda7f26
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 63 deletions.
65 changes: 65 additions & 0 deletions packages/rspack/src/utils/lib/apply-react-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Configuration, RspackOptionsNormalized } from '@rspack/core';
import { SvgrOptions } from '../model';

export function applyReactConfig(
options: { svgr?: boolean | SvgrOptions },
config: Partial<RspackOptionsNormalized | Configuration> = {}
): void {
if (global.NX_GRAPH_CREATION) return;

addHotReload(config);

if (options.svgr !== false || typeof options.svgr === 'object') {
removeSvgLoaderIfPresent(config);

const defaultSvgrOptions = {
svgo: false,
titleProp: true,
ref: true,
};

const svgrOptions =
typeof options.svgr === 'object' ? options.svgr : defaultSvgrOptions;

config.module.rules.push(
{
test: /\.svg$/i,
type: 'asset',
resourceQuery: /react/, // *.svg?react
},
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
resourceQuery: { not: [/react/] }, // exclude react component if *.svg?react
use: [{ loader: '@svgr/webpack', options: svgrOptions }],
}
);
}

// enable rspack node api
config.node = {
__dirname: true,
__filename: true,
};
}

function removeSvgLoaderIfPresent(
config: Partial<RspackOptionsNormalized | Configuration>
) {
const svgLoaderIdx = config.module.rules.findIndex(
(rule) => typeof rule === 'object' && rule.test.toString().includes('svg')
);
if (svgLoaderIdx === -1) return;
config.module.rules.splice(svgLoaderIdx, 1);
}

function addHotReload(
config: Partial<RspackOptionsNormalized | Configuration>
) {
const ReactRefreshPlugin = require('@rspack/plugin-react-refresh');
const isDev =
process.env.NODE_ENV === 'development' || config.mode === 'development';
if (isDev) {
config.plugins.push(new ReactRefreshPlugin({ overlay: false }));
}
}
6 changes: 6 additions & 0 deletions packages/rspack/src/utils/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ export interface EmittedFile {
initial: boolean;
asset?: boolean;
}

export interface SvgrOptions {
svgo?: boolean;
titleProp?: boolean;
ref?: boolean;
}
73 changes: 10 additions & 63 deletions packages/rspack/src/utils/with-react.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,24 @@
import { Configuration } from '@rspack/core';
import { withWeb } from './with-web';
import { NxRspackExecutionContext } from './config';
import { withWeb, WithWebOptions } from './with-web';
import { applyReactConfig } from './lib/apply-react-config';
import { SvgrOptions } from './model';

export function withReact(opts = {}) {
export interface WithReactOptions extends WithWebOptions {
svgr?: boolean | SvgrOptions;
}

export function withReact(opts: WithReactOptions = {}) {
return function makeConfig(
config: Configuration,
{ options, context }: NxRspackExecutionContext
): Configuration {
const isDev =
process.env.NODE_ENV === 'development' || options.mode === 'development';

config = withWeb({ ...opts, cssModules: true })(config, {
options,
context,
});

// eslint-disable-next-line @typescript-eslint/no-var-requires
const ReactRefreshPlugin = require('@rspack/plugin-react-refresh');

const react = {
runtime: 'automatic',
development: isDev,
refresh: isDev,
};

return {
...config,
plugins: [
...(config.plugins || []),
isDev && new ReactRefreshPlugin(),
].filter(Boolean),
module: {
...config.module,
rules: [
...(config.module.rules || []),
{
test: /\.jsx$/,
loader: 'builtin:swc-loader',
exclude: /node_modules/,
options: {
jsc: {
parser: {
syntax: 'ecmascript',
jsx: true,
},
transform: {
react,
},
externalHelpers: true,
},
},
type: 'javascript/auto',
},
{
test: /\.tsx$/,
loader: 'builtin:swc-loader',
exclude: /node_modules/,
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
transform: {
react,
},
externalHelpers: true,
},
},
type: 'javascript/auto',
},
],
},
};
applyReactConfig(opts, config);
return config;
};
}

0 comments on commit cda7f26

Please sign in to comment.