UNPKG

@kitchenshelf/serverless-rspack

Version:

[Serverless Framework](https://www.serverless.com) plugin for zero-config JavaScript and TypeScript code bundling using the high performance Rust-based JavaScript bundler [`rspack`](https://rspack.dev/guide/start/introduction)

165 lines 7.48 kB
import { __awaiter } from "tslib"; import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin'; import { DefinePlugin, ProgressPlugin, node, rspack, } from '@rspack/core'; import { writeFileSync } from 'node:fs'; import path from 'node:path'; import { cwd } from 'node:process'; import { mergeWithCustomize } from 'webpack-merge'; export function bundle(entries) { return __awaiter(this, void 0, void 0, function* () { var _a; let config; if (this.providedRspackConfig && ((_a = this.pluginOptions.config) === null || _a === void 0 ? void 0 : _a.strategy)) { this.log.verbose(`[Bundle] Config merge strategy: ${this.pluginOptions.config.strategy}`); if (this.pluginOptions.config.strategy === 'combine') { const baseConfig = defaultConfig(entries, this.pluginOptions, this.offlineMode, this.buildOutputFolderPath, this.log); const mergedConfig = mergeWithCustomize({ customizeArray: mergeArrayUniqueStrategy(this.log), })([baseConfig, this.providedRspackConfig]); config = enforcePluginReadOnlyDefaults(mergedConfig, this.buildOutputFolderPath, entries); } else { config = enforcePluginReadOnlyDefaults(this.providedRspackConfig, this.buildOutputFolderPath, entries); } } else { config = defaultConfig(entries, this.pluginOptions, this.offlineMode, this.buildOutputFolderPath, this.log); } this.log.verbose(`[Bundle] Bundling with config: ${safelyStringifyConfig(config)}`); const startBundle = Date.now(); return new Promise((resolve) => { rspack(config, (x, y) => { var _a; if (this.pluginOptions.stats) { const c = y === null || y === void 0 ? void 0 : y.toJson(); try { writeFileSync(path.join(this.buildOutputFolderPath, 'stats.json'), JSON.stringify(c)); } catch (error) { (_a = this.log) === null || _a === void 0 ? void 0 : _a.error(`[Bundle] Failed to write stats file: ${error}`); } } this.log.verbose(`[Performance] Bundle total execution time for service ${this.serverless.service.service} [${Date.now() - startBundle} ms]`); resolve('Success!'); // Yay! Everything went well! }); }); }); } const esmOutput = { chunkFormat: 'module', chunkLoading: 'import', library: { type: 'module', }, }; const defaultConfig = (entries, buildOptions, offlineMode, workFolderPath, logger) => { var _a, _b; return (Object.assign(Object.assign({ mode: buildOptions.mode, entry: entries, target: 'node', experiments: { outputModule: buildOptions.esm, }, devtool: buildOptions.sourcemap !== undefined ? buildOptions.sourcemap : false, resolve: Object.assign({ extensions: ['...', '.ts', '.tsx', '.jsx'] }, (buildOptions.tsConfig ? { tsConfig: path.resolve(cwd(), buildOptions.tsConfig), } : {})) }, (((_a = buildOptions.externals) === null || _a === void 0 ? void 0 : _a.length) && ((_b = buildOptions.externals) === null || _b === void 0 ? void 0 : _b.length) > 0 ? { externals: [ ({ request }, callback) => { var _a; const isExternal = (_a = buildOptions === null || buildOptions === void 0 ? void 0 : buildOptions.externals) === null || _a === void 0 ? void 0 : _a.some((external) => { return new RegExp(external).test(request); }); if (isExternal) { logger.verbose(`[Bundle] Marking ${request} as external`); return callback(null, 'node-commonjs ' + request); } callback(); }, ], } : {})), { plugins: [ new DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env['NODE_ENV']), }), new ProgressPlugin({}), new node.NodeTargetPlugin(), createDoctorPlugin(buildOptions), ].filter(Boolean), module: { rules: [ { test: /\.ts$/, use: { loader: 'builtin:swc-loader', options: { jsc: { target: 'es2020', parser: { syntax: 'typescript', }, }, }, }, }, ], }, optimization: { mangleExports: false, }, output: Object.assign(Object.assign({ path: workFolderPath, library: { type: 'commonjs2' } }, (buildOptions.esm ? esmOutput : {})), (offlineMode ? { devtoolModuleFilenameTemplate: '[absolute-resource-path]' } : {})) })); }; function mergeArrayUniqueStrategy(logger) { return (base, provided, key) => { if (key === 'plugins' && isPlugins(base) && isPlugins(provided)) { const plugins = [...provided]; base.forEach((basePlugin) => { const matchedPlugin = provided.find((providedPlugin) => basePlugin.name === providedPlugin.name); if (matchedPlugin) { logger.warning(`[Bundle] You have provided your own ${matchedPlugin.name}. This will override the default one provided by @kitchenshelf/serverless-rspack.`); } else { plugins.push(basePlugin); } }); return plugins; } // Fall back to default merging return undefined; }; } const enforcePluginReadOnlyDefaults = (config, buildOutputFolderPath, entries) => { return Object.assign(Object.assign({}, config), { entry: entries, optimization: Object.assign(Object.assign({}, config.optimization), { mangleExports: false }), output: Object.assign(Object.assign({}, config.output), { path: buildOutputFolderPath }) }); }; function isPlugins(a) { return Array.isArray(a); } function createDoctorPlugin(buildOptions) { const isEnabled = enabledViaSimpleConfig(buildOptions.doctor) || enabledViaConfigObject(buildOptions.doctor); return isEnabled ? new RsdoctorRspackPlugin({ disableClientServer: true, mode: 'brief', reportDir: getReportDir(buildOptions.doctor), }) : null; } function enabledViaSimpleConfig(doctor) { return typeof doctor === 'boolean' && doctor === true; } function enabledViaConfigObject(doctor) { return (typeof doctor === 'object' && doctor !== null && doctor.enable === true); } function getReportDir(doctor) { if (enabledViaConfigObject(doctor) && doctor.outputDirectory) { return doctor.outputDirectory; } return undefined; } function safelyStringifyConfig(config) { return JSON.stringify(config, (key, value) => { if (key === 'plugins') { return value.map((plugin) => plugin.constructor.name); } return value; }); } //# sourceMappingURL=bundle.js.map