Skip to content

Commit

Permalink
feat: support environments api
Browse files Browse the repository at this point in the history
  • Loading branch information
XXXMrG committed Jan 17, 2025
1 parent cd2b97e commit 0492df6
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 22 deletions.
51 changes: 32 additions & 19 deletions packages/ice/src/bundler/rspack/getConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getFallbackEntry, getReCompilePlugin, getServerPlugin, getSpinnerPlugin
import { getExpandedEnvs } from '../../utils/runtimeEnv.js';
import type { BundlerOptions, Context } from '../types.js';
import type { PluginData } from '../../types/plugin.js';
import { bundlerConfigContext } from '../../service/onGetBundlerConfig.js';

type GetConfig = (
context: Context,
Expand Down Expand Up @@ -71,25 +72,37 @@ const getConfig: GetConfig = async (context, options, rspack) => {
getReCompilePlugin(reCompile, routeManifest),
].filter(Boolean) as Config['plugins'];
};
return await Promise.all(taskConfigs.map(async ({ config }) => {
const plugins = getPlugins(config);
return await getRspackConfig({
rootDir,
rspack,
runtimeTmpDir: RUNTIME_TMP_DIR,
runtimeDefineVars: {
[IMPORT_META_TARGET]: JSON.stringify(config.target),
[IMPORT_META_RENDERER]: JSON.stringify('client'),
},
getRoutesFile,
getExpandedEnvs,
localIdentName: config.cssModules?.localIdentName || (config.mode === 'development' ? CSS_MODULES_LOCAL_IDENT_NAME_DEV : CSS_MODULES_LOCAL_IDENT_NAME),
taskConfig: {
...config,
plugins: (config.plugins || []).concat(plugins),
},
});
}));
return await Promise.all(
taskConfigs.map(async ({ config, name }) => {
const plugins = getPlugins(config);
const rspackConfig = await getRspackConfig({
rootDir,
rspack,
runtimeTmpDir: RUNTIME_TMP_DIR,
runtimeDefineVars: {
[IMPORT_META_TARGET]: JSON.stringify(config.target),
[IMPORT_META_RENDERER]: JSON.stringify('client'),
},
getRoutesFile,
getExpandedEnvs,
localIdentName:
config.cssModules?.localIdentName ||
(config.mode === 'development' ? CSS_MODULES_LOCAL_IDENT_NAME_DEV : CSS_MODULES_LOCAL_IDENT_NAME),
taskConfig: {
...config,
plugins: (config.plugins || []).concat(plugins),
},
});

// run onGetBundlerConfig hooks
const finalConfig = await bundlerConfigContext.runOnGetBundlerConfig(rspackConfig, {
environment: { name },
type: 'rspack',
});

return finalConfig as Configuration;
}),
);
};

