@meteorjs/rspack 1.1.0-beta.1 → 1.1.0-beta.10

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/lib/ignore.js CHANGED
@@ -117,7 +117,7 @@ function createIgnoreRegex(globPatterns) {
117
117
 
118
118
  // For absolute paths, we don't want to force the pattern to match from the beginning
119
119
  // but we still want to ensure it matches to the end of the path segment
120
- regexPattern = '(?:^|/)' + regexPattern + '$';
120
+ regexPattern = '(?:^|/)' + regexPattern;
121
121
 
122
122
  return regexPattern;
123
123
  }).filter(pattern => pattern !== null);
@@ -202,6 +202,12 @@ function disablePlugins(config, matchers) {
202
202
  return config;
203
203
  }
204
204
 
205
+ function outputMeteorRspack(data) {
206
+ const jsonString = JSON.stringify(data);
207
+ const output = `[Meteor-Rspack]${jsonString}[/Meteor-Rspack]`;
208
+ console.log(output);
209
+ }
210
+
205
211
  module.exports = {
206
212
  compileWithMeteor,
207
213
  compileWithRspack,
@@ -210,4 +216,5 @@ module.exports = {
210
216
  extendSwcConfig,
211
217
  makeWebNodeBuiltinsAlias,
212
218
  disablePlugins,
219
+ outputMeteorRspack,
213
220
  };
package/lib/test.js CHANGED
@@ -9,17 +9,20 @@ const { createIgnoreRegex, createIgnoreGlobConfig } = require("./ignore.js");
9
9
  * @param {string} options.projectDir - The project directory
10
10
  * @param {string} options.buildContext - The build context
11
11
  * @param {string[]} options.ignoreEntries - Array of ignore patterns
12
+ * @param {string[]} options.meteorIgnoreEntries - Array of meteor ignore patterns
12
13
  * @param {string} options.extraEntry - Extra entry to load
13
14
  * @returns {string} The path to the generated file
14
15
  */
15
16
  const generateEagerTestFile = ({
16
- isAppTest,
17
- projectDir,
18
- buildContext,
19
- ignoreEntries: inIgnoreEntries = [],
20
- prefix: inPrefix = '',
21
- extraEntry,
22
- }) => {
17
+ isAppTest,
18
+ projectDir,
19
+ buildContext,
20
+ ignoreEntries: inIgnoreEntries = [],
21
+ meteorIgnoreEntries: inMeteorIgnoreEntries = [],
22
+ prefix: inPrefix = '',
23
+ extraEntry,
24
+ globalImportPath,
25
+ }) => {
23
26
  const distDir = path.resolve(projectDir, ".meteor/local/test");
24
27
  if (!fs.existsSync(distDir)) {
25
28
  fs.mkdirSync(distDir, { recursive: true });
@@ -39,6 +42,11 @@ const generateEagerTestFile = ({
39
42
  const excludeFoldersRegex = createIgnoreRegex(
40
43
  createIgnoreGlobConfig(ignoreEntries)
41
44
  );
45
+ console.log("inMeteorIgnoreEntries", inMeteorIgnoreEntries);
46
+ // Create regex from meteor ignore entries
47
+ const excludeMeteorIgnoreRegex = inMeteorIgnoreEntries.length > 0
48
+ ? createIgnoreRegex(createIgnoreGlobConfig(inMeteorIgnoreEntries))
49
+ : null;
42
50
 
43
51
  const prefix = (inPrefix && `${inPrefix}-`) || "";
44
52
  const filename = isAppTest
@@ -49,25 +57,39 @@ const generateEagerTestFile = ({
49
57
  ? "/\\.app-(?:test|spec)s?\\.[^.]+$/"
50
58
  : "/\\.(?:test|spec)s?\\.[^.]+$/";
51
59
 
52
- const content = `{
53
- const ctx = import.meta.webpackContext('/', {
60
+ const content = `${
61
+ globalImportPath ? `import '${globalImportPath}';\n\n` : ""
62
+ }${
63
+ excludeMeteorIgnoreRegex
64
+ ? `const MeteorIgnoreRegex = ${excludeMeteorIgnoreRegex.toString()};`
65
+ : ""
66
+ }
67
+ {
68
+ const ctx = import.meta.webpackContext('${projectDir}', {
54
69
  recursive: true,
55
70
  regExp: ${regExp},
56
71
  exclude: ${excludeFoldersRegex.toString()},
57
72
  mode: 'eager',
58
73
  });
59
- ctx.keys().forEach(ctx);
74
+ ctx.keys().filter((k) => {
75
+ ${
76
+ excludeMeteorIgnoreRegex
77
+ ? `// Only exclude based on *relative* path segments.
78
+ return !MeteorIgnoreRegex.test(k);`
79
+ : "return true;"
80
+ }
81
+ }).forEach(ctx);
60
82
  ${
61
83
  extraEntry
62
84
  ? `const extra = import.meta.webpackContext('${path.dirname(
63
- extraEntry
64
- )}', {
85
+ extraEntry
86
+ )}', {
65
87
  recursive: false,
66
88
  regExp: ${new RegExp(`${path.basename(extraEntry)}$`).toString()},
67
89
  mode: 'eager',
68
90
  });
69
91
  extra.keys().forEach(extra);`
70
- : ''
92
+ : ""
71
93
  }
72
94
  }`;
73
95
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meteorjs/rspack",
3
- "version": "1.1.0-beta.1",
3
+ "version": "1.1.0-beta.10",
4
4
  "description": "Configuration logic for using Rspack in Meteor projects",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
@@ -0,0 +1,36 @@
1
+ // MeteorRspackOutputPlugin.js
2
+ //
3
+ // This plugin outputs a JSON stringified with a tag delimiter each time
4
+ // a new Rspack compilation happens. The JSON content is configurable
5
+ // via plugin instantiation options.
6
+
7
+ const { outputMeteorRspack } = require('../lib/meteorRspackHelpers');
8
+
9
+ class MeteorRspackOutputPlugin {
10
+ constructor(options = {}) {
11
+ this.pluginName = 'MeteorRspackOutputPlugin';
12
+ this.options = options;
13
+ this.compilationCount = 0;
14
+ // The data to be output as JSON, can be a static object or a function
15
+ this.getData =
16
+ typeof options.getData === 'function'
17
+ ? options.getData
18
+ : () => options.data || {};
19
+ }
20
+
21
+ apply(compiler) {
22
+ // Hook into the 'done' event which fires after each compilation completes
23
+ compiler.hooks.done.tap(this.pluginName, stats => {
24
+ this.compilationCount++;
25
+ const data = {
26
+ ...(this.getData(stats, {
27
+ compilationCount: this.compilationCount,
28
+ isRebuild: this.compilationCount > 1,
29
+ }) || {}),
30
+ };
31
+ outputMeteorRspack(data);
32
+ });
33
+ }
34
+ }
35
+
36
+ module.exports = { MeteorRspackOutputPlugin };
package/rspack.config.js CHANGED
@@ -10,6 +10,7 @@ const { getMeteorAppSwcConfig } = require('./lib/swc.js');
10
10
  const HtmlRspackPlugin = require('./plugins/HtmlRspackPlugin.js');
11
11
  const { RequireExternalsPlugin } = require('./plugins/RequireExtenalsPlugin.js');
12
12
  const { AssetExternalsPlugin } = require('./plugins/AssetExternalsPlugin.js');
13
+ const { MeteorRspackOutputPlugin } = require('./plugins/MeteorRspackOutputPlugin.js');
13
14
  const { generateEagerTestFile } = require("./lib/test.js");
14
15
  const { getMeteorIgnoreEntries, createIgnoreGlobConfig } = require("./lib/ignore");
15
16
  const { mergeMeteorRspackFragments } = require("./lib/meteorRspackConfigFactory.js");
@@ -21,6 +22,7 @@ const {
21
22
  extendSwcConfig,
22
23
  makeWebNodeBuiltinsAlias,
23
24
  disablePlugins,
25
+ outputMeteorRspack,
24
26
  } = require('./lib/meteorRspackHelpers.js');
25
27
  const { prepareMeteorRspackConfig } = require("./lib/meteorRspackConfigFactory");
26
28
 
@@ -225,6 +227,8 @@ module.exports = async function (inMeteor = {}, argv = {}) {
225
227
  const isTestLike = !!Meteor.isTestLike;
226
228
  const swcExternalHelpers = !!Meteor.swcExternalHelpers;
227
229
  const isNative = !!Meteor.isNative;
230
+ const isProfile = !!Meteor.isProfile;
231
+ const isVerbose = !!Meteor.isVerbose;
228
232
  const mode = isProd ? 'production' : 'development';
229
233
  const projectDir = process.cwd();
230
234
  const projectConfigPath = Meteor.projectConfigPath || path.resolve(projectDir, 'rspack.config.js');
@@ -427,27 +431,35 @@ module.exports = async function (inMeteor = {}, argv = {}) {
427
431
  : [];
428
432
  // Not supported in Meteor yet (Rspack 1.7+ is enabled by default)
429
433
  const lazyCompilationConfig = { lazyCompilation: false };
434
+ const shouldLogVerbose = isProfile || isVerbose;
435
+ const loggingConfig = shouldLogVerbose
436
+ ? {}
437
+ : { stats: "errors-warnings", infrastructureLogging: { level: "warn" } };
430
438
 
431
439
  const clientEntry =
432
- isTest && isTestEager && isTestFullApp
440
+ isClient && isTest && isTestEager && isTestFullApp
433
441
  ? generateEagerTestFile({
434
442
  isAppTest: true,
435
443
  projectDir,
436
444
  buildContext,
437
- ignoreEntries: [...meteorIgnoreEntries, "**/server/**"],
445
+ ignoreEntries: ["**/server/**"],
446
+ meteorIgnoreEntries,
438
447
  prefix: "client",
439
448
  extraEntry: path.resolve(process.cwd(), Meteor.mainClientEntry),
449
+ globalImportPath: path.resolve(projectDir, buildContext, entryPath),
440
450
  })
441
- : isTest && isTestEager
451
+ : isClient && isTest && isTestEager
442
452
  ? generateEagerTestFile({
443
453
  isAppTest: false,
444
454
  isClient: true,
445
455
  projectDir,
446
456
  buildContext,
447
- ignoreEntries: [...meteorIgnoreEntries, "**/server/**"],
457
+ ignoreEntries: ["**/server/**"],
458
+ meteorIgnoreEntries,
448
459
  prefix: "client",
460
+ globalImportPath: path.resolve(projectDir, buildContext, entryPath),
449
461
  })
450
- : isTest && testEntry
462
+ : isClient && isTest && testEntry
451
463
  ? path.resolve(process.cwd(), testEntry)
452
464
  : path.resolve(process.cwd(), buildContext, entryPath);
453
465
  const clientNameConfig = `[${(isTest && 'test-') || ''}client-rspack]`;
@@ -541,30 +553,42 @@ module.exports = async function (inMeteor = {}, argv = {}) {
541
553
  writeToDisk: filePath =>
542
554
  /\.(html)$/.test(filePath) && !filePath.includes('.hot-update.'),
543
555
  },
556
+ onListening(devServer) {
557
+ if (!devServer) return;
558
+ const { host, port } = devServer.options;
559
+ const protocol = devServer.options.server?.type === "https" ? "https" : "http";
560
+ const devServerUrl = `${protocol}://${host || "localhost"}:${port}`;
561
+ outputMeteorRspack({ devServerUrl });
562
+ },
544
563
  },
545
564
  }),
546
565
  ...merge(cacheStrategy, { experiments: { css: true } }),
547
566
  ...lazyCompilationConfig,
567
+ ...loggingConfig,
548
568
  };
549
569
 
550
570
  const serverEntry =
551
- isTest && isTestEager && isTestFullApp
571
+ isServer && isTest && isTestEager && isTestFullApp
552
572
  ? generateEagerTestFile({
553
573
  isAppTest: true,
554
574
  projectDir,
555
575
  buildContext,
556
- ignoreEntries: [...meteorIgnoreEntries, "**/client/**"],
576
+ ignoreEntries: ["**/client/**"],
577
+ meteorIgnoreEntries,
557
578
  prefix: "server",
579
+ globalImportPath: path.resolve(projectDir, buildContext, entryPath),
558
580
  })
559
- : isTest && isTestEager
581
+ : isServer && isTest && isTestEager
560
582
  ? generateEagerTestFile({
561
583
  isAppTest: false,
562
584
  projectDir,
563
585
  buildContext,
564
- ignoreEntries: [...meteorIgnoreEntries, "**/client/**"],
586
+ ignoreEntries: ["**/client/**"],
587
+ meteorIgnoreEntries,
565
588
  prefix: "server",
589
+ globalImportPath: path.resolve(projectDir, buildContext, entryPath),
566
590
  })
567
- : isTest && testEntry
591
+ : isServer && isTest && testEntry
568
592
  ? path.resolve(process.cwd(), testEntry)
569
593
  : path.resolve(projectDir, buildContext, entryPath);
570
594
  const serverNameConfig = `[${(isTest && 'test-') || ''}server-rspack]`;
@@ -631,6 +655,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
631
655
  ...((isDevEnvironment || (isTest && !isTestEager) || isNative) &&
632
656
  cacheStrategy),
633
657
  ...lazyCompilationConfig,
658
+ ...loggingConfig,
634
659
  };
