diff --git a/changelog.md b/changelog.md index a52368a..27b758e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2025-06-19 - 2.4.0 - feat(bundler) +Introduce rspack bundler support and update multi-bundler workflow + +- Added full support for rspack with its own implementation in ts/mod_rspack +- Updated package.json: new dependency on @rspack/core and revised description +- Refactored bundler types and switch statement to remove deprecated rollup and parcel options +- Modified test suite to include tests for esbuild, rolldown, and rspack with bundle size comparisons +- Adjusted output configuration for esbuild and rolldown for dynamic naming and inline dynamic imports + ## 2025-06-19 - 2.3.0 - feat(bundler) Integrate rolldown bundler support and update bundler selection logic diff --git a/package.json b/package.json index d1b772b..3436e02 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,14 @@ "name": "@git.zone/tsbundle", "version": "2.3.0", "private": false, - "description": "a bundler using rollup for painless bundling of web projects", + "description": "a multi-bundler tool supporting esbuild, rolldown, and rspack for painless bundling of web projects", "main": "dist_ts/index.js", "typings": "dist_ts/index.d.ts", "type": "module", "author": "Lossless GmbH", "license": "MIT", "scripts": { - "test": "npm run build && (tstest test/) && (cd test && node ../cli.js --production)", + "test": "npm run build && (tstest test/ --verbose)", "build": "(tsbuild --web --allowimplicitany)" }, "bin": { @@ -36,6 +36,7 @@ "esbuild": "^0.25.5", "html-minifier": "^4.0.0", "rolldown": "^1.0.0-beta.18", + "@rspack/core": "^1.1.8", "typescript": "5.8.3" }, "files": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 079c4ed..003c011 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: '@push.rocks/smartspawn': specifier: ^3.0.3 version: 3.0.3 + '@rspack/core': + specifier: ^1.1.8 + version: 1.3.15 '@types/html-minifier': specifier: ^4.0.5 version: 4.0.5 @@ -804,6 +807,24 @@ packages: '@mixmark-io/domino@2.2.0': resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} + '@module-federation/error-codes@0.14.3': + resolution: {integrity: sha512-sBJ3XKU9g5Up31jFeXPFsD8AgORV7TLO/cCSMuRewSfgYbG/3vSKLJmfHrO6+PvjZSb9VyV2UaF02ojktW65vw==} + + '@module-federation/runtime-core@0.14.3': + resolution: {integrity: sha512-xMFQXflLVW/AJTWb4soAFP+LB4XuhE7ryiLIX8oTyUoBBgV6U2OPghnFljPjeXbud72O08NYlQ1qsHw1kN/V8Q==} + + '@module-federation/runtime-tools@0.14.3': + resolution: {integrity: sha512-QBETX7iMYXdSa3JtqFlYU+YkpymxETZqyIIRiqg0gW+XGpH3jgU68yjrme2NBJp7URQi/CFZG8KWtfClk0Pjgw==} + + '@module-federation/runtime@0.14.3': + resolution: {integrity: sha512-7ZHpa3teUDVhraYdxQGkfGHzPbjna4LtwbpudgzAxSLLFxLDNanaxCuSeIgSM9c+8sVUNC9kvzUgJEZB0krPJw==} + + '@module-federation/sdk@0.14.3': + resolution: {integrity: sha512-THJZMfbXpqjQOLblCQ8jjcBFFXsGRJwUWE9l/Q4SmuCSKMgAwie7yLT0qSGrHmyBYrsUjAuy+xNB4nfKP0pnGw==} + + '@module-federation/webpack-bundler-runtime@0.14.3': + resolution: {integrity: sha512-hIyJFu34P7bY2NeMIUHAS/mYUHEY71VTAsN0A0AqEJFSVPszheopu9VdXq0VDLrP9KQfuXT8SDxeYeJXyj0mgA==} + '@mongodb-js/saslprep@1.3.0': resolution: {integrity: sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==} @@ -1293,6 +1314,67 @@ packages: '@rolldown/pluginutils@1.0.0-beta.18': resolution: {integrity: sha512-sHG++r1AOeQrzp0Lm3w9TBuaMHty3rU4yCZ4Vd/s428dvv3eTIhuRqHPHJCBlVpZjOJ5b4ZcBPTyRCsDKFt2+w==} + '@rspack/binding-darwin-arm64@1.3.15': + resolution: {integrity: sha512-f+DnVRENRdVe+ufpZeqTtWAUDSTnP48jVo7x9KWsXf8XyJHUi+eHKEPrFoy1HvL1/k5yJ3HVnFBh1Hb9cNIwSg==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.3.15': + resolution: {integrity: sha512-TfUvEIBqYUT2OK01BYXb2MNcZeZIhAnJy/5aj0qV0uy4KlvwW63HYcKWa1sFd4Ac7bnGShDkanvP3YEuHOFOyg==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-linux-arm64-gnu@1.3.15': + resolution: {integrity: sha512-D/YjYk9snKvYm1Elotq8/GsEipB4ZJWVv/V8cZ+ohhFNOPzygENi6JfyI06TryBTQiN0/JDZqt/S9RaWBWnMqw==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-arm64-musl@1.3.15': + resolution: {integrity: sha512-lJbBsPMOiR0hYPCSM42yp7QiZjfo0ALtX7ws2wURpsQp3BMfRVAmXU3Ixpo2XCRtG1zj8crHaCmAWOJTS0smsA==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-x64-gnu@1.3.15': + resolution: {integrity: sha512-qGB8ucHklrzNg6lsAS36VrBsCbOw0acgpQNqTE5cuHWrp1Pu3GFTRiFEogenxEmzoRbohMZt0Ev5grivrcgKBQ==} + cpu: [x64] + os: [linux] + + '@rspack/binding-linux-x64-musl@1.3.15': + resolution: {integrity: sha512-qRn6e40fLQP+N2rQD8GAj/h4DakeTIho32VxTIaHRVuzw68ZD7VmKkwn55ssN370ejmey35ZdoNFNE12RBrMZA==} + cpu: [x64] + os: [linux] + + '@rspack/binding-win32-arm64-msvc@1.3.15': + resolution: {integrity: sha512-7uJ7dWhO1nWXJiCss6Rslz8hoAxAhFpwpbWja3eHgRb7O4NPHg6MWw63AQSI2aFVakreenfu9yXQqYfpVWJ2dA==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.3.15': + resolution: {integrity: sha512-UsaWTYCjDiSCB0A0qETgZk4QvhwfG8gCrO4SJvA+QSEWOmgSai1YV70prFtLLIiyT9mDt1eU3tPWl1UWPRU/EQ==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.3.15': + resolution: {integrity: sha512-ZnDIc9Es8EF94MirPDN+hOMt7tkb8nMEbRJFKLMmNd0ElNPgsql+1cY5SqyGRH1hsKB87KfSUQlhFiKZvzbfIg==} + cpu: [x64] + os: [win32] + + '@rspack/binding@1.3.15': + resolution: {integrity: sha512-utNPuJglLO5lW9XbwIqjB7+2ilMo6JkuVLTVdnNVKU94FW7asn9F/qV+d+MgjUVqU1QPCGm0NuGO9xhbgeJ7pg==} + + '@rspack/core@1.3.15': + resolution: {integrity: sha512-QuElIC8jXSKWAp0LSx18pmbhA7NiA5HGoVYesmai90UVxz98tud0KpMxTVCg+0lrLrnKZfCWN9kwjCxM5pGnrA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/lite-tapable@1.0.1': + resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} + engines: {node: '>=16.0.0'} + '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -5642,6 +5724,31 @@ snapshots: '@mixmark-io/domino@2.2.0': {} + '@module-federation/error-codes@0.14.3': {} + + '@module-federation/runtime-core@0.14.3': + dependencies: + '@module-federation/error-codes': 0.14.3 + '@module-federation/sdk': 0.14.3 + + '@module-federation/runtime-tools@0.14.3': + dependencies: + '@module-federation/runtime': 0.14.3 + '@module-federation/webpack-bundler-runtime': 0.14.3 + + '@module-federation/runtime@0.14.3': + dependencies: + '@module-federation/error-codes': 0.14.3 + '@module-federation/runtime-core': 0.14.3 + '@module-federation/sdk': 0.14.3 + + '@module-federation/sdk@0.14.3': {} + + '@module-federation/webpack-bundler-runtime@0.14.3': + dependencies: + '@module-federation/runtime': 0.14.3 + '@module-federation/sdk': 0.14.3 + '@mongodb-js/saslprep@1.3.0': dependencies: sparse-bitfield: 3.0.3 @@ -6651,6 +6758,53 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.18': {} + '@rspack/binding-darwin-arm64@1.3.15': + optional: true + + '@rspack/binding-darwin-x64@1.3.15': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.3.15': + optional: true + + '@rspack/binding-linux-arm64-musl@1.3.15': + optional: true + + '@rspack/binding-linux-x64-gnu@1.3.15': + optional: true + + '@rspack/binding-linux-x64-musl@1.3.15': + optional: true + + '@rspack/binding-win32-arm64-msvc@1.3.15': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.3.15': + optional: true + + '@rspack/binding-win32-x64-msvc@1.3.15': + optional: true + + '@rspack/binding@1.3.15': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.3.15 + '@rspack/binding-darwin-x64': 1.3.15 + '@rspack/binding-linux-arm64-gnu': 1.3.15 + '@rspack/binding-linux-arm64-musl': 1.3.15 + '@rspack/binding-linux-x64-gnu': 1.3.15 + '@rspack/binding-linux-x64-musl': 1.3.15 + '@rspack/binding-win32-arm64-msvc': 1.3.15 + '@rspack/binding-win32-ia32-msvc': 1.3.15 + '@rspack/binding-win32-x64-msvc': 1.3.15 + + '@rspack/core@1.3.15': + dependencies: + '@module-federation/runtime-tools': 0.14.3 + '@rspack/binding': 1.3.15 + '@rspack/lite-tapable': 1.0.1 + + '@rspack/lite-tapable@1.0.1': {} + '@sec-ant/readable-stream@0.4.1': {} '@sinclair/typebox@0.27.8': {} diff --git a/readme.hints.md b/readme.hints.md index 01d3333..150cf55 100644 --- a/readme.hints.md +++ b/readme.hints.md @@ -6,10 +6,11 @@ - The main class `TsBundle` spawns child processes using `smartspawn.ThreadSimple` ## Bundler Implementations -- **esbuild** (default): Fully implemented, production ready -- **rolldown**: Implemented and working (beta), produces smaller bundles than esbuild -- **rollup**: Empty module directory exists but not implemented -- **parcel**: Empty module directory exists but not implemented +- **esbuild** (default): Fully implemented, production ready, 2.2K minified +- **rolldown**: Implemented and working (beta), produces smallest bundles (1.5K minified) +- **rspack**: Implemented and working, webpack-compatible API, 6.1K minified +- **rollup**: Removed (was never implemented) +- **parcel**: Removed (was never implemented) ## Adding New Bundlers To add a new bundler, you need: @@ -24,12 +25,22 @@ To add a new bundler, you need: - Rolldown is in beta (v1.0.0-beta.18) but working well - API: Use `rolldown()` function directly, not `rolldown.rolldown()` - Output options go in the `write()` method, not the initial config +- Uses `dir` and `entryFileNames` instead of `file` for output (handles dynamic imports) +- Includes `inlineDynamicImports: true` to avoid chunk splitting issues - Produces smaller minified bundles than esbuild (1.5K vs 2.2K in tests) - Supports TypeScript via `resolve.tsconfigFilename` +## Rspack Specific Notes +- Rspack v1.3.15 - stable and production ready +- Uses webpack-compatible API (callback-based) +- Built-in SWC loader for TypeScript transpilation +- Produces larger bundles than esbuild/rolldown due to webpack runtime overhead +- Best choice if you need webpack compatibility or advanced features +- Supports ES modules output via `experiments.outputModule: true` + ## CLI Usage -- Default bundler: `tsbundle` -- Specify bundler: `tsbundle --bundler=rolldown` +- Default bundler: `tsbundle` (uses esbuild) +- Specify bundler: `tsbundle --bundler=rolldown` or `tsbundle --bundler=rspack` - Production mode: `tsbundle --production` - Combined: `tsbundle --bundler=rolldown --production` diff --git a/test/test.ts b/test/test.ts index 99420d4..c19b094 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,17 +1,108 @@ -import { expect, tap } from '@push.rocks/tapbundle'; -import * as tsbundle from '../ts/index.js'; +import { expect, tap } from '@git.zone/tstest/tapbundle'; +import * as tsbundle from '../dist_ts/index.js'; +import * as path from 'path'; +import * as fs from 'fs'; + +const testBundler = async (bundlerName: 'esbuild' | 'rolldown' | 'rspack', mode: 'test' | 'production') => { + const outputFile = `./dist_manual/${bundlerName}-${mode}.js`; + const testDir = path.join(process.cwd(), 'test'); + + // Clean up output directory + const outputDir = path.join(testDir, 'dist_manual'); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + // Clean up output file if exists + const outputPath = path.join(testDir, outputFile); + if (fs.existsSync(outputPath)) { + fs.rmSync(outputPath, { force: true }); + } -tap.test('should bundle with esbuild', async () => { const tsbundleInstance = new tsbundle.TsBundle(); await tsbundleInstance.build( - process.cwd() + '/test', + testDir, './ts_web/index.ts', - './dist_manual/test.js', + outputFile, { - bundler: 'esbuild' + bundler: bundlerName, + production: mode === 'production' } ); + + // Verify output file was created + expect(fs.existsSync(outputPath)).toBeTrue(); + + console.log(`āœ… ${bundlerName} ${mode} mode: success`); +}; + +// Test esbuild +tap.test('should bundle with esbuild in test mode', async () => { + await testBundler('esbuild', 'test'); }); +tap.test('should bundle with esbuild in production mode', async () => { + await testBundler('esbuild', 'production'); +}); + +// Test rolldown +tap.test('should bundle with rolldown in test mode', async () => { + await testBundler('rolldown', 'test'); +}); + +tap.test('should bundle with rolldown in production mode', async () => { + await testBundler('rolldown', 'production'); +}); + +// Test rspack +tap.test('should bundle with rspack in test mode', async () => { + await testBundler('rspack', 'test'); +}); + +tap.test('should bundle with rspack in production mode', async () => { + await testBundler('rspack', 'production'); +}); + +// Test size comparison +tap.test('should show bundle size comparison', async () => { + const testDir = path.join(process.cwd(), 'test'); + const sizes: Record = { + esbuild: { test: 0, production: 0 }, + rolldown: { test: 0, production: 0 }, + rspack: { test: 0, production: 0 } + }; + + for (const bundler of ['esbuild', 'rolldown', 'rspack'] as const) { + for (const mode of ['test', 'production'] as const) { + const filePath = path.join(testDir, `dist_manual/${bundler}-${mode}.js`); + if (fs.existsSync(filePath)) { + const stats = fs.statSync(filePath); + sizes[bundler][mode] = stats.size; + } + } + } + + console.log('\nšŸ“Š Bundle Size Comparison:'); + console.log('ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”'); + console.log('│ Bundler │ Test Mode │ Production │'); + console.log('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤'); + for (const bundler of ['esbuild', 'rolldown', 'rspack'] as const) { + const testSize = (sizes[bundler].test / 1024).toFixed(1) + ' KB'; + const prodSize = (sizes[bundler].production / 1024).toFixed(1) + ' KB'; + console.log(`│ ${bundler.padEnd(11)} │ ${testSize.padEnd(10)} │ ${prodSize.padEnd(12)} │`); + } + console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜'); + + // Verify all sizes are reasonable + for (const bundler of ['esbuild', 'rolldown', 'rspack'] as const) { + expect(sizes[bundler].test).toBeGreaterThan(0); + expect(sizes[bundler].production).toBeGreaterThan(0); + // Production bundles should generally be smaller due to minification + // but rspack might be larger due to runtime overhead + if (bundler !== 'rspack') { + expect(sizes[bundler].production).toBeLessThan(sizes[bundler].test); + } + } +}); tap.start(); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index dde9a17..c0e7997 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@git.zone/tsbundle', - version: '2.3.0', - description: 'a bundler using rollup for painless bundling of web projects' + version: '2.4.0', + description: 'a multi-bundler tool supporting esbuild, rolldown, and rspack for painless bundling of web projects' } diff --git a/ts/interfaces/index.ts b/ts/interfaces/index.ts index 275d1a0..a67f58b 100644 --- a/ts/interfaces/index.ts +++ b/ts/interfaces/index.ts @@ -2,7 +2,7 @@ export interface ICliOptions { commonjs?: boolean; skiplibcheck?: boolean; production?: boolean; - bundler: 'parcel' | 'esbuild' | 'rollup' | 'rolldown' + bundler: 'esbuild' | 'rolldown' | 'rspack' } export interface IEnvTransportOptions { diff --git a/ts/mod_esbuild/index.child.ts b/ts/mod_esbuild/index.child.ts index 1aeb103..4f3f438 100644 --- a/ts/mod_esbuild/index.child.ts +++ b/ts/mod_esbuild/index.child.ts @@ -61,7 +61,7 @@ export class TsBundleProcess { format: 'esm', target: 'es2022', minify: true, - entryNames: 'bundle', + entryNames: plugins.path.parse(toArg).name, outdir: plugins.path.parse(toArg).dir, tsconfig: paths.tsconfigPath, splitting: false, diff --git a/ts/mod_rolldown/index.child.ts b/ts/mod_rolldown/index.child.ts index 7c0c34d..a4be54f 100644 --- a/ts/mod_rolldown/index.child.ts +++ b/ts/mod_rolldown/index.child.ts @@ -39,10 +39,15 @@ export class TsBundleProcess { }, }); + const outputDir = plugins.path.dirname(toArg); + const outputFilename = plugins.path.basename(toArg); + await result.write({ - file: toArg, + dir: outputDir, + entryFileNames: outputFilename, format: 'es', sourcemap: true, + inlineDynamicImports: true, }); } @@ -66,11 +71,16 @@ export class TsBundleProcess { }, }); + const outputDir = plugins.path.dirname(toArg); + const outputFilename = plugins.path.basename(toArg); + await result.write({ - file: toArg, + dir: outputDir, + entryFileNames: outputFilename, format: 'es', sourcemap: true, minify: true, + inlineDynamicImports: true, }); } } diff --git a/ts/mod_rspack/index.child.ts b/ts/mod_rspack/index.child.ts new file mode 100644 index 0000000..6af681f --- /dev/null +++ b/ts/mod_rspack/index.child.ts @@ -0,0 +1,236 @@ +import * as plugins from './plugins.js'; +import * as paths from '../paths.js'; +import * as interfaces from '../interfaces/index.js'; +import { logger } from '../tsbundle.logging.js'; + +export class TsBundleProcess { + constructor() { + // Nothing here + } + + public async getAliases() { + try { + const aliasObject: Record = {}; + const localTsConfig = plugins.smartfile.fs.toObjectSync( + plugins.path.join(paths.cwd, 'tsconfig.json') + ); + if (localTsConfig.compilerOptions && localTsConfig.compilerOptions.paths) { + for (const alias of Object.keys(localTsConfig.compilerOptions.paths)) { + const aliasPath = localTsConfig.compilerOptions.paths[alias][0]; + // Convert TypeScript path to absolute path for rspack + aliasObject[alias.replace('/*', '')] = plugins.path.resolve(paths.cwd, aliasPath.replace('/*', '')); + } + } + return aliasObject; + } catch (error) { + return {}; + } + } + + /** + * creates a bundle for the test enviroment + */ + public async buildTest(fromArg: string, toArg: string, argvArg: any) { + const aliases = await this.getAliases(); + const outputDir = plugins.path.dirname(toArg); + const outputFilename = plugins.path.basename(toArg); + + const config = { + mode: 'development' as const, + entry: { + main: fromArg, + }, + output: { + path: outputDir, + filename: outputFilename, + library: { + type: 'module' as const, + }, + }, + devtool: 'source-map' as const, + resolve: { + alias: aliases, + extensions: ['.ts', '.tsx', '.js', '.jsx'], + }, + module: { + rules: [ + { + test: /\.tsx?$/, + exclude: /node_modules/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'typescript', + tsx: true, + decorators: true, + }, + target: 'es2022', + transform: { + decoratorVersion: '2022-03', + }, + }, + }, + }, + type: 'javascript/auto', + }, + ], + }, + experiments: { + outputModule: true, + }, + }; + + return new Promise((resolve, reject) => { + plugins.rspack(config, (err, stats) => { + if (err) { + console.error(err.stack || err); + reject(err); + return; + } + + if (stats.hasErrors()) { + console.error(stats.toString()); + reject(new Error('Build failed with errors')); + return; + } + + console.log(stats.toString({ + colors: true, + modules: false, + children: false, + chunks: false, + chunkModules: false, + })); + + resolve(undefined); + }); + }); + } + + /** + * creates a bundle for the production environment + */ + public async buildProduction(fromArg: string, toArg: string, argvArg: any) { + console.log('rspack specific:'); + console.log(`from: ${fromArg}`); + console.log(`to: ${toArg}`); + + const aliases = await this.getAliases(); + const outputDir = plugins.path.dirname(toArg); + const outputFilename = plugins.path.basename(toArg); + + const config = { + mode: 'production' as const, + entry: { + main: fromArg, + }, + output: { + path: outputDir, + filename: outputFilename, + library: { + type: 'module' as const, + }, + }, + devtool: 'source-map' as const, + resolve: { + alias: aliases, + extensions: ['.ts', '.tsx', '.js', '.jsx'], + }, + module: { + rules: [ + { + test: /\.tsx?$/, + exclude: /node_modules/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'typescript', + tsx: true, + decorators: true, + }, + target: 'es2022', + transform: { + decoratorVersion: '2022-03', + }, + minify: { + compress: true, + mangle: true, + }, + }, + }, + }, + type: 'javascript/auto', + }, + ], + }, + optimization: { + minimize: true, + concatenateModules: true, + usedExports: true, + sideEffects: true, + }, + experiments: { + outputModule: true, + }, + }; + + return new Promise((resolve, reject) => { + plugins.rspack(config, (err, stats) => { + if (err) { + console.error(err.stack || err); + reject(err); + return; + } + + if (stats.hasErrors()) { + console.error(stats.toString()); + reject(new Error('Build failed with errors')); + return; + } + + console.log(stats.toString({ + colors: true, + modules: false, + children: false, + chunks: false, + chunkModules: false, + })); + + resolve(undefined); + }); + }); + } +} + +const run = async () => { + console.log('running spawned compilation process'); + const transportOptions: interfaces.IEnvTransportOptions = JSON.parse( + process.env.transportOptions + ); + console.log('=======> RSPACK'); + console.log(transportOptions); + process.chdir(transportOptions.cwd); + console.log(`switched to ${process.cwd()}`); + const tsbundleProcessInstance = new TsBundleProcess(); + if (transportOptions.mode === 'test') { + console.log('building for test:'); + await tsbundleProcessInstance.buildTest( + plugins.smartpath.transform.makeAbsolute(transportOptions.from, process.cwd()), + plugins.smartpath.transform.makeAbsolute(transportOptions.to, process.cwd()), + transportOptions.argv + ); + } else { + console.log('building for production:'); + await tsbundleProcessInstance.buildProduction( + plugins.smartpath.transform.makeAbsolute(transportOptions.from, process.cwd()), + plugins.smartpath.transform.makeAbsolute(transportOptions.to, process.cwd()), + transportOptions.argv + ); + } +}; + +run(); \ No newline at end of file diff --git a/ts/mod_rspack/plugins.ts b/ts/mod_rspack/plugins.ts new file mode 100644 index 0000000..bf55374 --- /dev/null +++ b/ts/mod_rspack/plugins.ts @@ -0,0 +1,5 @@ +export * from '../plugins.js'; + +import { rspack } from '@rspack/core'; + +export { rspack } \ No newline at end of file diff --git a/ts/tsbundle.class.tsbundle.ts b/ts/tsbundle.class.tsbundle.ts index 62424cd..58536ad 100644 --- a/ts/tsbundle.class.tsbundle.ts +++ b/ts/tsbundle.class.tsbundle.ts @@ -15,10 +15,8 @@ export class TsBundle { switch (argvArg.bundler) { case 'rolldown': return './mod_rolldown/index.child.js'; - case 'rollup': - return './mod_rollup/index.child.js'; - case 'parcel': - return './mod_parcel/index.child.js'; + case 'rspack': + return './mod_rspack/index.child.js'; case 'esbuild': default: return './mod_esbuild/index.child.js';