@gravity-ui/app-builder 0.15.0 → 0.15.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
1
  import WebpackDevServer from 'webpack-dev-server';
2
+ import { RspackDevServer } from '@rspack/dev-server';
2
3
  import type { NormalizedServiceConfig } from '../../common/models';
3
- export declare function watchClientCompilation(config: NormalizedServiceConfig, onManifestReady: () => void): Promise<WebpackDevServer<import("express").Application, import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>>>;
4
+ export declare function watchClientCompilation(config: NormalizedServiceConfig, onManifestReady: () => void): Promise<WebpackDevServer<import("express").Application, import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>> | RspackDevServer>;
@@ -34,9 +34,13 @@ const webpack_dev_server_1 = __importDefault(require("webpack-dev-server"));
34
34
  const webpack_manifest_plugin_1 = require("webpack-manifest-plugin");
35
35
  const webpack_assets_manifest_1 = __importDefault(require("webpack-assets-manifest"));
36
36
  const utils_1 = require("../../common/utils");
37
+ const rspack_manifest_plugin_1 = require("rspack-manifest-plugin");
38
+ const core_1 = require("@rspack/core");
39
+ const dev_server_1 = require("@rspack/dev-server");
37
40
  const paths_1 = __importDefault(require("../../common/paths"));
38
41
  const logger_1 = require("../../common/logger");
39
42
  const config_1 = require("../../common/webpack/config");
43
+ const rspack_1 = require("../../common/webpack/rspack");
40
44
  async function watchClientCompilation(config, onManifestReady) {
41
45
  const clientCompilation = await buildDevServer(config);
42
46
  const compiler = clientCompilation.compiler;
@@ -44,19 +48,42 @@ async function watchClientCompilation(config, onManifestReady) {
44
48
  return clientCompilation;
45
49
  }
46
50
  async function buildDevServer(config) {
51
+ const bundler = config.client.bundler;
47
52
  const logger = new logger_1.Logger('client', config.verbose);
48
53
  const { webSocketPath = path.normalize(`/${config.client.publicPathPrefix}/build/sockjs-node`), writeToDisk, ...devServer } = config.client.devServer || {};
49
54
  const normalizedConfig = { ...config.client, devServer: { ...devServer, webSocketPath } };
50
- const webpackConfigs = [
51
- await (0, config_1.webpackConfigFactory)("development" /* WebpackMode.Dev */, normalizedConfig, { logger }),
52
- ];
53
55
  const isSsr = Boolean(normalizedConfig.ssr);
54
- if (isSsr) {
55
- const ssrLogger = new logger_1.Logger('client(SSR)', config.verbose);
56
- webpackConfigs.push(await (0, config_1.webpackConfigFactory)("development" /* WebpackMode.Dev */, normalizedConfig, {
57
- logger: ssrLogger,
58
- isSsr,
59
- }));
56
+ let webpackConfigs = [];
57
+ let rspackConfigs = [];
58
+ if (bundler === 'webpack') {
59
+ webpackConfigs = [
60
+ await (0, config_1.webpackConfigFactory)({
61
+ webpackMode: "development" /* WebpackMode.Dev */,
62
+ config: normalizedConfig,
63
+ logger,
64
+ }),
65
+ ];
66
+ if (isSsr) {
67
+ const ssrLogger = new logger_1.Logger('webpack(SSR)', config.verbose);
68
+ webpackConfigs.push(await (0, config_1.webpackConfigFactory)({
69
+ webpackMode: "development" /* WebpackMode.Dev */,
70
+ config: normalizedConfig,
71
+ logger: ssrLogger,
72
+ isSsr,
73
+ }));
74
+ }
75
+ }
76
+ else {
77
+ if (isSsr) {
78
+ throw new Error(`SSR is not supported in ${bundler}`);
79
+ }
80
+ rspackConfigs = [
81
+ await (0, config_1.rspackConfigFactory)({
82
+ webpackMode: "development" /* WebpackMode.Dev */,
83
+ config: normalizedConfig,
84
+ logger,
85
+ }),
86
+ ];
60
87
  }
61
88
  const publicPath = path.normalize(config.client.publicPathPrefix + '/build/');
62
89
  const staticFolder = path.resolve(paths_1.default.appDist, 'public');
@@ -134,41 +161,60 @@ async function buildDevServer(config) {
134
161
  });
135
162
  }
136
163
  options.proxy = proxy;
137
- const compiler = (0, webpack_1.default)(webpackConfigs);
138
- const server = new webpack_dev_server_1.default(options, compiler);
164
+ let server;
165
+ if (bundler === 'rspack') {
166
+ // Rspack multicompiler dont work with lazy compilation
167
+ const compiler = (0, core_1.rspack)(rspackConfigs[0]);
168
+ server = new dev_server_1.RspackDevServer(options, compiler);
169
+ // Need to clean cache before start. https://github.com/web-infra-dev/rspack/issues/9025
170
+ (0, rspack_1.clearCacheDirectory)(rspackConfigs[0], logger);
171
+ }
172
+ else {
173
+ const compiler = (0, webpack_1.default)(webpackConfigs);
174
+ server = new webpack_dev_server_1.default(options, compiler);
175
+ }
139
176
  try {
140
177
  await server.start();
141
178
  }
142
179
  catch (e) {
143
- logger.logError('Cannot start webpack dev server', e);
180
+ logger.logError(`Cannot start ${bundler} dev server`, e);
144
181
  }
145
182
  if (options.ipc && typeof options.ipc === 'string') {
146
183
  fs.chmod(options.ipc, 0o666, (e) => logger.logError('', e));
147
184
  }
148
185
  return server;
149
186
  }