type GetDataLoaderRspackConfig = (
Expand Down
20 changes: 17 additions & 3 deletions packages/ice/src/bundler/webpack/getWebpackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type RouteManifest from '../../utils/routeManifest.js';
import type ServerRunnerPlugin from '../../webpack/ServerRunnerPlugin.js';
import type ServerCompilerPlugin from '../../webpack/ServerCompilerPlugin.js';
import type { BundlerOptions, Context } from '../types.js';
import { bundlerConfigContext } from '../../service/onGetBundlerConfig.js';

const { debounce } = lodash;

Expand Down Expand Up @@ -67,7 +68,7 @@ const getWebpackConfig: GetWebpackConfig = async (context, options) => {
const { target = WEB } = commandArgs;
const userConfigHash = await getFileHash(configFilePath);

const webpackConfigs = taskConfigs.map(({ config }) => {
const webpackConfigs = taskConfigs.map(({ config, name }) => {
const { useDevServer, useDataLoader, server } = config;
// If the target in the task config doesn't exit, use the target from cli command option.
config.target ||= target;
Expand Down Expand Up @@ -125,10 +126,23 @@ const getWebpackConfig: GetWebpackConfig = async (context, options) => {
// Add spinner for webpack task.
webpackConfig.plugins.push(getSpinnerPlugin(spinner));

return webpackConfig;
return {
webpackConfig,
name,
};
});

return webpackConfigs;
const finalConfigs = await Promise.all(
webpackConfigs.map(async ({ webpackConfig, name }) => {
const result = await bundlerConfigContext.runOnGetBundlerConfig(webpackConfig, {
environment: { name },
type: 'webpack',
});
return result;
}),
);

return finalConfigs as Configuration[];
};

export default getWebpackConfig;
4 changes: 4 additions & 0 deletions packages/ice/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,10 @@ const userConfig = [
validation: 'boolean',
defaultValue: true,
},
{
name: 'environments',
validation: 'object',
},
];

const cliOption = [
Expand Down
14 changes: 14 additions & 0 deletions packages/ice/src/createService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import rspackBundler from './bundler/rspack/index.js';
import getDefaultTaskConfig from './plugins/task.js';
import { multipleServerEntry, renderMultiEntry } from './utils/multipleEntry.js';
import hasDocument from './utils/hasDocument.js';
import { onGetBundlerConfig } from './service/onGetBundlerConfig.js';
import { onGetEnvironmentConfig, environmentConfigContext } from './service/onGetEnvironmentConfig.js';

const require = createRequire(import.meta.url);
const __dirname = path.dirname(fileURLToPath(import.meta.url));
Expand Down Expand Up @@ -186,6 +188,8 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
const defaultTaskConfig = getDefaultTaskConfig({ rootDir, command });
return ctx.registerTask(target, mergeConfig(defaultTaskConfig, config));
},
onGetBundlerConfig,
onGetEnvironmentConfig,
},
});
// Load .env before resolve user config, so we can access env variables defined in .env files.
Expand Down Expand Up @@ -384,6 +388,16 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
dataLoader: command !== 'build' || loaderExports,
});

const { environments } = userConfig;
if (environments) {
for (const [envName, envConfig] of Object.entries(environments)) {
const envTaskConfig = mergeConfig(Object.assign({}, platformTaskConfig.config), envConfig as Config);
ctx.registerTask(envName, envTaskConfig);
}

environmentConfigContext.runOnGetEnvironmentConfig(taskConfigs);
}

