@nlabs/lex 1.59.4 → 2.0.0

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.
Files changed (41) hide show
  1. package/.storybook/main.ts +3 -47
  2. package/README.md +13 -19
  3. package/__mocks__/build.js +3 -3
  4. package/config.json +3 -1
  5. package/examples/lex.config.js +3 -7
  6. package/lib/LexConfig.d.ts +2 -6
  7. package/lib/LexConfig.js +2 -2
  8. package/lib/commands/ai/ai.js +3 -3
  9. package/lib/commands/build/build.d.ts +5 -3
  10. package/lib/commands/build/build.js +66 -156
  11. package/lib/commands/config/config.js +9 -7
  12. package/lib/commands/dev/dev.d.ts +0 -2
  13. package/lib/commands/dev/dev.js +24 -115
  14. package/lib/commands/init/init.js +4 -9
  15. package/lib/commands/migrate/migrate.js +2 -2
  16. package/lib/commands/serverless-dev/serverless-dev.js +2 -2
  17. package/lib/commands/versions/versions.d.ts +1 -1
  18. package/lib/commands/versions/versions.js +4 -4
  19. package/lib/lex.js +10 -11
  20. package/lib/types.d.ts +1 -1
  21. package/lib/types.js +1 -1
  22. package/lib/utils/app.d.ts +0 -2
  23. package/lib/utils/app.js +2 -29
  24. package/lib/utils/{webpack/LexSvgSpritemapPlugin.d.ts → assets/LexSvgSpritemap.d.ts} +6 -8
  25. package/lib/utils/assets/LexSvgSpritemap.js +219 -0
  26. package/lib/utils/file.d.ts +0 -4
  27. package/lib/utils/file.js +4 -100
  28. package/lib/utils/staticSite.d.ts +15 -0
  29. package/lib/utils/staticSite.js +80 -0
  30. package/lib/utils/vite/assets.d.ts +19 -0
  31. package/lib/utils/vite/assets.js +249 -0
  32. package/lib/utils/vite/config.d.ts +12 -0
  33. package/lib/utils/vite/config.js +279 -0
  34. package/package.json +27 -45
  35. package/postcss.config.js +1 -2
  36. package/tsconfig.lint.json +0 -1
  37. package/tsconfig.test.json +0 -1
  38. package/lib/utils/webpack/LexSvgSpritemapPlugin.js +0 -255
  39. package/scripts/test-webpack.js +0 -453
  40. package/webpack.config.d.ts +0 -2
  41. package/webpack.config.js +0 -960