150
- function subscribeToManifestReadyEvent(webpackCompiler, onManifestReady) {
187
+ function isRspackCompiler(compiler) {
188
+ return 'rspack' in compiler;
189
+ }
190
+ function subscribeToManifestReadyEvent(compiler, onManifestReady) {
151
191
  const promises = [];
152
- const options = Array.isArray(webpackCompiler.options)
153
- ? webpackCompiler.options
154
- : [webpackCompiler.options];
155
- const compilers = 'compilers' in webpackCompiler ? webpackCompiler.compilers : [webpackCompiler];
192
+ const options = Array.isArray(compiler.options) ? compiler.options : [compiler.options];
193
+ const compilers = 'compilers' in compiler ? compiler.compilers : [compiler];
156
194
  for (let i = 0; i < options.length; i++) {
157
195
  const config = options[i];
158
196
  const compiler = compilers[i];
159
197
  if (!config || !compiler) {
160
198
  throw new Error('Something goes wrong!');
161
199
  }
162
- const assetsManifestPlugin = config.plugins.find((plugin) => plugin instanceof webpack_assets_manifest_1.default);
163
- if (assetsManifestPlugin) {
164
- const assetsManifestReady = (0, utils_1.deferredPromise)();
165
- promises.push(assetsManifestReady.promise);
166
- assetsManifestPlugin.hooks.done.tap('app-builder', assetsManifestReady.resolve);
200
+ if (!isRspackCompiler(compiler)) {
201
+ const assetsManifestPlugin = config.plugins.find((plugin) => plugin instanceof webpack_assets_manifest_1.default);
202
+ if (assetsManifestPlugin) {
203
+ const assetsManifestReady = (0, utils_1.deferredPromise)();
204
+ promises.push(assetsManifestReady.promise);
205
+ assetsManifestPlugin.hooks.done.tap('app-builder', assetsManifestReady.resolve);
206
+ }
167
207
  }
168
208
  const manifestReady = (0, utils_1.deferredPromise)();
169
209
  promises.push(manifestReady.promise);
170
- const { afterEmit } = (0, webpack_manifest_plugin_1.getCompilerHooks)(compiler);
171
- afterEmit.tap('app-builder', manifestReady.resolve);
210
+ if (isRspackCompiler(compiler)) {
211
+ const { afterEmit } = (0, rspack_manifest_plugin_1.getCompilerHooks)(compiler);
212
+ afterEmit.tap('app-builder', manifestReady.resolve);
213
+ }
214
+ else {
215
+ const { afterEmit } = (0, webpack_manifest_plugin_1.getCompilerHooks)(compiler);
216
+ afterEmit.tap('app-builder', manifestReady.resolve);
217
+ }
172
218
  }
173
219
  Promise.all(promises).then(() => onManifestReady());
174
220
  }
@@ -197,9 +197,11 @@ async function normalizeClientConfig(client, mode) {
197
197
  svgr: client.svgr ?? {},
198
198
  entryFilter: client.entryFilter && splitPaths(client.entryFilter),
199
199
  webpack: typeof client.webpack === 'function' ? client.webpack : (config) => config,
200
+ rspack: typeof client.rspack === 'function' ? client.rspack : (config) => config,
200
201
  babel: typeof client.babel === 'function' ? client.babel : (config) => config,
201
202
  devServer: undefined,
202
203
  lazyCompilation: undefined,
204
+ bundler: client.bundler || 'webpack',
203
205
  };
204
206
  if (mode === 'dev') {
205
207
  if (client.lazyCompilation) {
@@ -129,6 +129,7 @@ function compileStyles(inputDir, outputDir, onFinish, additionalGlobs = []) {
129
129
  const sassTransformed = sass_1.default.compile(scssFile, {
130
130
  sourceMap: true,
131
131
  sourceMapIncludeSources: true,
132
+ silenceDeprecations: ['legacy-js-api'],
132
133
  importers: [
133
134
  {
134
135
  findFileUrl(url) {
@@ -3,6 +3,7 @@ import type { EditorFeature } from 'monaco-editor-webpack-plugin/out/features';
3
3
  import type { IFeatureDefinition } from 'monaco-editor-webpack-plugin/out/types';
4
4
  import type { Options as MomentTzOptions } from 'moment-timezone-data-webpack-plugin';
5
5
  import type { Configuration, DefinePlugin, FileCacheOptions, MemoryCacheOptions, ResolveOptions } from 'webpack';
6
+ import type { Configuration as RspackConfiguration } from '@rspack/core';
6
7
  import type * as Babel from '@babel/core';
7
8
  import type { ServerConfiguration } from 'webpack-dev-server';
8
9
  import type { Options as CircularDependenciesOptions } from 'circular-dependency-plugin';
@@ -14,6 +15,7 @@ import type { WebpackMode } from '../webpack/config';
14
15
  import type { UploadOptions } from '../s3-upload/upload';
15
16
  import type { TerserOptions } from 'terser-webpack-plugin';
16
17
  import type { ReactRefreshPluginOptions } from '@pmmmwh/react-refresh-webpack-plugin/types/lib/types';
18
+ type Bundler = 'webpack' | 'rspack';
17
19
  export interface Entities<T> {
18
20
  data: Record<string, T>;
19
21
  keys: string[];
@@ -182,6 +184,13 @@ export interface ClientConfig {
182
184
  configType: `${WebpackMode}`;
183
185
  isSsr?: boolean;
184
186
  }) => Configuration | Promise<Configuration>;
187
+ /**
188
+ * Modify or return a custom Rspack config.
189
+ */
190
+ rspack?: (config: RspackConfiguration, options: {
191
+ configType: `${WebpackMode}`;
192
+ isSsr?: boolean;
193
+ }) => RspackConfiguration | Promise<RspackConfiguration>;
185
194
  /**
186
195
  * Modify or return a custom Babel config.
187
196
  */
@@ -197,6 +206,7 @@ export interface ClientConfig {
197
206
  noExternal?: string | RegExp | (string | RegExp)[] | true;
198
207
  moduleType?: 'commonjs' | 'esm';
199
208
  };
209
+ bundler?: Bundler;
200
210
  }
201
211
  export interface CdnUploadConfig {
202
212
  bucket: string;
@@ -225,6 +235,7 @@ export interface ServiceConfig {
225
235
  verbose?: boolean;
226
236
  }
227
237
  export type NormalizedClientConfig = Omit<ClientConfig, 'publicPathPrefix' | 'hiddenSourceMap' | 'svgr' | 'lazyCompilation' | 'devServer' | 'disableForkTsChecker' | 'disableReactRefresh'> & {
238
+ bundler: Bundler;
228
239
  publicPathPrefix: string;
229
240
  hiddenSourceMap: boolean;
230
241
  svgr: NonNullable<ClientConfig['svgr']>;
@@ -238,6 +249,9 @@ export type NormalizedClientConfig = Omit<ClientConfig, 'publicPathPrefix' | 'hi
238
249
  configType: `${WebpackMode}`;
239
250
  isSsr: boolean;
240
251
  }) => Configuration | Promise<Configuration>;
252
+ rspack: (config: RspackConfiguration, options: {
253
+ configType: `${WebpackMode}`;
254
+ }) => RspackConfiguration | Promise<RspackConfiguration>;
241
255
  debugWebpack?: boolean;
242
256
  babel: (config: Babel.TransformOptions, options: {
243
257
  configType: `${WebpackMode}`;
@@ -0,0 +1,3 @@
1
+ import { NormalizedClientConfig } from '../models';
2
+ import type { Logger } from '../logger';
3
+ export declare function createS3UploadPlugins(config: NormalizedClientConfig, logger?: Logger): (false | "" | 0 | ((this: import("webpack").Compiler, compiler: import("webpack").Compiler) => void) | import("webpack").WebpackPluginInstance | null)[];
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createS3UploadPlugins = createS3UploadPlugins;
4
+ const webpack_plugin_1 = require("./webpack-plugin");
5
+ function createS3UploadPlugins(config, logger) {
6
+ const plugins = [];
7
+ let credentialsGlobal;
8
+ if (process.env.FRONTEND_S3_ACCESS_KEY_ID && process.env.FRONTEND_S3_SECRET_ACCESS_KEY) {
9
+ credentialsGlobal = {
10
+ accessKeyId: process.env.FRONTEND_S3_ACCESS_KEY_ID,
11
+ secretAccessKey: process.env.FRONTEND_S3_SECRET_ACCESS_KEY,
12
+ };
13
+ }
14
+ const cdns = Array.isArray(config.cdn) ? config.cdn : [config.cdn];
15
+ for (let index = 0; index < cdns.length; index++) {
16
+ const cdn = cdns[index];
17
+ if (!cdn) {
18
+ continue;
19
+ }
20
+ let credentials = credentialsGlobal;
21
+ const accessKeyId = process.env[`FRONTEND_S3_ACCESS_KEY_ID_${index}`];
22
+ const secretAccessKey = process.env[`FRONTEND_S3_SECRET_ACCESS_KEY_${index}`];
23
+ if (accessKeyId && secretAccessKey) {
24
+ credentials = {
25
+ accessKeyId,
26
+ secretAccessKey,
27
+ };
28
+ }
29
+ plugins.push(new webpack_plugin_1.S3UploadPlugin({
30
+ exclude: config.hiddenSourceMap ? /\.map$/ : undefined,
31
+ compress: cdn.compress,
32
+ s3ClientOptions: {
33
+ region: cdn.region,
34
+ endpoint: cdn.endpoint,
35
+ credentials,
36
+ },
37
+ s3UploadOptions: {
38
+ bucket: cdn.bucket,
39
+ targetPath: cdn.prefix,
40
+ cacheControl: cdn.cacheControl,
41
+ },
42
+ additionalPattern: cdn.additionalPattern,
43
+ logger,
44
+ }));
45
+ }
46
+ return plugins;
47
+ }
@@ -1,3 +1,4 @@
1
1
  export { S3UploadPlugin } from './webpack-plugin';
2
2
  export { uploadFiles } from './upload';
3
+ export { createS3UploadPlugins } from './create-plugin';
3
4
  export type { UploadFilesOptions } from './upload';
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uploadFiles = exports.S3UploadPlugin = void 0;
3
+ exports.createS3UploadPlugins = exports.uploadFiles = exports.S3UploadPlugin = void 0;
4
4
  var webpack_plugin_1 = require("./webpack-plugin");
5
5
  Object.defineProperty(exports, "S3UploadPlugin", { enumerable: true, get: function () { return webpack_plugin_1.S3UploadPlugin; } });
6
6
  var upload_1 = require("./upload");
7
7
  Object.defineProperty(exports, "uploadFiles", { enumerable: true, get: function () { return upload_1.uploadFiles; } });
8
+ var create_plugin_1 = require("./create-plugin");
9
+ Object.defineProperty(exports, "createS3UploadPlugins", { enumerable: true, get: function () { return create_plugin_1.createS3UploadPlugins; } });
@@ -5,22 +5,46 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.clientCompile = clientCompile;
7
7
  const webpack_1 = __importDefault(require("webpack"));
8
+ const core_1 = require("@rspack/core");
8
9
  const logger_1 = require("../logger");
9
10
  const config_1 = require("./config");
10
11
  const utils_1 = require("./utils");
11
12
  async function clientCompile(config) {
12
13
  const logger = new logger_1.Logger('client', config.verbose);
13
- const webpackConfigs = [await (0, config_1.webpackConfigFactory)("production" /* WebpackMode.Prod */, config, { logger })];
14
+ const webpackConfigs = [];
15
+ const rspackConfigs = [];
14
16
  const isSsr = Boolean(config.ssr);
15
- if (isSsr) {
16
- const ssrLogger = new logger_1.Logger('client(SSR)', config.verbose);
17
- webpackConfigs.push(await (0, config_1.webpackConfigFactory)("production" /* WebpackMode.Prod */, config, { logger: ssrLogger, isSsr }));
17
+ if (config.bundler === 'rspack') {
18
+ rspackConfigs.push(await (0, config_1.rspackConfigFactory)({ webpackMode: "production" /* WebpackMode.Prod */, config, logger }));
19
+ if (isSsr) {
20
+ const ssrLogger = new logger_1.Logger('client(SSR)', config.verbose);
21
+ rspackConfigs.push(await (0, config_1.rspackConfigFactory)({
22
+ webpackMode: "production" /* WebpackMode.Prod */,
23
+ config,
24
+ logger: ssrLogger,
25
+ isSsr,
26
+ }));
27
+ }
28
+ }
29
+ else {
30
+ webpackConfigs.push(await (0, config_1.webpackConfigFactory)({ webpackMode: "production" /* WebpackMode.Prod */, config, logger }));
31
+ if (isSsr) {
32
+ const ssrLogger = new logger_1.Logger('client(SSR)', config.verbose);
33
+ webpackConfigs.push(await (0, config_1.webpackConfigFactory)({
34
+ webpackMode: "production" /* WebpackMode.Prod */,
35
+ config,
36
+ logger: ssrLogger,
37
+ isSsr,
38
+ }));
39
+ }
18
40
  }
19
41
  logger.verbose('Config created');
20
42
  return new Promise((resolve) => {
21
- const compiler = (0, webpack_1.default)(webpackConfigs, (0, utils_1.webpackCompilerHandlerFactory)(logger, async () => {
22
- resolve();
23
- }));
43
+ const compiler = config.bundler === 'rspack'
44
+ ? (0, core_1.rspack)(rspackConfigs) // TODO add compiler factory
45
+ : (0, webpack_1.default)(webpackConfigs, (0, utils_1.webpackCompilerHandlerFactory)(logger, async () => {
46
+ resolve();
47
+ }));
24
48
  process.on('SIGINT', async () => {
25
49
  compiler.close(() => {
26
50
  process.exit(1);
@@ -1,4 +1,5 @@
1
1
  import * as webpack from 'webpack';
2
+ import { Configuration as RspackConfiguration } from '@rspack/core';
2
3
  import type { NormalizedClientConfig } from '../models';
3
4
  import type { Logger } from '../logger';
4
5
  export interface HelperOptions {
@@ -15,12 +16,16 @@ export declare const enum WebpackMode {
15
16
  Prod = "production",
16
17
  Dev = "development"
17
18
  }
18
- export declare function webpackConfigFactory(webpackMode: WebpackMode, config: NormalizedClientConfig, { logger, isSsr }?: {
19
+ type ClientFactoryOptions = {
20
+ webpackMode: WebpackMode;
21
+ config: NormalizedClientConfig;
19
22
  logger?: Logger;
20
23
  isSsr?: boolean;
21
- }): Promise<webpack.Configuration>;
24
+ };
25
+ export declare function webpackConfigFactory(options: ClientFactoryOptions): Promise<webpack.Configuration>;
26
+ export declare function rspackConfigFactory(options: ClientFactoryOptions): Promise<RspackConfiguration>;
22
27
  export declare function configureModuleRules(helperOptions: HelperOptions, additionalRules?: NonNullable<webpack.RuleSetRule['oneOf']>): webpack.RuleSetRule[];
23
28
  export declare function configureResolve({ isEnvProduction, config }: HelperOptions): webpack.ResolveOptions;
24
29
  type Optimization = NonNullable<webpack.Configuration['optimization']>;
25
- export declare function configureOptimization({ config, isSsr }: HelperOptions): Optimization;
30
+ export declare function configureOptimization(helperOptions: HelperOptions): Optimization;
26
31
  export {};
@@ -27,6 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.webpackConfigFactory = webpackConfigFactory;
30
+ exports.rspackConfigFactory = rspackConfigFactory;
30
31
  exports.configureModuleRules = configureModuleRules;
31
32
  exports.configureResolve = configureResolve;
32
33
  exports.configureOptimization = configureOptimization;
@@ -43,6 +44,11 @@ const react_refresh_webpack_plugin_1 = __importDefault(require("@pmmmwh/react-re
43
44
  const moment_timezone_data_webpack_plugin_1 = __importDefault(require("moment-timezone-data-webpack-plugin"));
44
45
  const webpack_plugin_1 = __importDefault(require("@statoscope/webpack-plugin"));
45
46
  const circular_dependency_plugin_1 = __importDefault(require("circular-dependency-plugin"));
47
+ const core_1 = require("@rspack/core");
48
+ const rspack_manifest_plugin_1 = require("rspack-manifest-plugin");
49
+ const rspack_1 = require("./rspack");
50
+ const ts_checker_rspack_plugin_1 = require("ts-checker-rspack-plugin");
51
+ const plugin_react_refresh_1 = __importDefault(require("@rspack/plugin-react-refresh"));
46
52
  const paths_1 = __importDefault(require("../paths"));
47
53
  const babel_1 = require("../babel");
48
54
  const progress_plugin_1 = require("./progress-plugin");
@@ -53,10 +59,11 @@ const utils_2 = require("../typescript/utils");
53
59
  const node_externals_1 = require("./node-externals");
54
60
  const imagesSizeLimit = 2048;
55
61
  const fontSizeLimit = 8192;
56
- async function webpackConfigFactory(webpackMode, config, { logger, isSsr = false } = {}) {
62
+ const assetsManifestFile = 'assets-manifest.json';
63
+ function getHelperOptions({ webpackMode, config, logger, isSsr = false, }) {
57
64
  const isEnvDevelopment = webpackMode === "development" /* WebpackMode.Dev */;
58
65
  const isEnvProduction = webpackMode === "production" /* WebpackMode.Prod */;
59
- const helperOptions = {
66
+ return {
60
67
  config,
61
68
  logger,
62
69
  isEnvDevelopment,
@@ -66,6 +73,11 @@ async function webpackConfigFactory(webpackMode, config, { logger, isSsr = false
66
73
  entriesDirectory: isSsr ? paths_1.default.appSsrEntry : paths_1.default.appEntry,
67
74
  isSsr,
68
75
  };
76
+ }
77
+ async function webpackConfigFactory(options) {
78
+ const { config } = options;
79
+ const helperOptions = getHelperOptions(options);
80
+ const { isSsr, isEnvProduction } = helperOptions;
69
81
  let externals = config.externals;
70
82
  if (isSsr) {
71
83
  externals =
@@ -77,7 +89,7 @@ async function webpackConfigFactory(webpackMode, config, { logger, isSsr = false
77
89
  });
78
90
  }
79
91
  let webpackConfig = {
80
- mode: webpackMode,
92
+ mode: isEnvProduction ? 'production' : 'development',
81
93
  context: paths_1.default.app,
82
94
  bail: isEnvProduction,
83
95
  target: isSsr ? 'node' : undefined,
@@ -88,7 +100,7 @@ async function webpackConfigFactory(webpackMode, config, { logger, isSsr = false
88
100
  module: {
89
101
  rules: configureModuleRules(helperOptions),
90
102
  },
91
- plugins: configurePlugins(helperOptions),
103
+ plugins: configureWebpackPlugins(helperOptions),
92
104
  optimization: configureOptimization(helperOptions),
93
105
  externals,
94
106
  node: config.node,
@@ -106,12 +118,57 @@ async function webpackConfigFactory(webpackMode, config, { logger, isSsr = false
106
118
  },
107
119
  cache: config.cache,
108
120
  };
109
- webpackConfig = await config.webpack(webpackConfig, { configType: webpackMode, isSsr });
121
+ webpackConfig = await config.webpack(webpackConfig, {
122
+ configType: isEnvProduction ? 'production' : 'development',
123
+ isSsr,
124
+ });
110
125
  if (config.debugWebpack) {
111
126
  (0, log_config_1.logConfig)('Preview webpack config', webpackConfig);
112
127
  }
113
128
  return webpackConfig;
114
129
  }
130
+ async function rspackConfigFactory(options) {
131
+ const { config } = options;
132
+ const helperOptions = getHelperOptions(options);
133
+ const { isSsr, isEnvProduction, isEnvDevelopment } = helperOptions;
134
+ // Cache is required for lazy compilation
135
+ const cache = Boolean(config.cache) || (isEnvDevelopment && Boolean(config.lazyCompilation));
136
+ let rspackConfig = {
137
+ mode: isEnvProduction ? 'production' : 'development',
138
+ context: paths_1.default.app,
139
+ bail: isEnvProduction,
140
+ target: isSsr ? 'node' : undefined,
141
+ devtool: configureDevTool(helperOptions),
142
+ entry: configureEntry(helperOptions),
143
+ output: configureRspackOutput(helperOptions),
144
+ resolve: configureRspackResolve(helperOptions),
145
+ module: {
146
+ rules: (0, rspack_1.prepareRspackRules)(configureModuleRules(helperOptions)),
147
+ },
148
+ plugins: configureRspackPlugins(helperOptions),
149
+ optimization: configureRspackOptimization(helperOptions),
150
+ // TODO externals,
151
+ node: config.node,
152
+ watchOptions: configureWatchOptions(helperOptions),
153
+ ignoreWarnings: [/Failed to parse source map/],
154
+ infrastructureLogging: config.verbose
155
+ ? {
156
+ colors: true,
157
+ level: 'verbose',
158
+ }
159
+ : undefined,
160
+ experiments: configureRspackExperiments(helperOptions),
161
+ cache,
162
+ };
163
+ rspackConfig = await config.rspack(rspackConfig, {
164
+ configType: isEnvProduction ? 'production' : 'development',
165
+ isSsr,
166
+ });
167
+ if (config.debugWebpack) {
168
+ (0, log_config_1.logConfig)('Preview rspack config', rspackConfig);
169
+ }
170
+ return rspackConfig;
171
+ }
115
172
  function configureModuleRules(helperOptions, additionalRules = []) {
116
173
  const jsLoader = createJavaScriptLoader(helperOptions);
117
174
  return [
@@ -182,6 +239,56 @@ function configureExperiments({ config, isEnvProduction, isSsr, }) {
182
239
  lazyCompilation,
183
240
  };
184
241
  }
242
+ function configureRspackExperiments({ config, isEnvProduction, isSsr, }) {
243
+ if (isSsr) {
244
+ return config.ssr?.moduleType === 'esm' ? { outputModule: true } : undefined;
245
+ }
246
+ if (isEnvProduction) {
247
+ return undefined;
248
+ }
249
+ let lazyCompilation;
250
+ let port;
251
+ if (config.lazyCompilation) {
252
+ if (typeof config.lazyCompilation === 'object') {
253
+ port = config.lazyCompilation.port;
254
+ }
255
+ lazyCompilation = {
256
+ // Lazy compilation works without problems only with lazy imports
257
+ // See https://github.com/web-infra-dev/rspack/issues/8503
258
+ entries: false,
259
+ imports: true,
260
+ backend: {
261
+ client: require.resolve('./lazy-client.js'),
262
+ ...(port
263
+ ? {
264
+ listen: {
265
+ port,
266
+ },
267
+ }
268
+ : {}),
269
+ },
270
+ test(module) {
271
+ // make sure that lazy-client.js won't be lazy compiled)
272
+ return !module.nameForCondition().endsWith('lazy-client.js');
273
+ },
274
+ };
275
+ }
276
+ return {
277
+ cache: {
278
+ type: 'persistent',
279
+ snapshot: {
280
+ managedPaths: config.watchOptions?.watchPackages ? [] : undefined,
281
+ },
282
+ storage: {
283
+ type: 'filesystem',
284
+ directory: typeof config.cache === 'object' && 'cacheDirectory' in config.cache
285
+ ? config.cache.cacheDirectory
286
+ : undefined,
287
+ },
288
+ },
289
+ lazyCompilation,
290
+ };
291
+ }
185
292
  function configureResolve({ isEnvProduction, config }) {
186
293
  const alias = { ...config.alias };
187
294
  for (const [key, value] of Object.entries(alias)) {
@@ -203,6 +310,16 @@ function configureResolve({ isEnvProduction, config }) {
203
310
  fallback: config.fallback,
204
311
  };
205
312
  }
313
+ function configureRspackResolve(helperOptions) {
314
+ const { alias, modules, extensions, symlinks, fallback } = configureResolve(helperOptions);
315
+ return {
316
+ alias: Array.isArray(alias) ? undefined : alias,
317
+ modules,
318
+ extensions,
319
+ symlinks,
320
+ fallback: Array.isArray(fallback) ? undefined : fallback,
321
+ };
322
+ }
206
323
  function createEntryArray(entry) {
207
324
  return [require.resolve('./public-path'), entry];
208
325
  }
@@ -249,6 +366,18 @@ function configureOutput(options) {
249
366
  ...ssrOptions,
250
367
  };
251
368
  }
369
+ function configureRspackOutput(options) {
370
+ const { filename, chunkFilename, library, chunkFormat, path, pathinfo } = configureOutput(options);
371
+ return {
372
+ filename: typeof filename === 'string' ? filename : undefined,
373
+ chunkFilename: typeof chunkFilename === 'string' ? chunkFilename : undefined,
374
+ library,
375
+ chunkFormat,
376
+ path,
377
+ pathinfo,
378
+ clean: false,
379
+ };
380
+ }
252
381
  function createJavaScriptLoader({ isEnvProduction, isEnvDevelopment, configType, config, isSsr, }) {
253
382
  const plugins = [];
254
383
  if (!isSsr) {
@@ -326,7 +455,9 @@ function createWorkerRule(options) {
326
455
  loader: require.resolve('./worker/worker-loader'),
327
456
  }
328
457
  : {
329
- loader: require.resolve('worker-loader'),
458
+ loader: require.resolve(options.config.bundler === 'rspack'
459
+ ? 'worker-rspack-loader'
460
+ : 'worker-loader'),
330
461
  // currently workers located on cdn are not working properly, so we are enforcing loading workers from
331
462
  // service instead
332
463
  options: {
@@ -370,6 +501,7 @@ function createStylesRule(options) {
370
501
  };
371
502
  }
372
503
  function getCssLoaders({ isEnvDevelopment, isEnvProduction, config, isSsr }, additionalRules) {
504
+ const isRspack = config.bundler === 'rspack';
373
505
  const loaders = [];
374
506
  if (!config.transformCssWithLightningCss) {
375
507
  loaders.push({
@@ -409,11 +541,17 @@ function getCssLoaders({ isEnvDevelopment, isEnvProduction, config, isSsr }, add
409
541
  },
410
542
  });
411
543
  if (isEnvProduction) {
412
- loaders.unshift({ loader: mini_css_extract_plugin_1.default.loader, options: { emit: !isSsr } });
544
+ loaders.unshift({
545
+ loader: isRspack ? core_1.CssExtractRspackPlugin.loader : mini_css_extract_plugin_1.default.loader,
546
+ options: { emit: !isSsr },
547
+ });
413
548
  }
414
549
  if (isEnvDevelopment) {
415
550
  if (isSsr || config.ssr) {
416
- loaders.unshift({ loader: mini_css_extract_plugin_1.default.loader, options: { emit: !isSsr } });
551
+ loaders.unshift({
552
+ loader: isRspack ? core_1.CssExtractRspackPlugin.loader : mini_css_extract_plugin_1.default.loader,
553
+ options: { emit: !isSsr },
554
+ });
417
555
  }
418
556
  else {
419
557
  loaders.unshift({
@@ -567,47 +705,42 @@ function createMomentTimezoneDataPlugin(options = {}) {
567
705
  const endYear = options.endYear ?? currentYear;
568
706
  return new moment_timezone_data_webpack_plugin_1.default({ ...options, startYear, endYear });
569
707
  }
570
- function configurePlugins(options) {
571
- const { isEnvDevelopment, isEnvProduction, config, isSsr } = options;
572
- const excludeFromClean = config.excludeFromClean || [];
573
- const manifestFile = 'assets-manifest.json';
574
- const plugins = [
575
- new clean_webpack_plugin_1.CleanWebpackPlugin({
576
- verbose: config.verbose,
577
- cleanOnceBeforeBuildPatterns: [
578
- '**/*',
579
- ...(isEnvDevelopment ? ['!manifest.json'] : []),
580
- ...excludeFromClean,
581
- ],
582
- }),
583
- new webpack_manifest_plugin_1.WebpackManifestPlugin({
584
- writeToFileEmit: true,
585
- publicPath: '',
586
- }),
587
- new webpack_assets_manifest_1.default(isEnvProduction
588
- ? {
589
- entrypoints: true,
590
- output: manifestFile,
591
- }
592
- : {
593
- entrypoints: true,
594
- writeToDisk: true,
595
- output: path.resolve(options.buildDirectory, manifestFile),
596
- }),
597
- new webpack.DefinePlugin({
598
- 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
599
- 'process.env.IS_SSR': JSON.stringify(isSsr),
600
- ...config.definitions,
601
- }),
602
- ];
603
- if (options.logger) {
604
- plugins.push(new progress_plugin_1.ProgressPlugin({ logger: options.logger }));
708
+ function getDefinitions({ config, isSsr }) {
709
+ return {
710
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
711
+ 'process.env.IS_SSR': JSON.stringify(isSsr),
712
+ ...config.definitions,
713
+ };
714
+ }
715
+ function getContextReplacements({ config, isSsr }) {
716
+ const contextReplacement = config.contextReplacement || {};
717
+ if (isSsr) {
718
+ return [];
605
719
  }
606
- if (process.env.WEBPACK_PROFILE === 'true') {
607
- plugins.push(new webpack.debug.ProfilingPlugin());
720
+ const replacements = [
721
+ {
722
+ resourceRegExp: /moment[\\/]locale$/, // eslint-disable-next-line security/detect-non-literal-regexp
723
+ newResource: new RegExp(`^\\./(${(contextReplacement.locale || ['ru']).join('|')})$`),
724
+ },
725
+ {
726
+ resourceRegExp: /dayjs[\\/]locale$/,
727
+ // eslint-disable-next-line security/detect-non-literal-regexp
728
+ newResource: new RegExp(`^\\./(${(contextReplacement.locale || ['ru']).join('|')})\\.js$`),
729
+ },
730
+ ];
731
+ if (contextReplacement['highlight.js']) {
732
+ replacements.push({
733
+ resourceRegExp: /highlight\.js[\\/]lib[\\/]languages$/,
734
+ // eslint-disable-next-line security/detect-non-literal-regexp
735
+ newResource: new RegExp(`^\\./(${contextReplacement['highlight.js'].join('|')})$`),
736
+ });
608
737
  }
609
- if (config.forkTsChecker !== false) {
610
- plugins.push(new fork_ts_checker_webpack_plugin_1.default({
738
+ return replacements;
739
+ }
740
+ function getForkTsCheckerOptions({ config, }) {
741
+ return config.forkTsChecker === false
742
+ ? undefined
743
+ : {
611
744
  ...config.forkTsChecker,
612
745
  typescript: {
613
746
  typescriptPath: (0, utils_2.resolveTypescript)(),
@@ -618,8 +751,31 @@ function configurePlugins(options) {
618
751
  mode: 'write-references',
619
752
  ...config.forkTsChecker?.typescript,
620
753
  },
621
- }));
622
- }
754
+ };
755
+ }
756
+ function getCssExtractPluginOptions({ isEnvProduction }) {
757
+ return {
758
+ filename: isEnvProduction ? 'css/[name].[contenthash:8].css' : 'css/[name].css',
759
+ chunkFilename: isEnvProduction
760
+ ? 'css/[name].[contenthash:8].chunk.css'
761
+ : 'css/[name].chunk.css',
762
+ ignoreOrder: true,
763
+ };
764
+ }
765
+ function configureCommonPlugins(options) {
766
+ const { isEnvDevelopment, isEnvProduction, config, isSsr } = options;
767
+ const excludeFromClean = config.excludeFromClean || [];
768
+ const plugins = [
769
+ new clean_webpack_plugin_1.CleanWebpackPlugin({
770
+ verbose: config.verbose,
771
+ cleanOnceBeforeBuildPatterns: [
772
+ '**/*',
773
+ ...(isEnvDevelopment ? ['!manifest.json'] : []),
774
+ ...excludeFromClean,
775
+ ],
776
+ }),
777
+ ...(options.logger ? [new progress_plugin_1.ProgressPlugin({ logger: options.logger })] : []),
778
+ ];
623
779
  if (config.detectCircularDependencies) {
624
780
  let circularPluginOptions = {
625
781
  exclude: /node_modules/,
@@ -638,27 +794,6 @@ function configurePlugins(options) {
638
794
  reportFilename: 'stats.html',
639
795
  }));
640
796
  }
641
- if (config.analyzeBundle === 'statoscope') {
642
- const customStatoscopeConfig = config.statoscopeConfig || {};
643
- plugins.push(new webpack_plugin_1.default({
644
- saveReportTo: path.resolve(options.buildDirectory, 'report.html'),
645
- saveStatsTo: path.resolve(options.buildDirectory, 'stats.json'),
646
- open: false,
647
- statsOptions: {
648
- all: true,
649
- },
650
- ...customStatoscopeConfig,
651
- }));
652
- }
653
- }
654
- if (isEnvProduction || isSsr || config.ssr) {
655
- plugins.push(new mini_css_extract_plugin_1.default({
656
- filename: isEnvProduction ? 'css/[name].[contenthash:8].css' : 'css/[name].css',
657
- chunkFilename: isEnvProduction
658
- ? 'css/[name].[contenthash:8].chunk.css'
659
- : 'css/[name].chunk.css',
660
- ignoreOrder: true,
661
- }));
662
797
  }
663
798
  if (!isSsr) {
664
799
  if (config.monaco) {
@@ -671,84 +806,130 @@ function configurePlugins(options) {
671
806
  publicPath: path.normalize(config.publicPathPrefix + '/build/'),
672
807
  }));
673
808
  }
674
- const contextReplacement = config.contextReplacement || {};
675
809
  plugins.push(createMomentTimezoneDataPlugin(config.momentTz));
676
- plugins.push(new webpack.ContextReplacementPlugin(/moment[\\/]locale$/,
677
- // eslint-disable-next-line security/detect-non-literal-regexp
678
- new RegExp(`^\\./(${(contextReplacement.locale || ['ru']).join('|')})$`)));
679
- plugins.push(new webpack.ContextReplacementPlugin(/dayjs[\\/]locale$/,
680
- // eslint-disable-next-line security/detect-non-literal-regexp
681
- new RegExp(`^\\./(${(contextReplacement.locale || ['ru']).join('|')})\\.js$`)));
682
- if (contextReplacement['highlight.js']) {
683
- plugins.push(new webpack.ContextReplacementPlugin(/highlight\.js[\\/]lib[\\/]languages$/,
684
- // eslint-disable-next-line security/detect-non-literal-regexp
685
- new RegExp(`^\\./(${contextReplacement['highlight.js'].join('|')})$`)));
810
+ }
811
+ if (isEnvProduction) {
812
+ if (config.sentryConfig) {
813
+ const sentryPlugin = require('@sentry/webpack-plugin').sentryWebpackPlugin;
814
+ plugins.push(sentryPlugin({ ...config.sentryConfig }));
686
815
  }
816
+ }
817
+ if (config.cdn) {
818
+ plugins.push(...(0, s3_upload_1.createS3UploadPlugins)(config, options.logger));
819
+ }
820
+ return plugins;
821
+ }
822
+ function configureWebpackPlugins(options) {
823
+ const { isEnvDevelopment, isEnvProduction, config, isSsr } = options;
824
+ const forkTsCheckerOptions = getForkTsCheckerOptions(options);
825
+ const webpackPlugins = [
826
+ ...configureCommonPlugins(options),
827
+ new webpack.DefinePlugin(getDefinitions(options)),
828
+ new webpack_manifest_plugin_1.WebpackManifestPlugin({
829
+ writeToFileEmit: true,
830
+ publicPath: '',
831
+ }),
832
+ new webpack_assets_manifest_1.default(isEnvProduction
833
+ ? {
834
+ entrypoints: true,
835
+ output: assetsManifestFile,
836
+ }
837
+ : {
838
+ entrypoints: true,
839
+ writeToDisk: true,
840
+ output: path.resolve(options.buildDirectory, assetsManifestFile),
841
+ }),
842
+ ...(process.env.WEBPACK_PROFILE === 'true' ? [new webpack.debug.ProfilingPlugin()] : []),
843
+ ...(forkTsCheckerOptions ? [new fork_ts_checker_webpack_plugin_1.default(forkTsCheckerOptions)] : []),
844
+ ];
845
+ if (isEnvProduction || isSsr || config.ssr) {
846
+ webpackPlugins.push(new mini_css_extract_plugin_1.default(getCssExtractPluginOptions(options)));
847
+ }
848
+ if (isEnvProduction) {
849
+ if (config.analyzeBundle === 'statoscope') {
850
+ const customStatoscopeConfig = config.statoscopeConfig || {};
851
+ webpackPlugins.push(new webpack_plugin_1.default({
852
+ saveReportTo: path.resolve(options.buildDirectory, 'report.html'),
853
+ saveStatsTo: path.resolve(options.buildDirectory, 'stats.json'),
854
+ open: false,
855
+ statsOptions: {
856
+ all: true,
857
+ },
858
+ ...customStatoscopeConfig,
859
+ }));
860
+ }
861
+ }
862
+ if (!isSsr) {
863
+ const contextReplacements = getContextReplacements(options);
864
+ contextReplacements.forEach(({ resourceRegExp, newResource }) => webpackPlugins.push(new webpack.ContextReplacementPlugin(resourceRegExp, newResource)));
687
865
  if (isEnvDevelopment && config.reactRefresh !== false) {
688
866
  const { webSocketPath = path.normalize(`/${config.publicPathPrefix}/build/sockjs-node`), } = config.devServer || {};
689
- plugins.push(new react_refresh_webpack_plugin_1.default(config.reactRefresh({
867
+ const reactRefreshConfig = config.reactRefresh({
690
868
  overlay: { sockPath: webSocketPath },
691
869
  exclude: [/node_modules/, /\.worker\.[jt]sx?$/],
692
- })));
870
+ });
871
+ webpackPlugins.push(new react_refresh_webpack_plugin_1.default(reactRefreshConfig));
693
872
  }
694
873
  if (config.polyfill?.process) {
695
- plugins.push(new webpack.ProvidePlugin({ process: 'process/browser.js' }));
874
+ webpackPlugins.push(new webpack.ProvidePlugin({ process: 'process/browser.js' }));
696
875
  }
697
- if (isEnvProduction) {
698
- if (config.sentryConfig) {
699
- const sentryPlugin = require('@sentry/webpack-plugin').sentryWebpackPlugin;
700
- plugins.push(sentryPlugin({ ...config.sentryConfig }));
701
- }
876
+ }
877
+ return webpackPlugins;
878
+ }
879
+ function configureRspackPlugins(options) {
880
+ const { isEnvDevelopment, isEnvProduction, config, isSsr } = options;
881
+ const forkTsCheckerOptions = getForkTsCheckerOptions(options);
882
+ const rspackPlugins = [
883
+ ...configureCommonPlugins(options),
884
+ new core_1.rspack.DefinePlugin(getDefinitions(options)),
885
+ new rspack_manifest_plugin_1.RspackManifestPlugin({
886
+ fileName: isEnvProduction
887
+ ? assetsManifestFile
888
+ : path.resolve(paths_1.default.appBuild, assetsManifestFile),
889
+ writeToFileEmit: true,
890
+ useLegacyEmit: true,
891
+ publicPath: '',
892
+ generate: rspack_1.generateAssetsManifest,
893
+ }),
894
+ ...(forkTsCheckerOptions ? [new ts_checker_rspack_plugin_1.TsCheckerRspackPlugin(forkTsCheckerOptions)] : []),
895
+ ];
896
+ if (isEnvProduction || isSsr || config.ssr) {
897
+ rspackPlugins.push(new core_1.CssExtractRspackPlugin(getCssExtractPluginOptions(options)));
898
+ }
899
+ // TODO add rsdoctor plugin
900
+ if (!isSsr) {
901
+ const contextReplacements = getContextReplacements(options);
902
+ contextReplacements.forEach(({ resourceRegExp, newResource }) => rspackPlugins.push(new core_1.rspack.ContextReplacementPlugin(resourceRegExp, newResource)));
903
+ if (isEnvDevelopment && config.reactRefresh !== false) {
904
+ const { webSocketPath = path.normalize(`/${config.publicPathPrefix}/build/sockjs-node`), } = config.devServer || {};
905
+ const { overlay, ...reactRefreshConfig } = config.reactRefresh({
906
+ overlay: { sockPath: webSocketPath },
907
+ exclude: [/node_modules/, /\.worker\.[jt]sx?$/],
908
+ });
909
+ rspackPlugins.push(new plugin_react_refresh_1.default({
910
+ ...reactRefreshConfig,
911
+ overlay: typeof overlay === 'object'
912
+ ? {
913
+ entry: typeof overlay.entry === 'string' ? overlay.entry : undefined,
914
+ module: typeof overlay.module === 'string'
915
+ ? overlay.module
916
+ : undefined,
917
+ sockPath: overlay.sockPath,
918
+ sockHost: overlay.sockHost,
919
+ sockPort: overlay.sockPort?.toString(),
920
+ sockProtocol: overlay.sockProtocol,
921
+ sockIntegration: overlay.sockIntegration === 'wds' ? 'wds' : undefined,
922
+ }
923
+ : undefined,
924
+ }));
702
925
  }
703
- if (config.cdn) {
704
- let credentialsGlobal;
705
- if (process.env.FRONTEND_S3_ACCESS_KEY_ID &&
706
- process.env.FRONTEND_S3_SECRET_ACCESS_KEY) {
707
- credentialsGlobal = {
708
- accessKeyId: process.env.FRONTEND_S3_ACCESS_KEY_ID,
709
- secretAccessKey: process.env.FRONTEND_S3_SECRET_ACCESS_KEY,
710
- };
711
- }
712
- const cdns = Array.isArray(config.cdn) ? config.cdn : [config.cdn];
713
- for (let index = 0; index < cdns.length; index++) {
714
- const cdn = cdns[index];
715
- if (!cdn) {
716
- continue;
717
- }
718
- let credentials = credentialsGlobal;
719
- const accessKeyId = process.env[`FRONTEND_S3_ACCESS_KEY_ID_${index}`];
720
- const secretAccessKey = process.env[`FRONTEND_S3_SECRET_ACCESS_KEY_${index}`];
721
- if (accessKeyId && secretAccessKey) {
722
- credentials = {
723
- accessKeyId,
724
- secretAccessKey,
725
- };
726
- }
727
- plugins.push(new s3_upload_1.S3UploadPlugin({
728
- exclude: config.hiddenSourceMap ? /\.map$/ : undefined,
729
- compress: cdn.compress,
730
- s3ClientOptions: {
731
- region: cdn.region,
732
- endpoint: cdn.endpoint,
733
- credentials,
734
- },
735
- s3UploadOptions: {
736
- bucket: cdn.bucket,
737
- targetPath: cdn.prefix,
738
- cacheControl: cdn.cacheControl,
739
- },
740
- additionalPattern: cdn.additionalPattern,
741
- logger: options.logger,
742
- }));
743
- }
926
+ if (config.polyfill?.process) {
927
+ rspackPlugins.push(new core_1.rspack.ProvidePlugin({ process: 'process/browser.js' }));
744
928
  }
745
929
  }
746
- return plugins;
930
+ return rspackPlugins;
747
931
  }
748
- function configureOptimization({ config, isSsr }) {
749
- if (isSsr) {
750
- return {};
751
- }
932
+ function getOptimizationSplitChunks({ config }) {
752
933
  const configVendors = config.vendors ?? [];
753
934
  let vendorsList = [
754
935
  'react',
@@ -770,28 +951,35 @@ function configureOptimization({ config, isSsr }) {
770
951
  vendorsList = vendorsList.concat(configVendors);
771
952
  }
772
953
  const useVendorsList = vendorsList.length > 0;
773
- const optimization = {
774
- splitChunks: {
775
- chunks: 'all',
776
- cacheGroups: {
777
- ...(useVendorsList
778
- ? {
779
- defaultVendors: {
780
- name: 'vendors',
781
- // eslint-disable-next-line security/detect-non-literal-regexp
782
- test: new RegExp(`([\\\\/])node_modules\\1(${vendorsList.join('|')})\\1`),
783
- priority: Infinity,
784
- },
785
- }
786
- : undefined),
787
- css: {
788
- type: 'css/mini-extract',
789
- enforce: true,
790
- minChunks: 2,
791
- reuseExistingChunk: true,
792
- },
954
+ return {
955
+ chunks: 'all',
956
+ cacheGroups: {
957
+ ...(useVendorsList
958
+ ? {
959
+ defaultVendors: {
960
+ name: 'vendors',
961
+ // eslint-disable-next-line security/detect-non-literal-regexp
962
+ test: new RegExp(`([\\\\/])node_modules\\1(${vendorsList.join('|')})\\1`),
963
+ priority: Infinity,
964
+ },
965
+ }
966
+ : undefined),
967
+ css: {
968
+ type: 'css/mini-extract',
969
+ enforce: true,
970
+ minChunks: 2,
971
+ reuseExistingChunk: true,
793
972
  },
794
973
  },
974
+ };
975
+ }
976
+ function configureOptimization(helperOptions) {
977
+ const { config, isSsr } = helperOptions;
978
+ if (isSsr) {
979
+ return {};
980
+ }
981
+ const optimization = {
982
+ splitChunks: getOptimizationSplitChunks(helperOptions),
795
983
  runtimeChunk: 'single',
796
984
  minimizer: [
797
985
  (compiler) => {
@@ -841,3 +1029,33 @@ function configureOptimization({ config, isSsr }) {
841
1029
  };
842
1030
  return optimization;
843
1031
  }
1032
+ function configureRspackOptimization(helperOptions) {
1033
+ const { config, isSsr } = helperOptions;
1034
+ if (isSsr) {
1035
+ return {};
1036
+ }
1037
+ const optimization = {
1038
+ splitChunks: getOptimizationSplitChunks(helperOptions),
1039
+ runtimeChunk: 'single',
1040
+ minimizer: [
1041
+ new core_1.rspack.SwcJsMinimizerRspackPlugin({
1042
+ minimizerOptions: {
1043
+ mangle: !config.reactProfiling,
1044
+ compress: {
1045
+ passes: 2,
1046
+ },
1047
+ format: {
1048
+ safari10: config.safari10,
1049
+ },
1050
+ },
1051
+ }),
1052
+ new core_1.rspack.LightningCssMinimizerRspackPlugin({
1053
+ minimizerOptions: {
1054
+ // Plugin will read the browserslist itself and generate targets
1055
+ targets: [],
1056
+ },
1057
+ }),
1058
+ ],
1059
+ };
1060
+ return optimization;
1061
+ }
@@ -0,0 +1,7 @@
1
+ import { ManifestPluginOptions } from 'rspack-manifest-plugin';
2
+ import type { RuleSetRule as WebpackRuleSetRule } from 'webpack';
3
+ import type { Configuration, RuleSetRule as RspackRuleSetRule } from '@rspack/core';
4
+ import type { Logger } from '../logger';
5
+ export declare function clearCacheDirectory(config: Configuration, logger: Logger): void;
6
+ export declare const generateAssetsManifest: ManifestPluginOptions['generate'];
7
+ export declare function prepareRspackRules(webpackRules: (undefined | null | false | '' | 0 | WebpackRuleSetRule | '...')[]): (RspackRuleSetRule | '...')[];
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.generateAssetsManifest = void 0;
30
+ exports.clearCacheDirectory = clearCacheDirectory;
31
+ exports.prepareRspackRules = prepareRspackRules;
32
+ const fs = __importStar(require("node:fs"));
33
+ const path = __importStar(require("node:path"));
34
+ const paths_1 = __importDefault(require("../../common/paths"));
35
+ function clearCacheDirectory(config, logger) {
36
+ if (!config.cache) {
37
+ return;
38
+ }
39
+ let cacheDirectory = path.join(paths_1.default.appNodeModules, '.cache/rspack');
40
+ if (typeof config.experiments?.cache === 'object' &&
41
+ config.experiments.cache.type === 'persistent' &&
42
+ config.experiments.cache.storage?.directory) {
43
+ cacheDirectory = config.experiments.cache.storage?.directory;
44
+ }
45
+ if (fs.existsSync(cacheDirectory)) {
46
+ fs.rmdirSync(cacheDirectory, { recursive: true });
47
+ logger.message(`Rspack cache ${cacheDirectory} successfully cleared`);
48
+ }
49
+ }
50
+ const generateAssetsManifest = (seed, files, entries) => {
51
+ const manifestFiles = files.reduce((manifest, file) => {
52
+ manifest[file.name] = file.path;
53
+ return manifest;
54
+ }, seed);
55
+ const entrypoints = Object.keys(entries).reduce((previous, name) => {
56
+ return {
57
+ ...previous,
58
+ [name]: {
59
+ assets: {
60
+ js: entries[name].filter((file) => file.endsWith('.js')),
61
+ css: entries[name].filter((file) => file.endsWith('.css')),
62
+ },
63
+ },
64
+ };
65
+ }, {});
66
+ return {
67
+ files: manifestFiles,
68
+ entrypoints,
69
+ };
70
+ };
71
+ exports.generateAssetsManifest = generateAssetsManifest;
72
+ function prepareRspackUse(webpackUse) {
73
+ if (typeof webpackUse === 'string') {
74
+ if (webpackUse === 'swc-loader') {
75
+ return 'builtin:swc-loader';
76
+ }
77
+ return webpackUse;
78
+ }
79
+ if (Array.isArray(webpackUse)) {
80
+ for (const item of webpackUse) {
81
+ if (item) {
82
+ prepareRspackUse(item);
83
+ }
84
+ }
85
+ }
86
+ return webpackUse;
87
+ }
88
+ function prepareRspackRules(webpackRules) {
89
+ const rspackRules = [];
90
+ for (const webpackRule of webpackRules) {
91
+ if (!webpackRule) {
92
+ continue;
93
+ }
94
+ if (typeof webpackRule === 'string') {
95
+ rspackRules.push(webpackRule);
96
+ continue;
97
+ }
98
+ const rspackRule = webpackRule;
99
+ if (webpackRule.oneOf) {
100
+ rspackRule.oneOf = prepareRspackRules(webpackRule.oneOf);
101
+ }
102
+ if (webpackRule.rules) {
103
+ rspackRule.rules = prepareRspackRules(webpackRule.rules);
104
+ }
105
+ if (webpackRule.use) {
106
+ rspackRule.use = prepareRspackUse(webpackRule.use);
107
+ }
108
+ rspackRules.push(rspackRule);
109
+ }
110
+ return rspackRules;
111
+ }
@@ -5,8 +5,8 @@ export declare function createCli(argv: string[]): {
5
5
  cdn: string | undefined;
6
6
  env: string[] | undefined;
7
7
  target: "client" | "server" | undefined;
8
- inspect: number | undefined;
9
8
  c: unknown;
9
+ inspect: number | undefined;
10
10
  inspectBrk: number | undefined;
11
11
  "inspect-brk": number | undefined;
12
12
  entryFilter: string[] | undefined;
@@ -33,8 +33,8 @@ export declare function createCli(argv: string[]): {
33
33
  cdn: string | undefined;
34
34
  env: string[] | undefined;
35
35
  target: "client" | "server" | undefined;
36
- inspect: number | undefined;
37
36
  c: unknown;
37
+ inspect: number | undefined;
38
38
  inspectBrk: number | undefined;
39
39
  "inspect-brk": number | undefined;
40
40
  entryFilter: string[] | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/app-builder",
3
- "version": "0.15.0",
3
+ "version": "0.15.1-beta.1",
4
4
  "description": "Develop and build your React client-server projects, powered by typescript and webpack",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -70,6 +70,9 @@
70
70
  "@babel/runtime": "^7.26.0",
71
71
  "@okikio/sharedworker": "^1.0.7",
72
72
  "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
73
+ "@rspack/core": "^1.2.2",
74
+ "@rspack/dev-server": "^1.0.10",
75
+ "@rspack/plugin-react-refresh": "^1.0.0",
73
76
  "@statoscope/webpack-plugin": "^5.28.2",
74
77
  "@svgr/core": "^8.1.0",
75
78
  "@svgr/plugin-jsx": "^8.1.0",
@@ -110,6 +113,7 @@
110
113
  "react-refresh": "^0.14.2",
111
114
  "resolve-url-loader": "^5.0.0",
112
115
  "rimraf": "^5.0.7",
116
+ "rspack-manifest-plugin": "^5.0.1",
113
117
  "sass": "^1.79.0",
114
118
  "sass-loader": "^16.0.0",
115
119
  "semver": "^7.6.3",
@@ -119,6 +123,7 @@
119
123
  "style-loader": "^4.0.0",
120
124
  "svgo": "^3.3.2",
121
125
  "terser-webpack-plugin": "5.3.10",
126
+ "ts-checker-rspack-plugin": "^1.1.1",
122
127
  "ts-node": "10.9.2",
123
128
  "tslib": "^2.6.2",
124
129
  "typescript": "~5.6.0",
@@ -128,6 +133,7 @@
128
133
  "webpack-dev-server": "^5.1.0",
129
134
  "webpack-manifest-plugin": "^5.0.0",
130
135
  "worker-loader": "^3.0.8",
136
+ "worker-rspack-loader": "^3.1.2",
131
137
  "yargs": "^17.7.2"
132
138
  },
133
139
  "devDependencies": {