Skip to content

Commit

Permalink
feat: support only build specified environment (#3059)
Browse files Browse the repository at this point in the history
Co-authored-by: neverland <[email protected]>
  • Loading branch information
9aoy and chenjiahan authored Jul 30, 2024
1 parent cb548a1 commit ef4f39b
Show file tree
Hide file tree
Showing 18 changed files with 201 additions and 38 deletions.
20 changes: 20 additions & 0 deletions e2e/cases/cli/specified-environment/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { execSync } from 'node:child_process';
import path from 'node:path';
import { globContentJSON } from '@e2e/helper';
import { expect, test } from '@playwright/test';

test('should only build specified environment when using --environment option', async () => {
execSync('npx rsbuild build --environment web2', {
cwd: __dirname,
});

const files = await globContentJSON(path.join(__dirname, 'dist'));
const outputFiles = Object.keys(files);

expect(
outputFiles.find((item) => item.includes('web1/index.html')),
).toBeFalsy();
expect(
outputFiles.find((item) => item.includes('web2/index.html')),
).toBeTruthy();
});
20 changes: 20 additions & 0 deletions e2e/cases/cli/specified-environment/rsbuild.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineConfig } from '@rsbuild/core';

export default defineConfig({
environments: {
web1: {
output: {
distPath: {
root: 'dist/web1',
},
},
},
web2: {
output: {
distPath: {
root: 'dist/web2',
},
},
},
},
});
1 change: 1 addition & 0 deletions e2e/cases/cli/specified-environment/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hello!');
4 changes: 2 additions & 2 deletions packages/compat/webpack/src/initConfigs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
type CreateRsbuildOptions,
type InspectConfigOptions,
type PluginManager,
type ResolvedCreateRsbuildOptions,
logger,
} from '@rsbuild/core';
import { inspectConfig } from './inspectConfig';
Expand All @@ -12,7 +12,7 @@ import { generateWebpackConfig } from './webpackConfig';
export type InitConfigsOptions = {
context: InternalContext;
pluginManager: PluginManager;
rsbuildOptions: Required<CreateRsbuildOptions>;
rsbuildOptions: ResolvedCreateRsbuildOptions;
};