635
660
 
636
661
  // Helper function to load and process config files
@@ -690,6 +715,8 @@ module.exports = async function (inMeteor = {}, argv = {}) {
690
715
  // Load and apply project-level overrides for the selected build
691
716
  // Check if we're in a Meteor package directory by looking at the path
692
717
  const isMeteorPackageConfig = projectDir.includes('/packages/rspack');
718
+ // Track if user config overrides stats and infrastructureLogging
719
+ let statsOverrided = false;
693
720
  if (fs.existsSync(projectConfigPath) && !isMeteorPackageConfig) {
694
721
  // Check if there's a .mjs or .cjs version of the config file
695
722
  const mjsConfigPath = projectConfigPath.replace(/\.js$/, '.mjs');
@@ -710,7 +737,11 @@ module.exports = async function (inMeteor = {}, argv = {}) {
710
737
  isAngularEnabled
711
738
  );
712
739
 
740
+ // Track if user config overrides stats
713
741
  if (nextUserConfig) {
742
+ if (nextUserConfig.stats != null) {
743
+ statsOverrided = true;
744
+ }
714
745
  if (Meteor.isClient) {
715
746
  clientConfig = mergeSplitOverlap(clientConfig, nextUserConfig);
716
747
  }
@@ -801,5 +832,20 @@ module.exports = async function (inMeteor = {}, argv = {}) {
801
832
  );
802
833
  }
803
834
 
835
+ // Add MeteorRspackOutputPlugin as the last plugin to output compilation info
836
+ const meteorRspackOutputPlugin = new MeteorRspackOutputPlugin({
837
+ getData: (stats, { isRebuild, compilationCount }) => ({
838
+ name: config.name,
839
+ mode: config.mode,
840
+ hasErrors: stats.hasErrors(),
841
+ hasWarnings: stats.hasWarnings(),
842
+ timestamp: Date.now(),
843
+ statsOverrided,
844
+ compilationCount,
845
+ isRebuild,
846
+ }),
847
+ });
848
+ config.plugins = [meteorRspackOutputPlugin, ...(config.plugins || [])];
849
+
804
850
  return [config];
805
851
  }