package/webpack.config.js DELETED
@@ -1,960 +0,0 @@
1
- /**
2
- * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3
- * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
- */
5
- import {StaticSitePlugin} from '@nlabs/webpack-plugin-static-site';
6
- import tailwindNesting from '@tailwindcss/nesting';
7
- import tailwindcss from '@tailwindcss/postcss';
8
- import autoprefixer from 'autoprefixer';
9
- import CompressionWebpackPlugin from 'compression-webpack-plugin';
10
- import CopyWebpackPlugin from 'copy-webpack-plugin';
11
- import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
12
- import cssnano from 'cssnano';
13
- import DotenvPlugin from 'dotenv-webpack';
14
- import FaviconsWebpackPlugin from 'favicons-webpack-plugin';
15
- import {existsSync} from 'fs';
16
- import {sync as globSync} from 'glob';
17
- import HtmlWebPackPlugin from 'html-webpack-plugin';
18
- import ImageMinimizerPlugin from 'image-minimizer-webpack-plugin';
19
- import isEmpty from 'lodash/isEmpty.js';
20
- import {createRequire} from 'module';
21
- import {resolve as pathResolve} from 'path';
22
- import postcssBrowserReporter from 'postcss-browser-reporter';
23
- import postcssCustomProperties from 'postcss-custom-properties';
24
- import postcssFlexbugsFixes from 'postcss-flexbugs-fixes';
25
- import postcssImport from 'postcss-import';
26
- import postcssNesting from 'postcss-nesting';
27
- import postcssPresetEnv from 'postcss-preset-env';
28
- import postcssUrl from 'postcss-url';
29
- import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
30
- import {URL} from 'url';
31
- import {default as webpack} from 'webpack';
32
- import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
33
- import {merge} from 'webpack-merge';
34
- import {WebpackPluginServe} from 'webpack-plugin-serve';
35
-
36
- import {LexConfig} from './lib/LexConfig.js';
37
- import {relativeFilePath, relativeNodePath} from './lib/utils/file.js';
38
- import LexSvgSpritemapPlugin from './lib/utils/webpack/LexSvgSpritemapPlugin.js';
39
- import postcssFor from './lib/utils/postcss/postcss-for.js';
40
- import postcssPercentage from './lib/utils/postcss/postcss-percentage.js';
41
- import tail from 'lodash/tail.js';
42
-
43
- const {ProgressPlugin, ProvidePlugin} = webpack;
44
- const isProduction = process.env.NODE_ENV === 'production';
45
- const lexConfig = JSON.parse(process.env.LEX_CONFIG) || {};
46
- const dirName = new URL('.', import.meta.url).pathname;
47
- const require = createRequire(import.meta.url);
48
-
49
- const {
50
- isStatic,
51
- outputFullPath,
52
- sourceFullPath,
53
- outputFile,
54
- outputHash,
55
- libraryName,
56
- libraryTarget,
57
- preset,
58
- targetEnvironment = 'es2015',
59
- webpack: webpackCustom
60
- } = lexConfig;
61
-
62
- const webpackStaticPath = webpackCustom?.staticPath || './src/static';
63
-
64
- const {publicPath: _, staticPath: __, ...webpackConfigFiltered} = webpackCustom || {};
65
- const swcConfig = LexConfig.getSWCConfigWithReactCompiler(lexConfig.swc, lexConfig.reactCompiler);
66
-
67
- const plugins = [
68
- new ProgressPlugin({
69
- activeModules: false,
70
- entries: true,
71
- handler(percentage, message, ...args) {
72
- // custom logic
73
- },
74
- modules: true,
75
- modulesCount: 5000,
76
- profile: false,
77
- dependencies: true,
78
- dependenciesCount: 10000,
79
- percentBy: null
80
- }),
81
- new DotenvPlugin({
82
- allowEmptyValues: true,
83
- path: pathResolve(process.cwd(), '.env'),
84
- safe: false,
85
- silent: true,
86
- systemvars: true
87
- }),
88
- new webpack.ProvidePlugin({
89
- Buffer: ['buffer', 'Buffer'],
90
- process: 'process/browser',
91
- global: 'global'
92
- }),
93
- new webpack.DefinePlugin({
94
- 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
95
- global: 'global'
96
- }),
97
- {
98
- apply: (compiler) => {
99
- compiler.hooks.watchRun.tap('NotifyOnRebuild', () => {
100
- console.log('\x1b[36m[webpack]\x1b[0m Detected file change. Rebuilding...');
101
- });
102
- compiler.hooks.done.tap('NotifyOnRebuild', (stats) => {
103
- if(stats.hasErrors()) {
104
- console.log('\x1b[31m[webpack]\x1b[0m Build failed with errors.');
105
- } else {
106
- console.log('\x1b[32m[webpack]\x1b[0m Build complete. Watching for changes...');
107
- }
108
- });
109
- compiler.hooks.normalModuleFactory.tap('ImportMetaTransform', (normalModuleFactory) => {
110
- normalModuleFactory.hooks.parser.for('javascript/auto').tap('ImportMetaTransform', (parser) => {
111
- parser.hooks.expression.for('import.meta').tap('ImportMetaTransform', (expr) => {
112
- const dep = new webpack.dependencies.ConstDependency(
113
- '({ url: typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : "") })',
114
- expr.range
115
- );
116
- dep.loc = expr.loc;
117
- parser.state.module.addPresentationalDependency(dep);
118
- return true;
119
- });
120
- parser.hooks.expression.for('import.meta.url').tap('ImportMetaTransform', (expr) => {
121
- const dep = new webpack.dependencies.ConstDependency(
122
- '(typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : ""))',
123
- expr.range
124
- );
125
- dep.loc = expr.loc;
126
- parser.state.module.addPresentationalDependency(dep);
127
- return true;
128
- });
129
- });
130
- normalModuleFactory.hooks.parser.for('javascript/esm').tap('ImportMetaTransform', (parser) => {
131
- parser.hooks.expression.for('import.meta').tap('ImportMetaTransform', (expr) => {
132
- const dep = new webpack.dependencies.ConstDependency(
133
- '({ url: typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : "") })',
134
- expr.range
135
- );
136
- dep.loc = expr.loc;
137
- parser.state.module.addPresentationalDependency(dep);
138
- return true;
139
- });
140
- parser.hooks.expression.for('import.meta.url').tap('ImportMetaTransform', (expr) => {
141
- const dep = new webpack.dependencies.ConstDependency(
142
- '(typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : ""))',
143
- expr.range
144
- );
145
- dep.loc = expr.loc;
146
- parser.state.module.addPresentationalDependency(dep);
147
- return true;
148
- });
149
- });
150
- });
151
- }
152
- }
153
- ];
154
-
155
- const isWeb = (preset || targetEnvironment) === 'web';
156
- const isReactNative = preset === 'react-native';
157
-
158
- if(isWeb) {
159
- plugins.push(
160
- new CompressionWebpackPlugin({algorithm: 'gzip'}),
161
- new ProvidePlugin({
162
- process: 'process/browser',
163
- global: 'global',
164
- React: pathResolve(dirName, './node_modules/react')
165
- })
166
- );
167
- }
168
-
169
- const globOptions = {
170
- cwd: sourceFullPath,
171
- dot: false,
172
- nodir: true,
173
- nosort: true
174
- };
175
-
176
- const svgPaths = `${sourceFullPath}/icons/**/**.svg`;
177
-
178
- if(globSync(svgPaths, globOptions).length) {
179
- plugins.push(
180
- new LexSvgSpritemapPlugin(svgPaths, {
181
- allowDuplicates: false,
182
- filename: './icons/icons.svg',
183
- prefix: false
184
- })
185
- );
186
- }
187
-
188
- const staticPaths = [];
189
- const watchIgnorePaths = [
190
- `${sourceFullPath}/**/**.gif`,
191
- `${sourceFullPath}/**/**.jpg`,
192
- `${sourceFullPath}/**/**.png`
193
- ];
194
- const imagePath = `${sourceFullPath}/images/`;
195
- const fontPath = `${sourceFullPath}/fonts/`;
196
- const docPath = `${sourceFullPath}/docs/`;
197
- const iconPath = `${sourceFullPath}/icons/`;
198
-
199
- const staticPathFull = pathResolve(process.cwd(), webpackStaticPath);
200
-
201
- if(existsSync(staticPathFull)) {
202
- staticPaths.push({
203
- from: staticPathFull,
204
- globOptions: {
205
- ignore: ['**/.DS_Store']
206
- },
207
- noErrorOnMissing: true,
208
- to: './'
209
- });
210
- watchIgnorePaths.push(staticPathFull);
211
- }
212
-
213
- if(existsSync(imagePath)) {
214
- staticPaths.push({from: imagePath, noErrorOnMissing: true, to: './images/'});
215
- watchIgnorePaths.push(imagePath);
216
- }
217
-
218
- if(existsSync(fontPath)) {
219
- staticPaths.push({from: fontPath, noErrorOnMissing: true, to: './fonts/'});
220
- watchIgnorePaths.push(fontPath);
221
- }
222
-
223
- if(existsSync(docPath)) {
224
- staticPaths.push({from: docPath, noErrorOnMissing: true, to: './docs/'});
225
- }
226
-
227
- if(existsSync(iconPath)) {
228
- staticPaths.push({
229
- from: iconPath,
230
- globOptions: {
231
- ignore: ['**/*.svg']
232
- },
233
- noErrorOnMissing: true,
234
- to: './icons/'
235
- });
236
- watchIgnorePaths.push(iconPath);
237
- }
238
-
239
- if(staticPaths.length) {
240
- plugins.push(new CopyWebpackPlugin({patterns: staticPaths}));
241
- }
242
-
243
- if(existsSync(`${sourceFullPath}/${lexConfig.entryHTML}`)) {
244
- plugins.push(
245
- new HtmlWebPackPlugin({
246
- filename: 'index.html',
247
- minify: isProduction,
248
- showErrors: !isProduction,
249
- template: `${sourceFullPath}/${lexConfig.entryHTML}`,
250
- inject: true
251
- })
252
- );
253
- }
254
-
255
- let outputFilename = outputFile;
256
-
257
- if(outputFile) {
258
- outputFilename = outputFile;
259
- } else if(outputHash || (isWeb && isProduction)) {
260
- outputFilename = '[name].[hash].js';
261
- } else {
262
- outputFilename = '[name].js';
263
- }
264
-
265
- const resolvePlugins = [];
266
- if(existsSync(`${sourceFullPath}/tsconfig.json`)) {
267
- resolvePlugins.push(new TsconfigPathsPlugin({
268
- configFile: `${sourceFullPath}/../tsconfig.json`
269
- }));
270
- }
271
-
272
- const swcLoaderPath = relativeNodePath('swc-loader', dirName) || 'swc-loader';
273
- const cssLoaderPath = relativeNodePath('css-loader', dirName) || 'css-loader';
274
- const graphqlLoaderPath = relativeNodePath('graphql-tag/loader', dirName) || 'graphql-tag/loader';
275
- const htmlLoaderPath = relativeNodePath('html-loader', dirName) || 'html-loader';
276
- const miniCssExtractPluginPath = relativeNodePath('mini-css-extract-plugin', dirName) || 'mini-css-extract-plugin';
277
- const postcssLoaderPath = relativeNodePath('postcss-loader', dirName) || 'postcss-loader';
278
- const sourceMapLoaderPath = relativeNodePath('source-map-loader', dirName) || 'source-map-loader';
279
- const styleLoaderPath = relativeNodePath('style-loader', dirName) || 'style-loader';
280
- const webpackPath = relativeNodePath('webpack', dirName) || 'webpack';
281
-
282
- const aliasPaths = {
283
- '@nlabs/arkhamjs': relativeNodePath('@nlabs/arkhamjs', process.cwd()),
284
- '@nlabs/arkhamjs-utils-react': relativeNodePath('@nlabs/arkhamjs-utils-react', process.cwd()),
285
- buffer: relativeNodePath('buffer', dirName),
286
- 'core-js': relativeNodePath('core-js', dirName),
287
- process: relativeNodePath('process', dirName),
288
- react: relativeNodePath('react', process.cwd()),
289
- 'react-dom': relativeNodePath('react-dom', process.cwd()),
290
- 'regenerator-runtime': relativeNodePath('regenerator-runtime', dirName),
291
- Buffer: relativeNodePath('buffer', dirName)
292
- };
293
- const aliasKeys = Object.keys(aliasPaths);
294
- const alias = aliasKeys.reduce((aliases, key) => {
295
- if(!isEmpty(aliasPaths[key])) {
296
- aliases[key] = aliasPaths[key];
297
- }
298
-
299
- return aliases;
300
- }, {});
301
-
302
- export default (webpackEnv, webpackOptions) => {
303
- const {bundleAnalyzer, watch, entry: cliEntry, mode: cliMode, port} = webpackOptions;
304
- const envPort = process.env.WEBPACK_DEV_PORT ? parseInt(process.env.WEBPACK_DEV_PORT, 10) : null;
305
- const finalPort = port || envPort || 3000;
306
- const entryValue = Array.isArray(cliEntry) ? cliEntry[0] : cliEntry;
307
-
308
- // Debug printout for environment and mode
309
- console.log('[Lex Webpack] NODE_ENV:', process.env.NODE_ENV);
310
- console.log('[Lex Webpack] isProduction:', isProduction);
311
- console.log('[Lex Webpack] cliMode:', cliMode);
312
-
313
- const webpackConfig = {
314
- bail: true,
315
- cache: !isProduction,
316
- devtool: isProduction
317
- ? 'inline-cheap-module-source-map'
318
- : 'eval-cheap-module-source-map',
319
- entry: entryValue
320
- ? {
321
- index: [
322
- 'buffer',
323
- 'process/browser',
324
- entryValue
325
- ]
326
- }
327
- : {
328
- index: [
329
- 'buffer',
330
- 'process/browser',
331
- `${sourceFullPath}/${lexConfig.entryJs}`
332
- ]
333
- },
334
- externals: isReactNative ? {'react-native': true} : undefined,
335
- ignoreWarnings: [/Failed to parse source map/],
336
- mode: isProduction ? 'production' : 'development',
337
- module: {
338
- rules: [
339
- {
340
- test: /\.m?js/,
341
- resolve: {
342
- fullySpecified: false
343
- }
344
- },
345
- {
346
- test: /\.js$/,
347
- include: /node_modules/,
348
- exclude: [
349
- /[\\/]websocket\.js$/,
350
- /[\\/]websocket.*\.js$/
351
- ],
352
- type: 'javascript/auto'
353
- },
354
- {
355
- test: /[\\/]websocket(.*)?\.js$/,
356
- include: /node_modules/,
357
- use: {
358
- loader: swcLoaderPath,
359
- options: {
360
- jsc: {
361
- parser: {
362
- syntax: 'ecmascript',
363
- dynamicImport: true,
364
- importAssertions: true
365
- },
366
- target: 'es2020',
367
- transform: {
368
- legacyDecorator: false,
369
- decoratorMetadata: false
370
- }
371
- },
372
- module: {
373
- type: 'es6',
374
- strict: false,
375
- strictMode: true,
376
- lazy: false,
377
- noInterop: true
378
- },
379
- minify: false,
380
- sourceMaps: false
381
- }
382
- }
383
- },
384
- {
385
- enforce: 'pre',
386
- exclude: /(node_modules)/,
387
- include: sourceFullPath,
388
- loader: sourceMapLoaderPath,
389
- test: /\.(ts|tsx|js)$/
390
- },
391
- {
392
- exclude: [
393
- /node_modules\/(?!(react-native))/,
394
- `${sourceFullPath}/**/*.test.js*`,
395
- `${sourceFullPath}/**/*.test.ts*`
396
- ],
397
- include: sourceFullPath,
398
- type: 'javascript/esm',
399
- loader: swcLoaderPath,
400
- options: {
401
- ...swcConfig,
402
- jsc: {
403
- ...swcConfig?.jsc,
404
- parser: {
405
- ...swcConfig?.jsc?.parser,
406
- tsx: false,
407
- dynamicImport: true
408
- },
409
- target: swcConfig?.jsc?.target || 'es2020'
410
- },
411
- module: {
412
- ...swcConfig?.module,
413
- type: 'es6'
414
- }
415
- },
416
- resolve: {
417
- symlinks: true
418
- },
419
- test: /\.(ts|js)$/
420
- },
421
- {
422
- exclude: [
423
- /node_modules\/(?!(react-native))/,
424
- `${sourceFullPath}/**/*.test.js*`,
425
- `${sourceFullPath}/**/*.test.ts*`
426
- ],
427
- include: sourceFullPath,
428
- type: 'javascript/esm',
429
- loader: swcLoaderPath,
430
- options: {
431
- ...swcConfig
432
- },
433
- resolve: {
434
- symlinks: true
435
- },
436
- test: /\.tsx$/
437
- },
438
- {
439
- exclude: [pathResolve(sourceFullPath, lexConfig.entryHTML)],
440
- include: sourceFullPath,
441
- test: /\.html$/,
442
- use: [
443
- {
444
- loader: htmlLoaderPath,
445
- options: {
446
- minimize: isProduction,
447
- sources: {
448
- list: [
449
- '...',
450
- {
451
- tag: 'link',
452
- attribute: 'href',
453
- type: 'src',
454
- filter: (tag, attribute, attributes) => {
455
- const href = attributes[attribute];
456
- return !href || !href.match(/\.(ico|png|jpg|jpeg|gif|svg|json)$/);
457
- }
458
- },
459
- {
460
- tag: 'script',
461
- attribute: 'src',
462
- type: 'src',
463
- filter: (tag, attribute, attributes) => {
464
- const src = attributes[attribute];
465
- return !src || !src.match(/\.(ico|png|jpg|jpeg|gif|svg|json)$/);
466
- }
467
- }
468
- ]
469
- }
470
- }
471
- }
472
- ]
473
- },
474
- {
475
- test: /\.css$/,
476
- use: [
477
- ...(isProduction && isWeb
478
- ? [{
479
- loader: require(miniCssExtractPluginPath).loader
480
- }]
481
- : [styleLoaderPath]),
482
- {
483
- loader: cssLoaderPath,
484
- options: {
485
- importLoaders: 1,
486
- url: {
487
- filter: (url, resourcePath) => {
488
- if(url.startsWith('/')) {
489
- return false;
490
- }
491
-
492
- return true;
493
- }
494
- }
495
- }
496
- },
497
- {
498
- loader: postcssLoaderPath,
499
- options: {
500
- postcssOptions: {
501
- plugins: [
502
- postcssImport({
503
- addDependencyTo: webpack,
504
- path: [relativeNodePath('', dirName)]
505
- }),
506
- postcssUrl({
507
- // Skip processing absolute URLs (starting with /) - let them pass through as-is
508
- filter: (asset) => {
509
- const url = asset.url || '';
510
- // If URL starts with /, it's an absolute path - don't process it
511
- if(url.startsWith('/')) {
512
- return false;
513
- }
514
- // Process relative URLs
515
- return true;
516
- }
517
- }),
518
- postcssFor(),
519
- postcssPercentage({
520
- floor: true,
521
- precision: 9,
522
- trimTrailingZero: true
523
- }),
524
- postcssCustomProperties({
525
- extensions: ['.css'],
526
- inject: {
527
- insertAt: 'top'
528
- },
529
- minimize: true,
530
- preserve: false,
531
- strict: false,
532
- warnings: false
533
- }),
534
- tailwindNesting(),
535
- postcssNesting(),
536
- tailwindcss(),
537
- autoprefixer(),
538
- postcssFlexbugsFixes(),
539
- postcssPresetEnv({
540
- stage: 0
541
- }),
542
- ...(isProduction ? [cssnano({autoprefixer: false})] : []),
543
- postcssBrowserReporter()
544
- ]
545
- }
546
- }
547
- }
548
- ]
549
- },
550
- {
551
- exclude: /(node_modules)/,
552
- include: sourceFullPath,
553
- test: /\.(gif|jpg|png|svg)$/,
554
- type: 'asset/resource'
555
- },
556
- {
557
- test: /\.(jpg|jpeg|png|gif|webp|svg|mp4|webm|ogg|mp3|wav|flac|aac)$/,
558
- include: staticPathFull,
559
- type: 'asset/resource',
560
- generator: {
561
- filename: '[name].[hash][ext]'
562
- }
563
- },
564
- {
565
- test: /\.json$/,
566
- type: 'json'
567
- },
568
- {
569
- test: /\.ico$/,
570
- type: 'asset/resource',
571
- generator: {
572
- filename: '[name][ext]'
573
- }
574
- },
575
- {
576
- exclude: /(node_modules)/,
577
- include: sourceFullPath,
578
- loader: graphqlLoaderPath,
579
- test: /\.(gql|graphql)$/
580
- }
581
- ]
582
- },
583
- optimization:
584
- isProduction && isWeb
585
- ? {
586
- minimizer: [
587
- new CssMinimizerPlugin(),
588
- new ImageMinimizerPlugin({
589
- include: staticPathFull,
590
- minimizer: [
591
- {
592
- filter: (_source, sourcePath) => /\.(gif|jpe?g|png|webp)$/i.test(sourcePath),
593
- implementation: ImageMinimizerPlugin.sharpMinify,
594
- options: {
595
- encodeOptions: {
596
- jpeg: {
597
- progressive: true,
598
- quality: 65
599
- },
600
- png: {
601
- quality: 90
602
- },
603
- webp: {
604
- quality: 75
605
- }
606
- }
607
- }
608
- },
609
- {
610
- filter: (_source, sourcePath) => /\.svg$/i.test(sourcePath),
611
- implementation: ImageMinimizerPlugin.svgoMinify,
612
- options: {
613
- encodeOptions: {
614
- multipass: true,
615
- plugins: ['preset-default']
616
- }
617
- }
618
- }
619
- ],
620
- test: /\.(gif|jpe?g|png|svg|webp)$/i
621
- })
622
- ],
623
- runtimeChunk: 'single',
624
- splitChunks: {
625
- cacheGroups: {
626
- vendor: {
627
- chunks: 'all',
628
- minSize: 0,
629
- name: 'vendors',
630
- test: /[\\/]node_modules[\\/]/
631
- }
632
- }
633
- },
634
- usedExports: true
635
- }
636
- : {},
637
- output: {
638
- filename: outputFilename,
639
- library: libraryName,
640
- libraryTarget,
641
- path: outputFullPath,
642
- publicPath: '/',
643
- environment: {
644
- module: true
645
- }
646
- },
647
- plugins,
648
- recordsPath: relativeFilePath('webpack.records.json', process.cwd()),
649
- resolve: {
650
- alias,
651
- extensions: [
652
- '.*',
653
- '.mjs',
654
- '.js',
655
- '.ts',
656
- '.tsx',
657
- '.jsx',
658
- '.json',
659
- '.gql',
660
- '.graphql'
661
- ],
662
- extensionAlias: {
663
- '.js': ['.ts', '.tsx', '.js', '.jsx'],
664
- '.jsx': ['.tsx', '.jsx']
665
- },
666
- fallback: {
667
- assert: relativeNodePath('assert', dirName),
668
- buffer: relativeNodePath('buffer', dirName),
669
- crypto: relativeNodePath('crypto-js', dirName),
670
- http: relativeNodePath('stream-http', dirName),
671
- https: relativeNodePath('https-browserify', dirName),
672
- os: relativeNodePath('os-browserify/browser.js', dirName),
673
- path: relativeNodePath('path-browserify', dirName),
674
- process: relativeNodePath('process/browser.js', dirName),
675
- randombytes: relativeNodePath('randombytes', dirName),
676
- stream: relativeNodePath('stream-browserify', dirName),
677
- util: relativeNodePath('util', dirName),
678
- vm: relativeNodePath('vm-browserify', dirName),
679
- Buffer: relativeNodePath('buffer', dirName)
680
- },
681
- mainFiles: ['index'],
682
- modules: [sourceFullPath, 'node_modules', relativeNodePath('', dirName), '/Users/nitrog7/.nvm/versions/node/v22.14.0/lib/node_modules'],
683
- plugins: resolvePlugins,
684
- unsafeCache: {
685
- node_modules: true
686
- }
687
- },
688
- target: isWeb ? 'web' : 'node'
689
- };
690
-
691
- if(!isProduction) {
692
- webpackConfig.resolve.alias = {
693
- ...webpackConfig.resolve.alias,
694
- webpack: webpackPath
695
- };
696
- webpackConfig.optimization = {minimize: false};
697
- webpackConfig.entry.wps = relativeNodePath(
698
- 'webpack-plugin-serve/client.js',
699
- dirName
700
- );
701
- webpackConfig.stats = {errorDetails: true};
702
- webpackConfig.plugins.push(
703
- new WebpackPluginServe({
704
- client: {
705
- silent: process.env.LEX_QUIET === 'true'
706
- },
707
- historyFallback: {
708
- disableDotRule: true,
709
- htmlAcceptHeaders: ['text/html', '*/*'],
710
- index: '/index.html',
711
- logger: console.log.bind(console),
712
- rewrites: [
713
- {
714
- from: '/wps',
715
- to: ({parsedUrl: {pathname}}) => pathname
716
- },
717
- {
718
- from: /\.js/,
719
- to: ({parsedUrl: {pathname}}) => {
720
- const pathUrl = pathname.split('/');
721
- const fileIndex = pathUrl.length > 1 ? pathUrl.length - 1 : 0;
722
- return `/${pathUrl[fileIndex]}`;
723
- }
724
- }
725
- ],
726
- verbose: !(process.env.LEX_QUIET === 'true')
727
- },
728
- hmr: false,
729
- log: {level: 'trace'},
730
- middleware: (app, builtins) => {
731
- const koaStatic = require('koa-static');
732
- const {readFileSync} = require('fs');
733
-
734
- app.use(async (ctx, next) => {
735
- const path = ctx.path || ctx.url || '';
736
- const isStaticFile = path && /\.(css|gif|ico|jpg|jpeg|json|png|svg|txt|woff|woff2|ttf|eot)$/i.test(path);
737
-
738
- if(isStaticFile && outputFullPath) {
739
- const filePath = pathResolve(outputFullPath, path.replace(/^\//, ''));
740
- if(existsSync(filePath)) {
741
- try {
742
- ctx.type = path.match(/\.svg$/i) ? 'image/svg+xml' :
743
- path.match(/\.(jpg|jpeg|png|gif)$/i) ? `image/${path.split('.').pop()}` :
744
- path.match(/\.css$/i) ? 'text/css' :
745
- 'application/octet-stream';
746
- ctx.body = readFileSync(filePath);
747
- ctx.status = 200;
748
-
749
- return;
750
- } catch(err) {
751
- if(process.env.LEX_CONFIG_DEBUG) {
752
- console.log(`[LEX_DEBUG] Error reading file ${filePath}:`, err.message);
753
- }
754
- }
755
- } else {
756
- if(process.env.LEX_CONFIG_DEBUG) {
757
- console.log(`[LEX_DEBUG] File not found at: ${filePath}, outputFullPath: ${outputFullPath}, path: ${path}`);
758
- }
759
- }
760
- }
761
-
762
- await next();
763
- });
764
-
765
- if(outputFullPath && existsSync(outputFullPath)) {
766
- if(process.env.LEX_CONFIG_DEBUG) {
767
- console.log(`[LEX_DEBUG] Setting up static file serving from output: ${outputFullPath}`);
768
- }
769
-
770
- app.use(koaStatic(outputFullPath, {
771
- index: false,
772
- defer: false,
773
- hidden: false,
774
- gzip: true,
775
- br: false
776
- }));
777
- }
778
-
779
- if(existsSync(staticPathFull)) {
780
- if(process.env.LEX_CONFIG_DEBUG) {
781
- console.log(`[LEX_DEBUG] Setting up static file serving from: ${staticPathFull}`);
782
- }
783
-
784
- app.use(koaStatic(staticPathFull, {
785
- index: false, // Don't auto-serve index files
786
- defer: false, // CRITICAL: Don't defer - serve immediately if file exists
787
- hidden: false,
788
- gzip: true,
789
- br: false
790
- }));
791
-
792
- if(process.env.LEX_CONFIG_DEBUG) {
793
- app.use(async (ctx, next) => {
794
- const path = ctx.path || ctx.url || '';
795
- if(path && !path.match(/^\/wps/) && !path.match(/^\/webpack/)) {
796
- console.log(`[LEX_DEBUG] Request: ${path}`);
797
- }
798
- await next();
799
- if(ctx.status === 404 && path && path.includes('.')) {
800
- console.log(`[LEX_DEBUG] 404 for: ${path}, body set: ${ctx.body !== undefined}`);
801
- }
802
- });
803
- }
804
- } else {
805
- if(process.env.LEX_CONFIG_DEBUG) {
806
- console.log(`[LEX_DEBUG] Static path does not exist: ${staticPathFull}`);
807
- }
808
- }
809
-
810
- app.use(async (ctx, next) => {
811
- const path = ctx.path || ctx.url || '';
812
- const isStaticFile = path && /\.(css|gif|ico|jpg|jpeg|json|png|svg|txt|woff|woff2|ttf|eot)$/i.test(path);
813
-
814
- await next();
815
-
816
- if(isStaticFile && ctx.status === 404) {
817
- ctx.body = 'File not found';
818
- return;
819
- }
820
- });
821
-
822
- app.use(async (ctx, next) => {
823
- const path = ctx.path || ctx.url || (ctx.request && ctx.request.path) || '';
824
- if(path && path.match(/^\/wps/)) {
825
- const {accept, Accept, ...remainingHeaders} =
826
- ctx.request.header;
827
- ctx.request.header = remainingHeaders;
828
- }
829
- await next();
830
- });
831
- },
832
- open: process.env.WEBPACK_DEV_OPEN === 'true',
833
- port: finalPort,
834
- progress: 'minimal',
835
- static: outputFullPath ? [outputFullPath] : [],
836
- status: true
837
- })
838
- );
839
-
840
- if(bundleAnalyzer) {
841
- webpackConfig.plugins.push(
842
- new BundleAnalyzerPlugin({openAnalyzer: false})
843
- );
844
- }
845
-
846
- if(watch) {
847
- webpackConfig.bail = false;
848
- webpackConfig.watchOptions = {
849
- aggregateTimeout: 500,
850
- ignored: ['node_modules/**', ...watchIgnorePaths]
851
- };
852
- }
853
- } else {
854
- // In production, extract CSS to separate files for injection into HTML
855
- if(isProduction && isWeb) {
856
- const MiniCssExtractPlugin = require(miniCssExtractPluginPath);
857
- plugins.push(
858
- new MiniCssExtractPlugin({
859
- filename: outputHash ? 'css/[name].[contenthash].css' : 'css/[name].css',
860
- chunkFilename: outputHash ? 'css/[name].[contenthash].chunk.css' : 'css/[name].chunk.css'
861
- })
862
- );
863
- webpackConfig.optimization.moduleIds = 'deterministic';
864
- }
865
-
866
- const siteLogo = `${sourceFullPath}/images/logo.png`;
867
-
868
- if(existsSync(siteLogo)) {
869
- plugins.push(
870
- new FaviconsWebpackPlugin({
871
- icons: {
872
- android: true,
873
- appleIcon: true,
874
- appleStartup: false,
875
- coast: false,
876
- favicons: true,
877
- firefox: false,
878
- opengraph: true,
879
- twitter: true,
880
- windows: false,
881
- yandex: false
882
- },
883
- logo: siteLogo
884
- })
885
- );
886
- }
887
-
888
- if(isStatic) {
889
- webpackConfig.plugins.push(
890
- new StaticSitePlugin()
891
- );
892
- }
893
- }
894
-
895
- if(process.env.LEX_CONFIG_DEBUG) {
896
- console.log('\n\x1b[36m[LEX_CONFIG_DEBUG] Webpack mode:', process.env.NODE_ENV, 'isProduction:', isProduction, '\x1b[0m');
897
- if(webpackConfig && webpackConfig.module && Array.isArray(webpackConfig.module.rules)) {
898
- console.log('\x1b[36m[LEX_CONFIG_DEBUG] Loader chains:\x1b[0m');
899
- webpackConfig.module.rules.forEach((rule, idx) => {
900
- if(rule.test) {
901
- const testStr = rule.test.toString();
902
- let use = rule.use || rule.loader || rule.type;
903
- if(Array.isArray(use)) {
904
- use = use.map((u) => (typeof u === 'string' ? u : u.loader || u.type)).join(' -> ');
905
- } else if(typeof use === 'object' && use !== null) {
906
- use = use.loader || use.type;
907
- }
908
- console.log(` [${idx}] ${testStr}: ${use}`);
909
- }
910
- });
911
- }
912
-
913
- if(webpackConfig && Array.isArray(webpackConfig.plugins)) {
914
- console.log('\x1b[36m[LEX_CONFIG_DEBUG] Plugins:\x1b[0m');
915
- webpackConfig.plugins.forEach((plugin, idx) => {
916
- let name = plugin.constructor && plugin.constructor.name;
917
- if(!name && typeof plugin === 'object' && plugin.apply) {
918
- name = 'CustomPlugin';
919
- }
920
- if(!name && typeof plugin === 'function') {
921
- name = 'FunctionPlugin';
922
- }
923
- console.log(` [${idx}] ${name}`);
924
- });
925
- }
926
-
927
- if(webpackConfig && webpackConfig.module && Array.isArray(webpackConfig.module.rules)) {
928
- const cssRule = webpackConfig.module.rules.find((rule) => rule.test && rule.test.toString().includes('css'));
929
- if(cssRule) {
930
- let use = cssRule.use || cssRule.loader || cssRule.type;
931
- if(Array.isArray(use)) {
932
- use = use.map((u) => (typeof u === 'string' ? u : u.loader || u.type)).join(' -> ');
933
- } else if(typeof use === 'object' && use !== null) {
934
- use = use.loader || use.type;
935
- }
936
- console.log('\x1b[36m[LEX_CONFIG_DEBUG] CSS Loader Chain:\x1b[0m', use);
937
- } else {
938
- console.log('\x1b[36m[LEX_CONFIG_DEBUG] No CSS loader rule found.\x1b[0m');
939
- }
940
- }
941
- }
942
-
943
- const mergedConfig = merge(webpackConfig, webpackConfigFiltered);
944
-
945
- if(Array.isArray(mergedConfig.plugins)) {
946
- mergedConfig.plugins = mergedConfig.plugins.filter((plugin) => {
947
- if(typeof plugin === 'function' || (plugin && typeof plugin.apply === 'function')) {
948
- return true;
949
- }
950
-
951
- if(plugin && typeof plugin === 'object' && 'postcssPlugin' in plugin) {
952
- return false;
953
- }
954
-
955
- return true;
956
- });
957
- }
958
-
959
- return mergedConfig;
960
- };