mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
ensure distinguish between test module and test for client and server
This commit is contained in:
@@ -116,6 +116,7 @@ export default function (inMeteor = {}, argv = {}) {
|
||||
const isClient = Meteor.isClient;
|
||||
const isRun = Meteor.isRun;
|
||||
const isReactEnabled = Meteor.isReactEnabled;
|
||||
const isTestModule = Meteor.isTestModule;
|
||||
const mode = isProd ? 'production' : 'development';
|
||||
|
||||
const isTypescriptEnabled = Meteor.isTypescriptEnabled || false;
|
||||
@@ -185,9 +186,26 @@ export default function (inMeteor = {}, argv = {}) {
|
||||
|
||||
const reactRefreshModule = isReactEnabled ? safeRequire('@rspack/plugin-react-refresh') : null;
|
||||
|
||||
const requireExternalsPlugin = new RequireExternalsPlugin({
|
||||
filePath: path.join(buildContext, runPath),
|
||||
...(Meteor.isBlazeEnabled && {
|
||||
externals: /\.html$/,
|
||||
externalMap: (module) => {
|
||||
const { request, context } = module;
|
||||
if (request.endsWith('.html')) {
|
||||
const relContext = path.relative(process.cwd(), context);
|
||||
const { name } = path.parse(request);
|
||||
return `./${relContext}/template.${name}.js`;
|
||||
}
|
||||
return request;
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const clientNameConfig = `[${isTest && 'test-' || ''}${isTestModule && 'module' || 'client'}-rspack]`;
|
||||
// Base client config
|
||||
let clientConfig = {
|
||||
name: '[client-rspack]',
|
||||
name: clientNameConfig,
|
||||
target: 'web',
|
||||
mode,
|
||||
entry: path.resolve(process.cwd(), buildContext, entryPath),
|
||||
@@ -221,28 +239,12 @@ export default function (inMeteor = {}, argv = {}) {
|
||||
resolve: { extensions, alias },
|
||||
externals,
|
||||
plugins: [
|
||||
...(isRun
|
||||
? [
|
||||
...(isReactEnabled && reactRefreshModule
|
||||
? [new reactRefreshModule()]
|
||||
: []),
|
||||
new RequireExternalsPlugin({
|
||||
filePath: path.join(buildContext, runPath),
|
||||
...(Meteor.isBlazeEnabled && {
|
||||
externals: /\.html$/,
|
||||
externalMap: (module) => {
|
||||
const { request, context } = module;
|
||||
if (request.endsWith('.html')) {
|
||||
const relContext = path.relative(process.cwd(), context);
|
||||
const { name } = path.parse(request);
|
||||
return `./${relContext}/template.${name}.js`;
|
||||
}
|
||||
return request;
|
||||
},
|
||||
}),
|
||||
}),
|
||||
].filter(Boolean)
|
||||
: []),
|
||||
...[
|
||||
...(isReactEnabled && reactRefreshModule
|
||||
? [new reactRefreshModule()]
|
||||
: []),
|
||||
requireExternalsPlugin,
|
||||
].filter(Boolean),
|
||||
new DefinePlugin({
|
||||
'Meteor.isClient': JSON.stringify(true),
|
||||
'Meteor.isServer': JSON.stringify(false),
|
||||
@@ -271,9 +273,10 @@ export default function (inMeteor = {}, argv = {}) {
|
||||
}),
|
||||
};
|
||||
|
||||
const serverNameConfig = `[${isTest && 'test-' || ''}${isTestModule && 'module' || 'server'}-rspack]`;
|
||||
// Base server config
|
||||
let serverConfig = {
|
||||
name: '[server-rspack]',
|
||||
name: serverNameConfig,
|
||||
target: 'node',
|
||||
mode,
|
||||
entry: path.resolve(process.cwd(), buildContext, entryPath),
|
||||
@@ -313,6 +316,7 @@ export default function (inMeteor = {}, argv = {}) {
|
||||
banner: bannerOutput,
|
||||
entryOnly: true,
|
||||
}),
|
||||
isTestModule && requireExternalsPlugin,
|
||||
],
|
||||
watchOptions,
|
||||
devtool: isRun ? 'source-map' : 'hidden-source-map',
|
||||
|
||||
@@ -107,12 +107,17 @@ export function ensureModuleFilesExist() {
|
||||
entryFile: initialEntrypoints.mainServer || '',
|
||||
outputFile: getBuildFilePath({ isMain: true, isServer: true, ...env, role: FILE_ROLE.output, onlyFilename: true }),
|
||||
};
|
||||
const testClientFiles = {
|
||||
entryFile: initialEntrypoints.testClient || initialEntrypoints.testModule || '',
|
||||
const isTestModule = initialEntrypoints.testModule != null;
|
||||
const testModuleFiles = {
|
||||
entryFile: initialEntrypoints.testModule || '',
|
||||
outputFile: getBuildFilePath({ isTest: true, isTestModule: true, role: FILE_ROLE.output, onlyFilename: true }),
|
||||
};
|
||||
const testClientFiles = isTestModule ? null : {
|
||||
entryFile: initialEntrypoints.testClient || '',
|
||||
outputFile: getBuildFilePath({ isTest: true, isClient: true, role: FILE_ROLE.output, onlyFilename: true }),
|
||||
};
|
||||
const testServerFiles = {
|
||||
entryFile: initialEntrypoints.testServer || initialEntrypoints.testModule || '',
|
||||
const testServerFiles = isTestModule ? null : {
|
||||
entryFile: initialEntrypoints.testServer || '',
|
||||
outputFile: getBuildFilePath({ isTest: true, isServer: true, role: FILE_ROLE.output, onlyFilename: true }),
|
||||
};
|
||||
|
||||
@@ -131,18 +136,27 @@ export function ensureModuleFilesExist() {
|
||||
[getBuildFilePath({ isMain: true, isServer: true, ...env, role: FILE_ROLE.output })]:
|
||||
getBuildFileContent({ isMain: true, isServer: true, ...env, role: FILE_ROLE.output, ...mainServerFiles }),
|
||||
/* Test module files for client and server */
|
||||
[getBuildFilePath({ isTest: true, isClient: true, ...commandRole })]:
|
||||
getBuildFileContent({ isTest: true, isClient: true, ...commandRole, ...testClientFiles }),
|
||||
[getBuildFilePath({ isTest: true, isClient: true, role: FILE_ROLE.entry })]:
|
||||
getBuildFileContent({ isTest: true, isClient: true, role: FILE_ROLE.entry, ...testClientFiles }),
|
||||
[getBuildFilePath({ isTest: true, isClient: true, role: FILE_ROLE.output })]:
|
||||
getBuildFileContent({ isTest: true, isClient: true, role: FILE_ROLE.output, ...testClientFiles }),
|
||||
[getBuildFilePath({ isTest: true, isServer: true, ...commandRole })]:
|
||||
getBuildFileContent({ isTest: true, isServer: true, ...commandRole, ...testServerFiles }),
|
||||
[getBuildFilePath({ isTest: true, isServer: true, role: FILE_ROLE.entry })]:
|
||||
getBuildFileContent({ isTest: true, isServer: true, role: FILE_ROLE.entry, ...testServerFiles }),
|
||||
[getBuildFilePath({ isTest: true, isServer: true, role: FILE_ROLE.output })]:
|
||||
getBuildFileContent({ isTest: true, isServer: true, role: FILE_ROLE.output, ...testServerFiles }),
|
||||
...(isTestModule && {
|
||||
[getBuildFilePath({ isTest: true, isTestModule: true, ...commandRole })]:
|
||||
getBuildFileContent({ isTest: true, isTestModule: true, ...commandRole, ...testModuleFiles }),
|
||||
[getBuildFilePath({ isTest: true, isTestModule: true, role: FILE_ROLE.entry })]:
|
||||
getBuildFileContent({ isTest: true, isTestModule: true, role: FILE_ROLE.entry, ...testModuleFiles }),
|
||||
[getBuildFilePath({ isTest: true, isTestModule: true, role: FILE_ROLE.output })]:
|
||||
getBuildFileContent({ isTest: true, isTestModule: true, role: FILE_ROLE.output, ...testModuleFiles }),
|
||||
} || {
|
||||
[getBuildFilePath({ isTest: true, isClient: true, ...commandRole })]:
|
||||
getBuildFileContent({ isTest: true, isClient: true, ...commandRole, ...testClientFiles }),
|
||||
[getBuildFilePath({ isTest: true, isClient: true, role: FILE_ROLE.entry })]:
|
||||
getBuildFileContent({ isTest: true, isClient: true, role: FILE_ROLE.entry, ...testClientFiles }),
|
||||
[getBuildFilePath({ isTest: true, isClient: true, role: FILE_ROLE.output })]:
|
||||
getBuildFileContent({ isTest: true, isClient: true, role: FILE_ROLE.output, ...testClientFiles }),
|
||||
[getBuildFilePath({ isTest: true, isServer: true, ...commandRole })]:
|
||||
getBuildFileContent({ isTest: true, isServer: true, ...commandRole, ...testServerFiles }),
|
||||
[getBuildFilePath({ isTest: true, isServer: true, role: FILE_ROLE.entry })]:
|
||||
getBuildFileContent({ isTest: true, isServer: true, role: FILE_ROLE.entry, ...testServerFiles }),
|
||||
[getBuildFilePath({ isTest: true, isServer: true, role: FILE_ROLE.output })]:
|
||||
getBuildFileContent({ isTest: true, isServer: true, role: FILE_ROLE.output, ...testServerFiles }),
|
||||
}),
|
||||
};
|
||||
|
||||
Object.entries(moduleFiles).forEach(([filename, defaultContent]) => {
|
||||
@@ -190,7 +204,7 @@ export function ensureModuleFilesExist() {
|
||||
|
||||
export function getBuildFilePath(config) {
|
||||
const module = config?.isTest ? 'test' : config?.isMain ? 'main' : '';
|
||||
const side = config?.isServer ? 'server' : config?.isClient ? 'client' : '';
|
||||
const side = config?.isTestModule ? 'test' : config?.isServer ? 'server' : config?.isClient ? 'client' : '';
|
||||
const env = config?.isTest
|
||||
? ''
|
||||
: config?.isDevelopment
|
||||
@@ -213,7 +227,7 @@ export function getBuildFilePath(config) {
|
||||
|
||||
export function getBuildFileContent(config) {
|
||||
const module = config?.isTest ? 'test' : config?.isMain ? 'main' : '';
|
||||
const side = config?.isServer ? 'server' : config?.isClient ? 'client' : '';
|
||||
const side = config?.isTestModule ? 'test' : config?.isServer ? 'server' : config?.isClient ? 'client' : '';
|
||||
const env = config?.isDevelopment ? 'development' : config?.isProduction ? 'production' : '';
|
||||
const role = config?.role;
|
||||
|
||||
|
||||
@@ -63,13 +63,14 @@ export function configureMeteorForRSPack() {
|
||||
const mainClientModule = getBuildFilePath({ isMain: true, ...env, ...commandRole, isClient: true });
|
||||
const mainServerModule = getBuildFilePath({ isMain: true, ...env, ...commandRole, isServer: true });
|
||||
const testClientModule = getBuildFilePath({ isTest: true, ...env, ...commandRole, isClient: true });
|
||||
const testServerModule = getBuildFilePath({ isTest: true, ...env, ...commandRole, isServer: true });
|
||||
const isTestModule = initialEntrypoints.testModule != null;
|
||||
const testServerModule = getBuildFilePath({ isTest: true, ...env, ...commandRole, isTestModule, isServer: true });
|
||||
|
||||
// Set entry points in environment variables if they exist
|
||||
setMeteorAppEntrypoints({
|
||||
mainClient: `${RSPACK_BUILD_CONTEXT}/${mainClientModule}`,
|
||||
mainServer: `${RSPACK_BUILD_CONTEXT}/${mainServerModule}`,
|
||||
...(initialEntrypoints.testModule && {
|
||||
...(isTestModule && {
|
||||
testModule: `${RSPACK_BUILD_CONTEXT}/${testServerModule}`,
|
||||
} || {
|
||||
testClient: `${RSPACK_BUILD_CONTEXT}/${testClientModule}`,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
* @module processes
|
||||
* @description Functions for managing RSPack processes
|
||||
*/
|
||||
import { RSPACK_BUILD_CONTEXT } from "./constants";
|
||||
import { getMeteorAppEntrypoints } from "../../tools-core/lib/meteor";
|
||||
|
||||
const {
|
||||
spawnProcess,
|
||||
@@ -28,6 +26,7 @@ const {
|
||||
isMeteorBlazeProject,
|
||||
isMeteorBlazeHotProject,
|
||||
getMeteorInitialAppEntrypoints,
|
||||
isMeteorAppTestModule,
|
||||
} = require('meteor/tools-core/lib/meteor');
|
||||
|
||||
const {
|
||||
@@ -65,20 +64,23 @@ export function getConfigFileName() {
|
||||
export function getRSPackEnv({ isClient, isServer }) {
|
||||
const RSPACK_BUILD_CONTEXT = require('./constants').RSPACK_BUILD_CONTEXT;
|
||||
|
||||
const initialEntrypoints = getMeteorInitialAppEntrypoints();
|
||||
const isTest = isMeteorAppTest();
|
||||
const isTestModule = initialEntrypoints.testModule != null;
|
||||
|
||||
const module = isMeteorAppTest() ? { isTest: true } : { isMain: true };
|
||||
const env = isMeteorAppDevelopment()
|
||||
? { isDevelopment: true }
|
||||
: { isProduction: true };
|
||||
const side = isClient ? { isClient: true } : { isServer: true };
|
||||
const side = isTest && isTestModule ? { isTestModule: true } : isClient ? { isClient: true } : { isServer: true };
|
||||
const commandRole = isMeteorAppRun()
|
||||
? { role: FILE_ROLE.run }
|
||||
: isMeteorAppBuild()
|
||||
? { role: FILE_ROLE.build }
|
||||
: { role: FILE_ROLE.run };
|
||||
|
||||
const initialEntrypoints = getMeteorInitialAppEntrypoints();
|
||||
const entryKey = `${isMeteorAppTest() ? 'test' : 'main'}${isClient ? 'Client' : 'Server'}`;
|
||||
const inputFilePath = initialEntrypoints[entryKey] || `testModule`;
|
||||
const entryKey = `${isTest && isTestModule ? 'test' : 'main'}${isClient ? 'Client' : 'Server'}`;
|
||||
const inputFilePath = isTest && isTestModule ? initialEntrypoints.testModule : initialEntrypoints[entryKey];
|
||||
const isTypescriptEnabled = inputFilePath.endsWith('.ts') || inputFilePath.endsWith('.tsx');
|
||||
const isTsxEnabled = inputFilePath.endsWith('.tsx');
|
||||
const isJsxEnabled = inputFilePath.endsWith('.jsx');
|
||||
@@ -88,6 +90,7 @@ export function getRSPackEnv({ isClient, isServer }) {
|
||||
['isProduction', isMeteorAppProduction()],
|
||||
['isDebug', isMeteorAppDebug()],
|
||||
['isTest', isMeteorAppTest()],
|
||||
['isTestModule', isTestModule],
|
||||
['isRun', isMeteorAppRun()],
|
||||
['isBuild', isMeteorAppBuild()],
|
||||
['isClient', isClient],
|
||||
@@ -140,9 +143,6 @@ export function startRSPackClientServe(options = {}) {
|
||||
|
||||
const appDir = getMeteorAppDir();
|
||||
const configFile = getConfigFileName();
|
||||
|
||||
logProgress(`[RSPack Client] Starting RSPack serve for client...`);
|
||||
|
||||
const newClientProcess = spawnProcess(
|
||||
'npx',
|
||||
['rspack', 'serve', '--config', configFile, ...getRSPackEnv({ isClient: true, isServer: false })], {
|
||||
@@ -195,9 +195,6 @@ export function startRSPackServerWatch(options = {}) {
|
||||
|
||||
const appDir = getMeteorAppDir();
|
||||
const configFile = getConfigFileName();
|
||||
|
||||
logProgress(`[RSPack Server] Starting RSPack for server...`);
|
||||
|
||||
const newServerProcess = spawnProcess(
|
||||
'npx',
|
||||
['rspack', 'build', '--watch', '--config', configFile, ...getRSPackEnv({ isClient: false, isServer: true })], {
|
||||
@@ -232,18 +229,17 @@ export function startRSPackServerWatch(options = {}) {
|
||||
* @param {Object} options - Options for the build
|
||||
* @param {boolean} options.isClient - Whether this is a client build
|
||||
* @param {boolean} options.isServer - Whether this is a server build
|
||||
* @param {boolean} options.isTestModule - Whether this is a test module
|
||||
* @param {Function} options.onCompile - Callback function to be called when compilation is complete
|
||||
* @param {boolean} options.watch - Whether to run RSPack in watch mode
|
||||
* @returns {Promise<void>} A promise that resolves when the build is complete
|
||||
* @throws {Error} If the build process fails
|
||||
*/
|
||||
export async function runRSPackBuild({ isClient, isServer, onCompile, watch } = {}) {
|
||||
export async function runRSPackBuild({ isClient, isServer, isTestModule, onCompile, watch, label = 'Build' } = {}) {
|
||||
const appDir = getMeteorAppDir();
|
||||
const configFile = getConfigFileName();
|
||||
|
||||
const endpoint = isClient ? 'Client' : 'Server';
|
||||
|
||||
logProgress(`Running RSPack build for ${endpoint}...`);
|
||||
const endpoint = isTestModule ? 'Module' : isClient ? 'Client' : 'Server';
|
||||
// Use a promise to ensure Meteor waits until RSPack finishes
|
||||
return new Promise((resolve, reject) => {
|
||||
spawnProcess(
|
||||
@@ -254,12 +250,12 @@ export async function runRSPackBuild({ isClient, isServer, onCompile, watch } =
|
||||
'--config',
|
||||
configFile,
|
||||
...(watch && ['--watch']) || [],
|
||||
...getRSPackEnv({ isClient, isServer }),
|
||||
...getRSPackEnv({ isClient, isServer, isTestModule }),
|
||||
].filter(Boolean),
|
||||
{
|
||||
cwd: appDir,
|
||||
onStdout: (data) => {
|
||||
logInfo(`[RSPack Build ${endpoint}] ${data}`);
|
||||
logInfo(`[RSPack ${label} ${endpoint}] ${data}`);
|
||||
if (onCompile && data.trim().includes("compiled")) {
|
||||
onCompile(data);
|
||||
}
|
||||
@@ -267,22 +263,22 @@ export async function runRSPackBuild({ isClient, isServer, onCompile, watch } =
|
||||
onStderr: (data) => {
|
||||
// Check if this is actually an informational message (like webpack-dev-server messages)
|
||||
if (data.includes('Project is running at:')) {
|
||||
logInfo(`[RSPack Build ${endpoint}] ${data}`);
|
||||
logInfo(`[RSPack ${label} ${endpoint}] ${data}`);
|
||||
} else {
|
||||
logError(`[RSPack Build Error ${endpoint}] ${data}`);
|
||||
logError(`[RSPack ${label} Error ${endpoint}] ${data}`);
|
||||
}
|
||||
},
|
||||
onExit: (code) => {
|
||||
if (code === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
const error = new Error(`RSPack build failed in ${endpoint} with exit code ${code}`);
|
||||
const error = new Error(`RSPack ${label} failed in ${endpoint} with exit code ${code}`);
|
||||
logError(error.message);
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
onError: (err) => {
|
||||
logError(`RSPack Build ${endpoint} error: ${err.message}`);
|
||||
logError(`RSPack ${label} ${endpoint} error: ${err.message}`);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -130,10 +130,12 @@ try {
|
||||
|
||||
if (initialEntrypoints?.testModule) {
|
||||
runRSPackBuild({
|
||||
isServer: true,
|
||||
isTestModule: true,
|
||||
isClient: false,
|
||||
isServer: true,
|
||||
watch: isMeteorAppTestWatch(),
|
||||
onCompile: onCompileServer,
|
||||
label: 'Test',
|
||||
});
|
||||
await waitForFirstCompilation(clientFirstCompile, serverFirstCompile, clientFirstCompilePromise, serverFirstCompilePromise, { target: 'server' });
|
||||
} else if (initialEntrypoints?.testModule?.client || initialEntrypoints?.testModule?.server) {
|
||||
@@ -142,6 +144,7 @@ try {
|
||||
isServer: false,
|
||||
watch: isMeteorAppTestWatch(),
|
||||
onCompile: onCompileClient,
|
||||
label: 'Test',
|
||||
});
|
||||
|
||||
runRSPackBuild({
|
||||
@@ -149,6 +152,7 @@ try {
|
||||
isClient: false,
|
||||
watch: isMeteorAppTestWatch(),
|
||||
onCompile: onCompileServer,
|
||||
label: 'Test',
|
||||
});
|
||||
|
||||
// Wait for first compilation to complete
|
||||
|
||||
@@ -73,6 +73,14 @@ export function getMeteorInitialAppEntrypoints() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current Meteor project is configured as test module.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isMeteorAppTestModule() {
|
||||
return getMeteorInitialAppEntrypoints().testModule != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Meteor application entry points in environment variables.
|
||||
* @param {Object} options - The entry points configuration object.
|
||||
|
||||
Reference in New Issue
Block a user