diff --git a/.changeset/blue-bats-tease.md b/.changeset/blue-bats-tease.md new file mode 100644 index 0000000000..e6790ccfed --- /dev/null +++ b/.changeset/blue-bats-tease.md @@ -0,0 +1,6 @@ +--- +'@lynx-js/rspeedy': patch +'@lynx-js/react-rsbuild-plugin': patch +--- + +Support environment variants to enable multiple configurations for the same targets. diff --git a/packages/rspeedy/core/src/utils/is-lynx.ts b/packages/rspeedy/core/src/utils/is-lynx.ts index 94bfe87c58..458d3ea1f2 100644 --- a/packages/rspeedy/core/src/utils/is-lynx.ts +++ b/packages/rspeedy/core/src/utils/is-lynx.ts @@ -5,7 +5,8 @@ import type { EnvironmentContext } from '@rsbuild/core' export function isLynx(environment: EnvironmentContext | string): boolean { - return typeof environment === 'string' - ? environment === 'lynx' - : environment.name === 'lynx' + const environmentName = typeof environment === 'string' + ? environment + : environment.name + return environmentName === 'lynx' || environmentName.startsWith('lynx-') } diff --git a/packages/rspeedy/core/src/utils/is-web.ts b/packages/rspeedy/core/src/utils/is-web.ts index 0fd862b39d..8f67dc8fea 100644 --- a/packages/rspeedy/core/src/utils/is-web.ts +++ b/packages/rspeedy/core/src/utils/is-web.ts @@ -5,7 +5,8 @@ import type { EnvironmentContext } from '@rsbuild/core' export function isWeb(environment: EnvironmentContext | string): boolean { - return typeof environment === 'string' - ? environment === 'web' - : environment.name === 'web' + const environmentName = typeof environment === 'string' + ? environment + : environment.name + return environmentName === 'web' || environmentName.startsWith('web-') } diff --git a/packages/rspeedy/plugin-react/src/entry.ts b/packages/rspeedy/plugin-react/src/entry.ts index 7276068ec4..d15a29cab3 100644 --- a/packages/rspeedy/plugin-react/src/entry.ts +++ b/packages/rspeedy/plugin-react/src/entry.ts @@ -61,7 +61,9 @@ export function applyEntry( api.modifyBundlerChain(async (chain, { environment, isDev, isProd }) => { const entries = chain.entryPoints.entries() ?? {} const isLynx = environment.name === 'lynx' + || environment.name.startsWith('lynx-') const isWeb = environment.name === 'web' + || environment.name.startsWith('web-') const { hmr, liveReload } = environment.config.dev ?? {} const enabledHMR = isDev && !isWeb && hmr !== false const enabledLiveReload = isDev && !isWeb && liveReload !== false diff --git a/packages/rspeedy/plugin-react/test/config.test.ts b/packages/rspeedy/plugin-react/test/config.test.ts index 3d8a540495..e4db926828 100644 --- a/packages/rspeedy/plugin-react/test/config.test.ts +++ b/packages/rspeedy/plugin-react/test/config.test.ts @@ -4,7 +4,7 @@ import { createRequire } from 'node:module' import path from 'node:path' -import type { RsbuildInstance } from '@rsbuild/core' +import type { RsbuildInstance, Rspack } from '@rsbuild/core' import { describe, expect, test, vi } from 'vitest' import type { ReactWebpackPlugin } from '@lynx-js/react-webpack-plugin' @@ -2353,6 +2353,106 @@ describe('Config', () => { require.resolve('@lynx-js/react/worklet-runtime'), ) }) + + describe('environment', () => { + test('lynx environment', async () => { + const { pluginReactLynx } = await import('../src/pluginReactLynx.js') + + const rspeedy = await createRspeedy({ + rspeedyConfig: { + environments: { lynx: {} }, + plugins: [ + pluginReactLynx(), + ], + }, + }) + + const configs = await rspeedy.initConfigs() + + expect(configs.length).toBe(1) + + expect(configs[0]!.name).toBe('lynx') + }) + + test('lynx variant environment', async () => { + const { pluginReactLynx } = await import('../src/pluginReactLynx.js') + + const rspeedy = await createRspeedy({ + rspeedyConfig: { + environments: { + lynx: {}, + 'lynx-foo': { output: { distPath: 'dist/foo' } }, + }, + plugins: [ + pluginReactLynx(), + ], + }, + }) + + const configs = await rspeedy.initConfigs() + + expect(configs.length).toBe(2) + + expect(configs[0]!.name).toBe('lynx') + expect(configs[1]!.name).toBe('lynx-foo') + // only lynx output will be emitted to `.rspeedy` + expect( + (configs[1]?.entry as Record)?.['main'] + ?.filename, + ).toBe('.rspeedy/main/background.js') + }) + + test('web environment', async () => { + const { pluginReactLynx } = await import('../src/pluginReactLynx.js') + + const rspeedy = await createRspeedy({ + rspeedyConfig: { + environments: { web: {} }, + plugins: [ + pluginReactLynx(), + ], + }, + }) + + const configs = await rspeedy.initConfigs() + + expect(configs.length).toBe(1) + + expect(configs[0]!.name).toBe('web') + }) + + test('web variant environment', async () => { + const { pluginReactLynx } = await import('../src/pluginReactLynx.js') + + const rspeedy = await createRspeedy({ + rspeedyConfig: { + environments: { + web: {}, + 'web-foo': { output: { distPath: 'dist/foo' } }, + }, + plugins: [ + pluginReactLynx(), + ], + }, + }) + + const configs = await rspeedy.initConfigs() + + expect(configs.length).toBe(2) + + expect(configs[0]!.name).toBe('web') + expect(configs[1]!.name).toBe('web-foo') + + expect( + (configs[0]?.entry as Record)?.['main'] + ?.filename, + ).toBe('main/background.js') + expect( + (configs[1]?.entry as Record)?.['main'] + ?.filename, + ).toBe('main/background.js') + }) + }) }) describe('MPA Config', () => {