refactor: webpack config (#11421)

This commit is contained in:
forehalo
2025-04-03 11:55:56 +00:00
parent 565d7b2b1e
commit c8d22d97d5
51 changed files with 766 additions and 547 deletions
+170 -74
View File
@@ -1,75 +1,130 @@
import type { Package } from '@affine-tools/utils/workspace';
import webpack, { type Compiler, type Configuration } from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
import { merge } from 'webpack-merge';
import { rmSync } from 'node:fs';
import { cpus } from 'node:os';
import { Logger } from '@affine-tools/utils/logger';
import { Package } from '@affine-tools/utils/workspace';
import { merge } from 'lodash-es';
import webpack from 'webpack';
import WebpackDevServer, {
type Configuration as DevServerConfiguration,
} from 'webpack-dev-server';
import { Option, PackageCommand } from './command';
import { createWebpackConfig } from './webpack';
import { createHTMLTargetConfig, createWorkerTargetConfig } from './webpack';
function getChannel() {
const channel = process.env.BUILD_TYPE ?? 'canary';
switch (channel) {
case 'canary':
case 'beta':
case 'stable':
case 'internal':
return channel;
default: {
throw new Error(
`BUILD_TYPE must be one of canary, beta, stable, internal, received [${channel}]`
function getBundleConfigs(pkg: Package) {
const core = new Package('@affine/core');
const workerConfigs = [
createWorkerTargetConfig(
pkg,
core.srcPath.join(
'modules/workspace-engine/impls/workspace-profile.worker.ts'
).value
),
createWorkerTargetConfig(
pkg,
core.srcPath.join('modules/pdf/renderer/pdf.worker.ts').value
),
createWorkerTargetConfig(
pkg,
core.srcPath.join('blocksuite/extensions/turbo-painter.worker.ts').value
),
];
switch (pkg.name) {
case '@affine/admin': {
return [createHTMLTargetConfig(pkg, pkg.srcPath.join('index.tsx').value)];
}
case '@affine/web':
case '@affine/mobile':
case '@affine/ios':
case '@affine/android': {
workerConfigs.push(
createWorkerTargetConfig(
pkg,
pkg.srcPath.join('nbstore.worker.ts').value
)
);
return [
createHTMLTargetConfig(
pkg,
pkg.srcPath.join('index.tsx').value,
{},
workerConfigs.map(config => config.name)
),
...workerConfigs,
];
}
case '@affine/electron-renderer': {
return [
createHTMLTargetConfig(
pkg,
{
index: pkg.srcPath.join('app/index.tsx').value,
shell: pkg.srcPath.join('shell/index.tsx').value,
popup: pkg.srcPath.join('popup/index.tsx').value,
backgroundWorker: pkg.srcPath.join('background-worker/index.ts')
.value,
},
{
additionalEntryForSelfhost: false,
injectGlobalErrorHandler: false,
emitAssetsManifest: false,
},
workerConfigs.map(config => config.name)
),
...workerConfigs,
];
}
}
throw new Error(`Unsupported package: ${pkg.name}`);
}
const IN_CI = !!process.env.CI;
const httpProxyMiddlewareLogLevel = IN_CI ? 'silent' : 'error';
export async function getConfig(pkg: Package, dev: boolean) {
let config = createWebpackConfig(pkg, {
mode: dev ? 'development' : 'production',
channel: getChannel(),
});
let configOverride: Configuration | undefined;
const overrideConfigPath = pkg.join('webpack.config.ts');
if (overrideConfigPath.isFile()) {
const override = await import(overrideConfigPath.toFileUrl().toString());
configOverride = override.config ?? override.default;
}
if (configOverride) {
config = merge(config, configOverride);
}
return config;
}
export async function start(
compiler: Compiler,
config: Configuration['devServer']
): Promise<WebpackDevServer> {
const devServer = new WebpackDevServer(config, compiler);
await devServer.start();
return devServer;
}
export async function build(compiler: Compiler) {
compiler.run((error, stats) => {
if (error) {
console.error(error);
process.exit(1);
}
if (stats) {
if (stats.hasErrors()) {
console.error(stats.toString('errors-only'));
process.exit(1);
} else {
console.log(stats.toString('minimal'));
}
}
});
}
const defaultDevServerConfig = {
host: '0.0.0.0',
allowedHosts: 'all',
hot: false,
liveReload: true,
client: {
overlay: process.env.DISABLE_DEV_OVERLAY === 'true' ? false : undefined,
logging: process.env.CI ? 'none' : 'error',
},
historyApiFallback: {
rewrites: [
{
from: /.*/,
to: () => {
return process.env.SELF_HOSTED === 'true'
? '/selfhost.html'
: '/index.html';
},
},
],
},
proxy: [
{
context: '/api',
target: 'http://localhost:3010',
logLevel: httpProxyMiddlewareLogLevel,
},
{
context: '/socket.io',
target: 'http://localhost:3010',
ws: true,
logLevel: httpProxyMiddlewareLogLevel,
},
{
context: '/graphql',
target: 'http://localhost:3010',
logLevel: httpProxyMiddlewareLogLevel,
},
],
} as DevServerConfiguration;
export class BundleCommand extends PackageCommand {
static override paths = [['bundle'], ['webpack'], ['pack'], ['bun']];
@@ -83,19 +138,60 @@ export class BundleCommand extends PackageCommand {
});
async execute() {
this.logger.info(`Packing package ${this.package}...`);
const pkg = this.workspace.getPackage(this.package);
const config = await getConfig(
this.workspace.getPackage(this.package),
this.dev
);
if (this.dev) {
await BundleCommand.dev(pkg);
} else {
await BundleCommand.build(pkg);
}
}
static async build(pkg: Package) {
process.env.NODE_ENV = 'production';
const logger = new Logger('bundle');
logger.info(`Packing package ${pkg.name}...`);
logger.info('Cleaning old output...');
rmSync(pkg.distPath.value, { recursive: true, force: true });
const config = getBundleConfigs(pkg);
// @ts-expect-error allow
config.parallelism = cpus().length;
const compiler = webpack(config);
if (this.dev) {
await start(compiler, config.devServer);
} else {
await build(compiler);
}
compiler.run((error, stats) => {
if (error) {
console.error(error);
process.exit(1);
}
if (stats) {
if (stats.hasErrors()) {
console.error(stats.toString('errors-only'));
process.exit(1);
} else {
console.log(stats.toString('minimal'));
}
}
});
}
static async dev(pkg: Package, devServerConfig?: DevServerConfiguration) {
process.env.NODE_ENV = 'development';
const logger = new Logger('bundle');
logger.info(`Starting dev server for ${pkg.name}...`);
const config = getBundleConfigs(pkg);
// @ts-expect-error allow
config.parallelism = cpus().length;
const compiler = webpack(config);
const devServer = new WebpackDevServer(
merge({}, defaultDevServerConfig, devServerConfig),
compiler
);
await devServer.start();
}
}