return {
run: async () => {
const bundlerConfig = {
Expand Down
41 changes: 41 additions & 0 deletions packages/ice/src/service/onGetBundlerConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Configuration as RspackConfiguration } from '@rspack/core';
import type { Configuration as WebpackConfiguration } from 'webpack';
import type { EnvironmentContext } from '../types';

type BundlerType = 'rspack' | 'webpack';
type BundlerConfig = RspackConfiguration | WebpackConfiguration;

export interface ModifyBundlerConfigOption {
environment: EnvironmentContext;
type: BundlerType;
}

type ModifyConfigFn = (
config: BundlerConfig,
options: ModifyBundlerConfigOption,
) => Promise<BundlerConfig | void> | void | BundlerConfig;

export type OnGetBundlerConfig = (cb: ModifyConfigFn) => void;

class BundlerConfigContext {
private modifyConfigFns: ModifyConfigFn[] = [];

onGetBundlerConfig(cb: ModifyConfigFn) {
this.modifyConfigFns.push(cb);
}

async runOnGetBundlerConfig(config: BundlerConfig, options: ModifyBundlerConfigOption) {
for (const fn of this.modifyConfigFns) {
const result = await fn(config, options);
if (result) {
config = result;
}
}
return config;
}
}

export const bundlerConfigContext = new BundlerConfigContext();

export const onGetBundlerConfig: OnGetBundlerConfig =
bundlerConfigContext.onGetBundlerConfig.bind(bundlerConfigContext);
36 changes: 36 additions & 0 deletions packages/ice/src/service/onGetEnvironmentConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { TaskConfig } from 'build-scripts';
import type { Config, EnvironmentContext } from '../types';

interface ModifyEnvironmentConfigOption {
environment: EnvironmentContext;
}

export type OnGetEnvironmentConfig = (cb: ModifyEnvironmentConfigFn) => void;

type ModifyEnvironmentConfigFn = (
config: Config,
options: ModifyEnvironmentConfigOption,
) => Promise<Config | void> | void | Config;

class EnvironmentConfigContext {
private modifyConfigFns: ModifyEnvironmentConfigFn[] = [];

onGetEnvironmentConfig(cb: ModifyEnvironmentConfigFn) {
this.modifyConfigFns.push(cb);
}

async runOnGetEnvironmentConfig(taskConfigs: TaskConfig<Config>[]) {
for (const fn of this.modifyConfigFns) {
taskConfigs.forEach(async (taskConfig) => {
const result = await fn(taskConfig.config, { environment: { name: taskConfig.name } });
if (result) {
taskConfig.config = result;
}
});
}
}
}

export const environmentConfigContext = new EnvironmentConfigContext();
export const onGetEnvironmentConfig: OnGetEnvironmentConfig =
environmentConfigContext.onGetEnvironmentConfig.bind(environmentConfigContext);
23 changes: 23 additions & 0 deletions packages/ice/src/types/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { UserConfig } from './userConfig';

type EnvironmentNotSupportConfig = Omit<
UserConfig,
| 'server'
| 'configureWebpack'
| 'webpack'
| 'routes'
| 'eslint'
| 'tsChecker'
| 'ssr'
| 'ssg'
| 'optimization'
| 'mock'
| 'plugins'
>;

export type EnvironmentUserConfig = Record<string, EnvironmentNotSupportConfig>;

export interface EnvironmentContext {
name: string;
// dependencies: Set<string>;
}
1 change: 1 addition & 0 deletions packages/ice/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './plugin.js';
export * from './userConfig.js';
// Export type webpack for same instance of webpack.
export type { Config, webpack } from '@ice/shared-config/types';
export * from './environment.js';
4 changes: 4 additions & 0 deletions packages/ice/src/types/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import type { Config } from '@ice/shared-config/types';
import type { AppConfig, AssetsManifest } from '@ice/runtime/types';
import type ServerCompileTask from '../utils/ServerCompileTask.js';
import type { CreateLogger } from '../utils/logger.js';
import type { OnGetEnvironmentConfig } from '../service/onGetEnvironmentConfig.js';
import type { OnGetBundlerConfig } from '../service/onGetBundlerConfig.js';
import type { DeclarationData, AddRenderFile, AddTemplateFiles, ModifyRenderData, AddDataLoaderImport, Render } from './generator.js';

export type { CreateLoggerReturnType } from '../utils/logger.js';
Expand Down Expand Up @@ -167,6 +169,8 @@ export interface ExtendsPluginAPI {
addRoutesDefinition: (defineRoutes: DefineExtraRoutes) => void;
dataCache: Map<string, string>;
createLogger: CreateLogger;
onGetBundlerConfig: OnGetBundlerConfig;
onGetEnvironmentConfig: OnGetEnvironmentConfig;
}

export interface OverwritePluginAPI extends ExtendsPluginAPI {
Expand Down
5 changes: 5 additions & 0 deletions packages/ice/src/types/userConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { UnpluginOptions } from '@ice/bundles/compiled/unplugin/index.js';
import type { ProcessOptions } from '@ice/bundles';
import type { Config, ModifyWebpackConfig, MinimizerOptions } from '@ice/shared-config/types';
import type { OverwritePluginAPI } from './plugin';
import type { EnvironmentUserConfig } from './environment';

interface SyntaxFeatures {
// syntax exportDefaultFrom and functionBind is not supported by esbuild
Expand Down Expand Up @@ -281,4 +282,8 @@ export interface UserConfig {
* @see https://v3.ice.work/docs/guide/basic/config#crossoriginloading
*/
crossOriginLoading?: Config['output']['crossOriginLoading'];
/**
* Setup environments
*/
environments?: EnvironmentUserConfig;
}

0 comments on commit 0492df6

Please sign in to comment.