@gravity-ui/app-builder 0.7.1 → 0.8.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.
package/README.md CHANGED
@@ -192,6 +192,8 @@ With this `{rootDir}/src/ui/tsconfig.json`:
192
192
  - `forkTsCheker` (`false | ForkTsCheckerWebpackPluginOptions`) - config for ForkTsCheckerWebpackPlugin [more](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#options). If `false`, ForkTsCheckerWebpackPlugin will be disabled.
193
193
  - `cache` (`boolean | FileCacheOptions | MemoryCacheOptions`) — Cache the generated webpack modules and chunks to improve build speed. [more](https://webpack.js.org/configuration/cache/)
194
194
  - `babelCacheDirectory` (`boolean | string`) — Set directory for babel-loader cache (`default: node_modules/.cache/babel-loader``)
195
+ - `babel` (`(config: babel.TransformOptions, options: {configType: 'development' | 'production'}) => babel.TransformOptions | Promise<babel.TransformOptions>`) - Allow override the default babel transform options.
196
+ - `webpack` (`(config: webpack.Configuration, options: {configType: 'development' | 'production'}) => webpack.Configuration | Promise<webpack.Configuration>`) - Allow override the default configuration.
195
197
 
196
198
  ##### Dev build
197
199
 
@@ -46,7 +46,7 @@ async function buildWebpackServer(config) {
46
46
  const logger = new logger_1.Logger('webpack', config.verbose);
47
47
  const { webSocketPath = path.normalize(`/${config.client.publicPathPrefix}/build/sockjs-node`), ...devServer } = config.client.devServer || {};
48
48
  const normalizedConfig = { ...config.client, devServer: { ...devServer, webSocketPath } };
49
- const webpackConfig = (0, config_1.webpackConfigFactory)("development" /* WebpackMode.Dev */, normalizedConfig, { logger });
49
+ const webpackConfig = await (0, config_1.webpackConfigFactory)("development" /* WebpackMode.Dev */, normalizedConfig, { logger });
50
50
  const options = {
51
51
  static: path.resolve(paths_1.default.appDist, 'public'),
52
52
  devMiddleware: {
@@ -129,6 +129,7 @@ async function getProjectConfig(command, { env, storybook, ...argv }) {
129
129
  ...config.client,
130
130
  ...omitUndefined(client),
131
131
  ...(argv.cdn === 'false' ? { cdn: undefined } : undefined),
132
+ ...(argv.debugWebpack ? { debugWebpack: argv.debugWebpack } : undefined),
132
133
  },
133
134
  server: {
134
135
  ...config.server,
@@ -168,6 +169,8 @@ async function normalizeClientConfig(client, mode) {
168
169
  client.hiddenSourceMap = client.hiddenSourceMap ?? true;
169
170
  client.svgr = client.svgr ?? {};
170
171
  client.entryFilter = client.entryFilter && splitPaths(client.entryFilter);
172
+ client.webpack = typeof client.webpack === 'function' ? client.webpack : (config) => config;
173
+ client.babel = typeof client.babel === 'function' ? client.babel : (config) => config;
171
174
  if (mode === 'dev') {
172
175
  if (client.lazyCompilation) {
173
176
  if (client.lazyCompilation === true) {
@@ -75,6 +75,7 @@ function compileToCjs(code, file, inputSourceMap, sourceDir = paths_1.default.sr
75
75
  fs.mkdirSync(compiledCjsDir, { recursive: true });
76
76
  babel.transform(code, {
77
77
  babelrc: false,
78
+ configFile: false,
78
79
  filename: sourceFile,
79
80
  plugins: [
80
81
  require.resolve('@babel/plugin-transform-modules-commonjs'),
@@ -194,6 +195,7 @@ function buildLibrary(config) {
194
195
  fs.mkdirSync(compiledDir, { recursive: true });
195
196
  babel.transform(source, {
196
197
  babelrc: false,
198
+ configFile: false,
197
199
  filename: sourceFile,
198
200
  presets: [(0, babel_1.babelPreset)(config.lib)],
199
201
  plugins: [
@@ -287,6 +289,7 @@ function buildLibrary(config) {
287
289
  });
288
290
  babel.transform(component, {
289
291
  babelrc: false,
292
+ configFile: false,
290
293
  filename: iconFile,
291
294
  presets: [(0, babel_1.babelPreset)(config.lib)],
292
295
  sourceMaps: true,
@@ -0,0 +1 @@
1
+ export declare function logConfig(caption: string, config: unknown): void;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logConfig = void 0;
4
+ const colors_1 = require("./colors");
5
+ function logConfig(caption, config) {
6
+ console.log(colors_1.colors.cyan(caption));
7
+ console.dir(config, { depth: Infinity });
8
+ }
9
+ exports.logConfig = logConfig;
@@ -3,12 +3,14 @@ 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 * as Babel from '@babel/core';
6
7
  import type { ServerConfiguration } from 'webpack-dev-server';
7
8
  import type { Options as CircularDependenciesOptions } from 'circular-dependency-plugin';
8
9
  import type { Config as SvgrConfig } from '@svgr/core';
9
10
  import type { ForkTsCheckerWebpackPluginOptions } from 'fork-ts-checker-webpack-plugin/lib/plugin-options';
10
11
  import type { Options as StatoscopeOptions } from '@statoscope/webpack-plugin';
11
12
  import type { SentryWebpackPluginOptions } from '@sentry/webpack-plugin';
13
+ import type { WebpackMode } from '../webpack/config';
12
14
  export interface Entities<T> {
13
15
  data: Record<string, T>;
14
16
  keys: string[];
@@ -171,6 +173,18 @@ export interface ClientConfig {
171
173
  /** Use [Lighting CSS](https://lightningcss.dev) to transform and minimize css instead of PostCSS and cssnano*/
172
174
  transformCssWithLightningCss?: boolean;
173
175
  sentryConfig?: SentryWebpackPluginOptions;
176
+ /**
177
+ * Modify or return a custom Webpack config.
178
+ */
179
+ webpack?: (config: Configuration, options: {
180
+ configType: `${WebpackMode}`;
181
+ }) => Configuration | Promise<Configuration>;
182
+ /**
183
+ * Modify or return a custom Babel config.
184
+ */
185
+ babel?: (config: Babel.TransformOptions, options: {
186
+ configType: `${WebpackMode}`;
187
+ }) => Babel.TransformOptions | Promise<Babel.TransformOptions>;
174
188
  }
175
189
  interface CdnUploadConfig {
176
190
  bucket: string;
@@ -207,6 +221,13 @@ export type NormalizedClientConfig = Omit<ClientConfig, 'publicPathPrefix' | 'hi
207
221
  server: ServerConfiguration;
208
222
  };
209
223
  verbose?: boolean;
224
+ webpack: (config: Configuration, options: {
225
+ configType: `${WebpackMode}`;
226
+ }) => Configuration | Promise<Configuration>;
227
+ debugWebpack?: boolean;
228
+ babel: (config: Babel.TransformOptions, options: {
229
+ configType: `${WebpackMode}`;
230
+ }) => Babel.TransformOptions | Promise<Babel.TransformOptions>;
210
231
  };
211
232
  export type NormalizedServerConfig = Omit<ServerConfig, 'serverPort'> & {
212
233
  serverPort?: number;
@@ -8,11 +8,11 @@ const webpack_1 = __importDefault(require("webpack"));
8
8
  const logger_1 = require("../logger");
9
9
  const config_1 = require("./config");
10
10
  const utils_1 = require("./utils");
11
- function webpackCompile(config) {
11
+ async function webpackCompile(config) {
12
12
  const logger = new logger_1.Logger('webpack', config.verbose);
13
+ const webpackConfig = await (0, config_1.webpackConfigFactory)("production" /* WebpackMode.Prod */, config, { logger });
14
+ logger.verbose('Config created');
13
15
  return new Promise((resolve) => {
14
- const webpackConfig = (0, config_1.webpackConfigFactory)("production" /* WebpackMode.Prod */, config, { logger });
15
- logger.verbose('Config created');
16
16
  const compiler = (0, webpack_1.default)(webpackConfig, (0, utils_1.webpackCompilerHandlerFactory)(logger, async () => {
17
17
  resolve();
18
18
  }));
@@ -6,6 +6,7 @@ export interface HelperOptions {
6
6
  logger?: Logger;
7
7
  isEnvDevelopment: boolean;
8
8
  isEnvProduction: boolean;
9
+ configType: `${WebpackMode}`;
9
10
  updateIncludes?: (values: string[], options?: {
10
11
  includeRootAssets?: boolean;
11
12
  includeRootStyles?: boolean;
@@ -18,6 +19,6 @@ export declare const enum WebpackMode {
18
19
  }
19
20
  export declare function webpackConfigFactory(webpackMode: WebpackMode, config: NormalizedClientConfig, { logger }?: {
20
21
  logger?: Logger;
21
- }): webpack.Configuration;
22
+ }): Promise<webpack.Configuration>;
22
23
  export declare function configureModuleRules(helperOptions: HelperOptions): webpack.RuleSetRule[];
23
24
  export declare function configureResolve({ isEnvProduction, config, tsLinkedPackages, }: HelperOptions): webpack.ResolveOptions;
@@ -49,9 +49,10 @@ const babel_1 = require("../babel");
49
49
  const progress_plugin_1 = require("./progress-plugin");
50
50
  const utils_1 = require("./utils");
51
51
  const s3_upload_1 = require("../s3-upload");
52
+ const log_config_1 = require("../logger/log-config");
52
53
  const imagesSizeLimit = 2048;
53
54
  const fontSizeLimit = 8192;
54
- function webpackConfigFactory(webpackMode, config, { logger } = {}) {
55
+ async function webpackConfigFactory(webpackMode, config, { logger } = {}) {
55
56
  const isEnvDevelopment = webpackMode === "development" /* WebpackMode.Dev */;
56
57
  const isEnvProduction = webpackMode === "production" /* WebpackMode.Prod */;
57
58
  const { updateIncludes, tsLinkedPackages } = updateIncludesFactory();
@@ -62,8 +63,9 @@ function webpackConfigFactory(webpackMode, config, { logger } = {}) {
62
63
  isEnvProduction,
63
64
  updateIncludes,
64
65
  tsLinkedPackages,
66
+ configType: webpackMode,
65
67
  };
66
- return {
68
+ let webpackConfig = {
67
69
  mode: webpackMode,
68
70
  context: paths_1.default.app,
69
71
  bail: isEnvProduction,
@@ -92,6 +94,11 @@ function webpackConfigFactory(webpackMode, config, { logger } = {}) {
92
94
  },
93
95
  cache: config.cache,
94
96
  };
97
+ webpackConfig = await config.webpack(webpackConfig, { configType: webpackMode });
98
+ if (config.debugWebpack) {
99
+ (0, log_config_1.logConfig)('Preview webpack config', webpackConfig);
100
+ }
101
+ return webpackConfig;
95
102
  }
96
103
  exports.webpackConfigFactory = webpackConfigFactory;
97
104
  function configureModuleRules(helperOptions) {
@@ -253,35 +260,41 @@ function configureOutput({ isEnvDevelopment, ...rest }) {
253
260
  pathinfo: isEnvDevelopment,
254
261
  };
255
262
  }
256
- function createJavaScriptLoader({ isEnvProduction, isEnvDevelopment, config, }) {
263
+ function createJavaScriptLoader({ isEnvProduction, isEnvDevelopment, configType, config, }) {
264
+ const plugins = [];
265
+ if (isEnvDevelopment && !config.disableReactRefresh) {
266
+ plugins.push([
267
+ require.resolve('react-refresh/babel'),
268
+ config.devServer?.webSocketPath
269
+ ? {
270
+ overlay: {
271
+ sockPath: config.devServer.webSocketPath,
272
+ },
273
+ }
274
+ : undefined,
275
+ ]);
276
+ }
277
+ if (isEnvProduction) {
278
+ plugins.push([
279
+ require.resolve('babel-plugin-import'),
280
+ { libraryName: 'lodash', libraryDirectory: '', camel2DashComponentName: false },
281
+ ]);
282
+ }
283
+ const transformOptions = config.babel({
284
+ presets: [(0, babel_1.babelPreset)(config)],
285
+ plugins,
286
+ }, { configType });
257
287
  return {
258
288
  loader: require.resolve('babel-loader'),
259
289
  options: {
290
+ sourceType: 'unambiguous',
291
+ ...transformOptions,
260
292
  babelrc: false,
261
293
  configFile: false,
262
- presets: [(0, babel_1.babelPreset)(config)],
263
- plugins: [
264
- isEnvDevelopment &&
265
- !config.disableReactRefresh && [
266
- require.resolve('react-refresh/babel'),
267
- config.devServer?.webSocketPath
268
- ? {
269
- overlay: {
270
- sockPath: config.devServer.webSocketPath,
271
- },
272
- }
273
- : undefined,
274
- ],
275
- isEnvProduction && [
276
- require.resolve('babel-plugin-import'),
277
- { libraryName: 'lodash', libraryDirectory: '', camel2DashComponentName: false },
278
- ],
279
- ].filter(Boolean),
280
- sourceType: 'unambiguous',
281
- cacheDirectory: config.babelCacheDirectory ? config.babelCacheDirectory : true,
282
- cacheCompression: isEnvProduction,
283
294
  compact: isEnvProduction,
284
- sourceMap: !config.disableSourceMapGeneration,
295
+ sourceMaps: !config.disableSourceMapGeneration,
296
+ cacheCompression: isEnvProduction,
297
+ cacheDirectory: config.babelCacheDirectory ? config.babelCacheDirectory : true,
285
298
  },
286
299
  };
287
300
  }
@@ -333,16 +346,12 @@ function createWorkerRule(options) {
333
346
  ],
334
347
  };
335
348
  }
336
- function createSassStylesRule({ isEnvDevelopment, isEnvProduction, config, }) {
337
- const loaders = getCssLoaders({
338
- isEnvDevelopment,
339
- isEnvProduction,
340
- config,
341
- });
349
+ function createSassStylesRule(options) {
350
+ const loaders = getCssLoaders(options);
342
351
  loaders.push({
343
352
  loader: require.resolve('resolve-url-loader'),
344
353
  options: {
345
- sourceMap: !config.disableSourceMapGeneration,
354
+ sourceMap: !options.config.disableSourceMapGeneration,
346
355
  },
347
356
  });
348
357
  loaders.push({
@@ -356,19 +365,15 @@ function createSassStylesRule({ isEnvDevelopment, isEnvProduction, config, }) {
356
365
  });
357
366
  return {
358
367
  test: /\.scss$/,
359
- sideEffects: isEnvProduction ? true : undefined,
368
+ sideEffects: options.isEnvProduction ? true : undefined,
360
369
  use: loaders,
361
370
  };
362
371
  }
363
- function createStylesRule({ isEnvDevelopment, isEnvProduction, config, }) {
364
- const loaders = getCssLoaders({
365
- isEnvDevelopment,
366
- isEnvProduction,
367
- config,
368
- });
372
+ function createStylesRule(options) {
373
+ const loaders = getCssLoaders(options);
369
374
  return {
370
375
  test: /\.css$/,
371
- sideEffects: isEnvProduction ? true : undefined,
376
+ sideEffects: options.isEnvProduction ? true : undefined,
372
377
  use: loaders,
373
378
  };
374
379
  }
@@ -600,7 +605,7 @@ function configurePlugins(options) {
600
605
  const { webSocketPath = path.normalize(`/${config.publicPathPrefix}/build/sockjs-node`) } = config.devServer || {};
601
606
  plugins.push(new react_refresh_webpack_plugin_1.default({
602
607
  overlay: { sockPath: webSocketPath },
603
- exclude: /\.worker\.[jt]sx?$/,
608
+ exclude: [/node_modules/, /\.worker\.[jt]sx?$/],
604
609
  }));
605
610
  }
606
611
  if (config.detectCircularDependencies) {
@@ -88,6 +88,7 @@ async function configureWebpackConfigForStorybook(mode, userConfig = {}) {
88
88
  isEnvDevelopment,
89
89
  isEnvProduction,
90
90
  config: config.client,
91
+ configType: mode,
91
92
  };
92
93
  return {
93
94
  module: {
@@ -3,13 +3,16 @@ export declare function createCli(argv: string[]): {
3
3
  [x: string]: unknown;
4
4
  verbose: boolean | undefined;
5
5
  c: unknown;
6
- inspect: number | undefined;
7
- target: "client" | "server" | undefined;
6
+ cdn: string | undefined;
8
7
  env: string[] | undefined;
8
+ target: "client" | "server" | undefined;
9
+ inspect: number | undefined;
9
10
  inspectBrk: number | undefined;
10
11
  "inspect-brk": number | undefined;
11
12
  entryFilter: string[] | undefined;
12
13
  "entry-filter": string[] | undefined;
14
+ disableForkTsChecker: boolean | undefined;
15
+ "disable-fork-ts-checker": boolean | undefined;
13
16
  disableReactRefresh: boolean | undefined;
14
17
  "disable-react-refresh": boolean | undefined;
15
18
  lazyCompilation: boolean | undefined;
@@ -18,24 +21,26 @@ export declare function createCli(argv: string[]): {
18
21
  "react-profiling": boolean | undefined;
19
22
  analyzeBundle: "true" | "statoscope" | undefined;
20
23
  "analyze-bundle": "true" | "statoscope" | undefined;
21
- disableForkTsChecker: boolean | undefined;
22
- "disable-fork-ts-checker": boolean | undefined;
23
24
  disableSourceMapGeneration: boolean | undefined;
24
25
  "disable-source-map-generation": boolean | undefined;
25
- cdn: string | undefined;
26
+ "debug-webpack": boolean | undefined;
27
+ debugWebpack: boolean | undefined;
26
28
  _: (string | number)[];
27
29
  $0: string;
28
30
  } | Promise<{
29
31
  [x: string]: unknown;
30
32
  verbose: boolean | undefined;
31
33
  c: unknown;
32
- inspect: number | undefined;
33
- target: "client" | "server" | undefined;
34
+ cdn: string | undefined;
34
35
  env: string[] | undefined;
36
+ target: "client" | "server" | undefined;
37
+ inspect: number | undefined;
35
38
  inspectBrk: number | undefined;
36
39
  "inspect-brk": number | undefined;
37
40
  entryFilter: string[] | undefined;
38
41
  "entry-filter": string[] | undefined;
42
+ disableForkTsChecker: boolean | undefined;
43
+ "disable-fork-ts-checker": boolean | undefined;
39
44
  disableReactRefresh: boolean | undefined;
40
45
  "disable-react-refresh": boolean | undefined;
41
46
  lazyCompilation: boolean | undefined;
@@ -44,11 +49,10 @@ export declare function createCli(argv: string[]): {
44
49
  "react-profiling": boolean | undefined;
45
50
  analyzeBundle: "true" | "statoscope" | undefined;
46
51
  "analyze-bundle": "true" | "statoscope" | undefined;
47
- disableForkTsChecker: boolean | undefined;
48
- "disable-fork-ts-checker": boolean | undefined;
49
52
  disableSourceMapGeneration: boolean | undefined;
50
53
  "disable-source-map-generation": boolean | undefined;
51
- cdn: string | undefined;
54
+ "debug-webpack": boolean | undefined;
55
+ debugWebpack: boolean | undefined;
52
56
  _: (string | number)[];
53
57
  $0: string;
54
58
  }>;
@@ -136,6 +136,11 @@ function createCli(argv) {
136
136
  group: 'Client',
137
137
  type: 'boolean',
138
138
  describe: 'Enable lazy compilation',
139
+ })
140
+ .option('debug-webpack', {
141
+ group: 'Client',
142
+ type: 'boolean',
143
+ describe: 'Display final webpack configurations for debugging purposes',
139
144
  }),
140
145
  handler: handlerP(getCommandHandler('dev', (args, cmd) => {
141
146
  if ((0, models_1.isLibraryConfig)(args)) {
@@ -194,6 +199,11 @@ function createCli(argv) {
194
199
  group: 'Client',
195
200
  describe: 'Disable upload files to CDN [false]',
196
201
  type: 'string',
202
+ })
203
+ .option('debug-webpack', {
204
+ group: 'Client',
205
+ type: 'boolean',
206
+ describe: 'Display final webpack configurations for debugging purposes',
197
207
  }),
198
208
  handler: handlerP(getCommandHandler('build')),
199
209
  })
package/dist/index.d.ts CHANGED
@@ -2,4 +2,5 @@ export { configureWebpackConfigForStorybook, configureServiceWebpackConfig, } fr
2
2
  export * from './common/s3-upload';
3
3
  export { createTransformPathsToLocalModules } from './common/typescript/transformers';
4
4
  export { defineConfig } from './common/models';
5
+ export { babelPreset } from './common/babel';
5
6
  export type { ProjectConfig, ServiceConfig, LibraryConfig, ProjectFileConfig } from './common/models';
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.defineConfig = exports.createTransformPathsToLocalModules = exports.configureServiceWebpackConfig = exports.configureWebpackConfigForStorybook = void 0;
17
+ exports.babelPreset = exports.defineConfig = exports.createTransformPathsToLocalModules = exports.configureServiceWebpackConfig = exports.configureWebpackConfigForStorybook = void 0;
18
18
  var storybook_1 = require("./common/webpack/storybook");
19
19
  Object.defineProperty(exports, "configureWebpackConfigForStorybook", { enumerable: true, get: function () { return storybook_1.configureWebpackConfigForStorybook; } });
20
20
  Object.defineProperty(exports, "configureServiceWebpackConfig", { enumerable: true, get: function () { return storybook_1.configureServiceWebpackConfig; } });
@@ -23,3 +23,5 @@ var transformers_1 = require("./common/typescript/transformers");
23
23
  Object.defineProperty(exports, "createTransformPathsToLocalModules", { enumerable: true, get: function () { return transformers_1.createTransformPathsToLocalModules; } });
24
24
  var models_1 = require("./common/models");
25
25
  Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return models_1.defineConfig; } });
26
+ var babel_1 = require("./common/babel");
27
+ Object.defineProperty(exports, "babelPreset", { enumerable: true, get: function () { return babel_1.babelPreset; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/app-builder",
3
- "version": "0.7.1",
3
+ "version": "0.8.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",