export async function initConfigs({
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/cli/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type CommonOptions = {
open?: boolean | string;
host?: string;
port?: number;
environment?: string[];
};

export type BuildOptions = CommonOptions & {
Expand All @@ -39,6 +40,11 @@ const applyCommonOptions = (command: Command) => {
'--env-mode <mode>',
'specify the env mode to load the `.env.[mode]` file',
)
.option<string[]>(
'--environment <name>',
'specify the name of environment to build',
(str, prev) => (prev ? prev.concat(str.split(',')) : str.split(',')),
)
.option('--env-dir <dir>', 'specify the directory to load `.env` files');
};

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/cli/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export async function init({
return createRsbuild({
cwd: root,
rsbuildConfig: config,
environment: commonOpts.environment,
});
} catch (err) {
if (isRestart) {
Expand Down
7 changes: 4 additions & 3 deletions packages/core/src/createContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import { getHTMLPathByEntry } from './initPlugins';
import { logger } from './logger';
import type {
BundlerType,
CreateRsbuildOptions,
EnvironmentContext,
InternalContext,
NormalizedConfig,
NormalizedEnvironmentConfig,
ResolvedCreateRsbuildOptions,
RsbuildConfig,
RsbuildContext,
RsbuildEntry,
Expand All @@ -35,7 +35,7 @@ function getAbsoluteDistPath(
* Create context by config.
*/
async function createContextByConfig(
options: Required<CreateRsbuildOptions>,
options: ResolvedCreateRsbuildOptions,
bundlerType: BundlerType,
): Promise<RsbuildContext> {
const { cwd } = options;
Expand Down Expand Up @@ -210,7 +210,7 @@ export function createPublicContext(
* which can have a lot of overhead and take some side effects.
*/
export async function createContext(
options: Required<CreateRsbuildOptions>,
options: ResolvedCreateRsbuildOptions,
userRsbuildConfig: RsbuildConfig,
bundlerType: BundlerType,
): Promise<InternalContext> {
Expand All @@ -223,5 +223,6 @@ export async function createContext(
hooks: initHooks(),
config: { ...rsbuildConfig },
originalConfig: userRsbuildConfig,
specifiedEnvironments: options.environment,
};
}
8 changes: 6 additions & 2 deletions packages/core/src/createRsbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
InternalContext,
PluginManager,
PreviewServerOptions,
ResolvedCreateRsbuildOptions,
RsbuildInstance,
RsbuildProvider,
} from './types';
Expand Down Expand Up @@ -99,7 +100,7 @@ export async function createRsbuild(
): Promise<RsbuildInstance> {
const { rsbuildConfig = {} } = options;

const rsbuildOptions: Required<CreateRsbuildOptions> = {
const rsbuildOptions: ResolvedCreateRsbuildOptions = {
cwd: process.cwd(),
rsbuildConfig,
...options,
Expand Down Expand Up @@ -180,7 +181,10 @@ export async function createRsbuild(
if (rsbuildConfig.environments) {
await Promise.all(
Object.entries(rsbuildConfig.environments).map(async ([name, config]) => {
if (config.plugins) {
const isEnvironmentEnabled =
!rsbuildOptions.environment ||
rsbuildOptions.environment.includes(name);
if (config.plugins && isEnvironmentEnabled) {
const plugins = await Promise.all(config.plugins);
rsbuild.addPlugins(plugins, {
environment: name,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export type {
CreateCompiler,
CreateCompilerOptions,
CreateRsbuildOptions,
ResolvedCreateRsbuildOptions,
CrossOrigin,
CSSLoaderOptions,
CSSModules,
Expand Down
76 changes: 49 additions & 27 deletions packages/core/src/provider/initConfigs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import color from 'picocolors';
import { getDefaultEntry, normalizeConfig } from '../config';
import { JS_DIST_DIR } from '../constants';
import {
Expand All @@ -9,14 +10,14 @@ import { isDebug, logger } from '../logger';
import { mergeRsbuildConfig } from '../mergeConfig';
import { initPlugins } from '../pluginManager';
import type {
CreateRsbuildOptions,
InspectConfigOptions,
InternalContext,
MergedEnvironmentConfig,
ModifyEnvironmentConfigUtils,
NormalizedConfig,
NormalizedEnvironmentConfig,
PluginManager,
ResolvedCreateRsbuildOptions,
RsbuildEntry,
RspackConfig,
} from '../types';
Expand Down Expand Up @@ -62,12 +63,13 @@ async function modifyEnvironmentConfig(
export type InitConfigsOptions = {
context: InternalContext;
pluginManager: PluginManager;
rsbuildOptions: Required<CreateRsbuildOptions>;
rsbuildOptions: ResolvedCreateRsbuildOptions;
};

const initEnvironmentConfigs = (
normalizedConfig: NormalizedConfig,
rootPath: string,
specifiedEnvironments?: string[],
): Record<string, MergedEnvironmentConfig> => {
let defaultEntry: RsbuildEntry;
const getDefaultEntryWithMemo = () => {
Expand All @@ -80,6 +82,9 @@ const initEnvironmentConfigs = (
normalizedConfig;
const { assetPrefix, lazyCompilation } = dev;

const isEnvironmentEnabled = (name: string) =>
!specifiedEnvironments || specifiedEnvironments.includes(name);

const applyEnvironmentDefaultConfig = (config: MergedEnvironmentConfig) => {
if (!config.source.entry) {
config.source.entry = getDefaultEntryWithMemo();
Expand All @@ -94,35 +99,51 @@ const initEnvironmentConfigs = (
};

if (environments && Object.keys(environments).length) {
return Object.fromEntries(
Object.entries(environments).map(([name, config]) => {
const environmentConfig: MergedEnvironmentConfig = {
...(mergeRsbuildConfig(
{
...rsbuildSharedConfig,
dev: {
assetPrefix,
lazyCompilation,
},
} as unknown as MergedEnvironmentConfig,
config as unknown as MergedEnvironmentConfig,
) as unknown as MergedEnvironmentConfig),
};

return [name, applyEnvironmentDefaultConfig(environmentConfig)];
}),
const resolvedEnvironments = Object.fromEntries(
Object.entries(environments)
.filter(([name]) => isEnvironmentEnabled(name))
.map(([name, config]) => {
const environmentConfig: MergedEnvironmentConfig = {
...(mergeRsbuildConfig(
{
...rsbuildSharedConfig,
dev: {
assetPrefix,
lazyCompilation,
},
} as unknown as MergedEnvironmentConfig,
config as unknown as MergedEnvironmentConfig,
) as unknown as MergedEnvironmentConfig),
};

return [name, applyEnvironmentDefaultConfig(environmentConfig)];
}),
);

if (!Object.keys(resolvedEnvironments).length) {
throw new Error(
`The current build is specified to run only in the ${color.yellow(specifiedEnvironments?.join(','))} environment, but the configuration of the specified environment was not found.`,
);
}
return resolvedEnvironments;
}

const defaultEnvironmentName = camelCase(rsbuildSharedConfig.output.target);

if (!isEnvironmentEnabled(defaultEnvironmentName)) {
throw new Error(
`The current build is specified to run only in the ${color.yellow(specifiedEnvironments?.join(','))} environment, but the configuration of the specified environment was not found.`,
);
}

return {
[camelCase(rsbuildSharedConfig.output.target)]:
applyEnvironmentDefaultConfig({
...rsbuildSharedConfig,
dev: {
assetPrefix,
lazyCompilation,
},
} as MergedEnvironmentConfig),
[defaultEnvironmentName]: applyEnvironmentDefaultConfig({
...rsbuildSharedConfig,
dev: {
assetPrefix,
lazyCompilation,
},
} as MergedEnvironmentConfig),
};
};

Expand Down Expand Up @@ -151,6 +172,7 @@ export async function initRsbuildConfig({
const mergedEnvironments = initEnvironmentConfigs(
normalizeBaseConfig,
context.rootPath,
context.specifiedEnvironments,
);

const {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/types/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ export type InternalContext = RsbuildContext & {
getPluginAPI?: (environment?: string) => RsbuildPluginAPI;
/** The environment context. */
environments: Record<string, EnvironmentContext>;
/** Only build specified environment. */
specifiedEnvironments?: string[];
};
7 changes: 6 additions & 1 deletion packages/core/src/types/rsbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,13 @@ export type CreateRsbuildOptions = {
cwd?: string;
/** Configurations of Rsbuild. */
rsbuildConfig?: RsbuildConfig;
/** Only build specified environment. */
environment?: string[];
};

export type ResolvedCreateRsbuildOptions = CreateRsbuildOptions &
Required<Omit<CreateRsbuildOptions, 'environment'>>;

export type ProviderInstance<B extends 'rspack' | 'webpack' = 'rspack'> = {
readonly bundler: Bundler;

Expand Down Expand Up @@ -104,7 +109,7 @@ export type RsbuildProvider<B extends 'rspack' | 'webpack' = 'rspack'> =
(options: {
context: InternalContext;
pluginManager: PluginManager;
rsbuildOptions: Required<CreateRsbuildOptions>;
rsbuildOptions: ResolvedCreateRsbuildOptions;
setCssExtractPlugin: (plugin: unknown) => void;
}) => Promise<ProviderInstance<B>>;

Expand Down
36 changes: 36 additions & 0 deletions packages/core/tests/environments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,42 @@ describe('environment config', () => {
).toMatchSnapshot();
});

it('should support run specified environment', async () => {
process.env.NODE_ENV = 'development';

const pluginLogs: string[] = [];

const plugin: (pluginId: string) => RsbuildPlugin = (pluginId) => ({
name: 'test-environment',
setup: () => {
pluginLogs.push(`run plugin in ${pluginId}`);
},
});

const rsbuild = await createRsbuild({
rsbuildConfig: {
environments: {
web: {
plugins: [plugin('web')],
},
ssr: {
plugins: [plugin('ssr')],
},
},
},
environment: ['ssr'],
});

rsbuild.addPlugins([plugin('global')]);

const {
origin: { environmentConfigs },
} = await rsbuild.inspectConfig();

expect(Object.keys(environmentConfigs)).toEqual(['ssr']);
expect(pluginLogs).toEqual(['run plugin in ssr', 'run plugin in global']);
});

it('should normalize environment config correctly', async () => {
process.env.NODE_ENV = 'development';
const rsbuild = await createRsbuild({
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-helper/src/rsbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function createStubRsbuild({
}
> {
const { createRsbuild } = await import('@rsbuild/core');
const rsbuildOptions: Required<CreateRsbuildOptions> = {
const rsbuildOptions = {
cwd: process.env.REBUILD_TEST_SUITE_CWD || process.cwd(),
rsbuildConfig,
...options,
Expand Down
Loading

0 comments on commit ef4f39b

Please sign in to comment.