UNPKG

repacked

Version:
649 lines (623 loc) 20.3 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { build: () => build_default, serve: () => serve_default, test: () => runTest }); module.exports = __toCommonJS(index_exports); // src/utils/cwd.ts var import_path = __toESM(require("path")); var cwd = (...paths) => { return import_path.default.join(process.cwd(), ...paths); }; var cwd_default = cwd; // src/features/test/jestConfig.ts var import_path2 = __toESM(require("path")); // src/features/swc/swcOptions.ts var getSwcOptions = (options) => { return { jsc: { parser: { syntax: "typescript", tsx: options.tsx }, externalHelpers: false, transform: { react: { runtime: "automatic", development: !options.isProduction, refresh: !options.isProduction && !options.isServer } } }, env: { targets: "Chrome >= 48" } }; }; // src/features/test/jestConfig.ts var getJestConfig = () => { return { rootDir: cwd_default(""), roots: ["<rootDir>/src"], collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}", "!src/**/*.d.ts"], setupFilesAfterEnv: ["@testing-library/jest-dom"], testMatch: [ "<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}", "<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}" ], testEnvironment: "jsdom", moduleFileExtensions: ["ts", "tsx", "js", "jsx"], transform: { "^.+\\.(js|ts|mjs|cjs)$": "@swc/jest", "^.+\\.(jsx|tsx)$": [ "@swc/jest", getSwcOptions({ isProduction: true, tsx: true }) ], "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": import_path2.default.resolve( __dirname, "./features/test/transformers/fileTransformer.js" ), "^.+\\.css$": import_path2.default.resolve( __dirname, "./features/test/transformers/cssTransformer.js" ) } }; }; var getJestConfigAsJSON = (override) => { return JSON.stringify(override(getJestConfig())); }; // src/features/test/test.ts var jest = require("jest"); var runTest = async (argv, appConfig) => { const jestConfig = getJestConfigAsJSON(appConfig.jest); argv.push("--config", jestConfig); jest.run(argv); }; // src/features/serve/index.ts var import_core5 = require("@rspack/core"); var import_dev_server3 = require("@rspack/dev-server"); // src/features/server/server.ts var import_express = __toESM(require("express")); var expressServer = () => { const app = (0, import_express.default)(); return app; }; // src/features/serve/index.ts var import_connect_history_api_fallback = __toESM(require("connect-history-api-fallback")); var import_webpack_hot_middleware = __toESM(require("webpack-hot-middleware")); var import_webpack_dev_middleware = __toESM(require("webpack-dev-middleware")); var import_http_proxy_middleware = require("http-proxy-middleware"); // src/features/server/getServerRspackConfig.ts var import_license_webpack_plugin = require("license-webpack-plugin"); // src/features/rspack/getRspackConfig.ts var import_dev_server = require("@rspack/dev-server"); var getRspackConfig = async (mode, appConfig, options) => { const isDevelopment = mode === "development"; const isServer = options?.target === "server"; const configOverride = options?.override ?? ((config) => config); const outputDirectory = cwd_default(appConfig.output.dir); const rspackConfig = { mode, watch: options?.watch, watchOptions: options?.watch ? { ignored: /node_modules/, poll: 1e3, aggregateTimeout: 300 } : void 0, cache: false, entry: cwd_default(appConfig.client.entry), devtool: "source-map", output: { uniqueName: appConfig.appName, publicPath: appConfig.client.publicPath, path: outputDirectory, filename: "js/[name].[fullhash].js", clean: typeof options?.clean === "boolean" ? options.clean : true }, plugins: [], module: { rules: [ { test: /\.(j|t)s?$/, use: { loader: "builtin:swc-loader", options: getSwcOptions({ tsx: false, isProduction: !isDevelopment, isServer }) }, exclude: /node_modules/ }, { test: /\.(js|ts)x?$/, use: { loader: "builtin:swc-loader", options: getSwcOptions({ tsx: true, isProduction: !isDevelopment, isServer }) }, exclude: /node_modules/ }, { test: /\.css$/, exclude: /node_modules/, use: ["style-loader", "css-loader"] }, { test: /\.(png|svg|jpg|gif)$/, exclude: /node_modules/, use: [ isServer ? { loader: "file-loader", options: { emitFile: false, publicPath: appConfig.client.publicPath } } : "file-loader" ] } ] }, resolve: { extensions: ["*", ".jsx", ".tsx", ".ts", ".js"] }, performance: { hints: false } }; appConfig.plugins.forEach((plugin) => { const customPlugin = plugin({ target: options.target, appConfig }); rspackConfig.plugins?.push(customPlugin); customPlugin.updateConfig?.(rspackConfig); }); return appConfig.rspack( configOverride(rspackConfig), options?.target ?? "client" ); }; var getRspackConfig_default = getRspackConfig; // src/features/server/plugins/hotReloadServer.ts var import_node_cluster = __toESM(require("cluster")); var import_path3 = __toESM(require("path")); var HotReloadServer = class _HotReloadServer { constructor(appConfig) { this.appConfig = appConfig; this.callback = () => { }; this.workers = []; import_node_cluster.default.setupPrimary({ exec: import_path3.default.resolve(cwd_default(appConfig.output.dir, "index.js")), args: [`--port=${appConfig.development.port + 1}`] }); import_node_cluster.default.on("online", (worker) => { this.workers.push(worker); this.callback(); }); } apply(compiler) { const pluginName = _HotReloadServer.name; compiler.hooks.afterEmit.tapAsync(pluginName, (compilation, callback) => { this.callback = callback; this.workers.forEach((worker) => { try { worker.process.kill("SIGTERM"); } catch (e) { console.warn(`Unable to kill worker ${worker.process.pid}`); } }); this.workers = []; import_node_cluster.default.fork(); }); } }; // src/features/server/getServerRspackConfig.ts var import_path4 = __toESM(require("path")); var import_core = require("@rspack/core"); var getServerRspackConfig = async (mode, appConfig, options) => { let runtimeEnv = mode === "production" ? "prod" : "dev"; if (runtimeEnv === "prod" && appConfig.server.runtime === "serverless") { runtimeEnv = "serverless"; } return await getRspackConfig_default(mode, appConfig, { ...options ?? {}, target: "server", override: (config) => { const entry = import_path4.default.join( __dirname, "/features/server/runtimes/", `runtime.${runtimeEnv}.js` ); config.module?.rules?.push({ test: entry, use: [ { loader: import_path4.default.resolve( __dirname, "./features/server/loaders/loadServer.js" ), options: { entry: cwd_default(appConfig.server.entry) } } ] }); config.plugins?.push( new import_core.DefinePlugin({ "process.env.__INTERNAL_REPACKED_SERVER_CONFIG": { client: { enabled: appConfig.client.enabled } } }) ); if (mode === "production") { config.plugins?.push( new import_license_webpack_plugin.LicenseWebpackPlugin({ outputFilename: "LICENSE", perChunkOutput: false, addBanner: true, stats: { warnings: false } }) ); } if (mode === "development") { config.plugins?.push(new HotReloadServer(appConfig)); } config.target = "node"; config.entry = { index: entry }; config.output.libraryTarget = "commonjs2"; config.output.filename = "[name].js"; config.output.publicPath = appConfig.client.publicPath; config.optimization = { sideEffects: true }; delete config.devServer; return config; } }); }; var getServerRspackConfig_default = getServerRspackConfig; // src/features/rspack/utils.ts var filterKnownWarnings = (warnings) => { const knownPackages = ["yargs", "express", "repacked"].map( (pkg) => `node_modules/${pkg}` ); const containsAny = (str, values) => { return values.some((value) => str.includes(value)); }; return warnings.filter((warning) => { if (warning.message.includes("Critical dependency") && (!warning.moduleName || containsAny(warning.moduleName ?? "", knownPackages))) { return false; } return true; }); }; var logRspackErrors = (err, stats) => { if (err) { console.error(err.stack || err); if (err.details) { console.error(err.details); } process.exit(1); } const statsData = stats?.toJson(); if (stats?.hasErrors()) { console.error(statsData?.errors); process.exit(1); } if (stats?.hasWarnings()) { const filteredWarnings = filterKnownWarnings(statsData?.warnings ?? []); if (filteredWarnings.length > 0) { console.warn(filteredWarnings); } } }; // src/features/client/getClientRspackConfig.ts var import_dev_server2 = require("@rspack/dev-server"); var import_core4 = require("@rspack/core"); var import_plugin_react_refresh = __toESM(require("@rspack/plugin-react-refresh")); var import_rspack = require("@module-federation/enhanced/rspack"); // src/features/client/plugins/envVariables.ts var import_core2 = require("@rspack/core"); var getEnvValues = (filterCallback) => { const envs = process.env || {}; const filteredEnvs = {}; Object.entries(envs).forEach(([key, value]) => { if (filterCallback(key, value)) { filteredEnvs[key] = value; } }); return filteredEnvs; }; var EnvVariablesPlugin = (filterCallback) => { return new import_core2.DefinePlugin({ "process.env": JSON.stringify({ ...getEnvValues(filterCallback) }) }); }; // src/features/client/plugins/htmlMFWebpackPlugin.ts var import_core3 = require("@rspack/core"); var HtmlMFRspackPlugin = class { constructor(entryFile = "remoteEntry.js") { this.entryFile = entryFile; } apply(compiler) { compiler.hooks.compilation.tap( "HtmlMFRspackPlugin", (compilation) => { import_core3.HtmlRspackPlugin.getCompilationHooks( compilation ).alterAssetTags.tapAsync("HtmlMFRspackPlugin", (data, cb) => { const entryFile = `${data.publicPath.toLowerCase() === "auto" ? "" : data.publicPath}${this.entryFile}`; data.assetTags.scripts = data.assetTags.scripts.filter( (script) => script.attributes.src !== entryFile ); cb(null, data); }); } ); } }; var htmlMFWebpackPlugin_default = HtmlMFRspackPlugin; // src/features/client/getClientRspackConfig.ts var getClientRspackConfig = async (mode, appConfig, options) => { const isDevelopment = mode === "development"; const outputDirectory = cwd_default(appConfig.output.dir); let entry = []; if (appConfig.server.enabled && isDevelopment) { entry = [ "webpack-hot-middleware/client?reload=true", cwd_default(appConfig.client.entry) ]; } else { entry = cwd_default(appConfig.client.entry); } const plugins = []; plugins.push( new import_core4.HtmlRspackPlugin({ template: cwd_default(appConfig.client.template) }) ); plugins.push(EnvVariablesPlugin(appConfig.client.envFilter)); isDevelopment && plugins.push(new import_core4.HotModuleReplacementPlugin()); isDevelopment && plugins.push(new import_plugin_react_refresh.default({ library: appConfig.appName })); plugins.push( new import_core4.rspack.CopyRspackPlugin({ patterns: [ { from: cwd_default(appConfig.client.assetsDir), to: outputDirectory } ] }) ); if (appConfig.moduleFederation) { plugins.push(new import_rspack.ModuleFederationPlugin(appConfig.moduleFederation)); plugins.push(new htmlMFWebpackPlugin_default(appConfig.moduleFederation.filename)); } return await getRspackConfig_default(mode, appConfig, { ...options ?? {}, target: "client", override: (config) => { config.entry = entry; config.plugins = [...config.plugins, ...plugins]; config.devServer = { hot: true, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization" }, ...appConfig.development }; return config; } }); }; var getClientRspackConfig_default = getClientRspackConfig; // src/features/serve/utils/copyHeaders.ts function copyHeaders(proxyRes, res) { if (proxyRes.statusCode) { res.statusCode = proxyRes.statusCode; } if (proxyRes.statusMessage) { res.statusMessage = proxyRes.statusMessage; } if (typeof res.setHeader === "function") { let keys = Object.keys(proxyRes.headers); keys = keys.filter( (key) => !["content-encoding", "transfer-encoding"].includes(key) ); keys.forEach((key) => { let value = proxyRes.headers[key]; if (value === void 0) { return; } if (key === "set-cookie") { value = Array.isArray(value) ? value : [value]; value = value.map((x) => x.replace(/Domain=[^;]+?/i, "")); } res.setHeader(key, value); }); } else { res.headers = proxyRes.headers; } } // src/features/serve/index.ts var serveClientOnly = async (mode, appConfig) => { const rspackConfig = await getClientRspackConfig_default(mode, appConfig); rspackConfig.devServer.historyApiFallback = true; const compiler = (0, import_core5.rspack)(rspackConfig); const server = new import_dev_server3.RspackDevServer(rspackConfig.devServer ?? {}, compiler); const runServer = async () => { console.log("Starting server..."); await server.start(); }; runServer(); }; var serveServer = async (mode, appConfig) => { const serverRspackConfig = await getServerRspackConfig_default(mode, appConfig, { watch: true }); (0, import_core5.rspack)(serverRspackConfig, logRspackErrors); const clientRspackConfig = await getClientRspackConfig_default(mode, appConfig, {}); clientRspackConfig.output.publicPath = appConfig.client.publicPath; const clientCompiler = (0, import_core5.rspack)(clientRspackConfig); const port = appConfig.development.port || 3e3; const clientEnabled = appConfig.client.enabled; const app = expressServer(); const nextWeakMap = /* @__PURE__ */ new WeakMap(); const proxy = (0, import_http_proxy_middleware.createProxyMiddleware)({ target: `http://localhost:${port + 1}`, changeOrigin: true, selfHandleResponse: true, on: { proxyRes: (proxyRes, req, res) => { if (!clientEnabled) { proxyRes.pipe(res); return; } if (proxyRes.headers?.["x-dev-repacked-route-status"] === "unhandled") { const next = nextWeakMap.get(req); return next(); } else { copyHeaders(proxyRes, res); proxyRes.pipe(res); } } } }); app.use((req, res, next) => { nextWeakMap.set(req, next); proxy(req, res, next); }); if (clientEnabled) { app.use((0, import_connect_history_api_fallback.default)()); const devMiddleware = (0, import_webpack_dev_middleware.default)( //@todo: fix once rspack dev middleware released clientCompiler, { publicPath: clientRspackConfig.output?.publicPath } ); app.use(devMiddleware); app.use((0, import_webpack_hot_middleware.default)(clientCompiler)); } app.listen(port, () => { console.log(`Server is running at http://localhost:${port}`); }); }; var serve = async (mode, appConfig) => { if (appConfig.server.enabled) { serveServer(mode, appConfig); } else { serveClientOnly(mode, appConfig); } }; var serve_default = serve; // src/features/client/build.ts var import_core6 = require("@rspack/core"); var buildClient = async (mode, appConfig) => { const rspackConfig = await getClientRspackConfig_default(mode, appConfig); (0, import_core6.rspack)(rspackConfig, logRspackErrors); }; // src/features/server/build.ts var import_core7 = require("@rspack/core"); var buildServer = async (mode, appConfig) => { const rspackConfig = await getServerRspackConfig_default(mode, appConfig, { clean: false }); return new Promise((resolve, reject) => { (0, import_core7.rspack)(rspackConfig, (err, stats) => { logRspackErrors(err, stats); if (err) { reject(err); return; } if (stats?.hasErrors()) { const info = stats.toJson(); reject( new Error(`Build failed with errors: ${info.errors?.join("\n")}`) ); return; } resolve(true); }); }); }; // src/features/build/index.ts var import_path5 = __toESM(require("path")); // src/features/build/utils/removeFolder.ts var import_fs = require("fs"); var removeFolder = async (folder) => { try { await import_fs.promises.rm(folder, { recursive: true, force: true }); console.log(`Folder "${folder}" removed successfully.`); } catch (error) { console.error(`Error removing folder: ${error.message}`); throw error; } }; var removeFolder_default = removeFolder; // src/features/build/index.ts var build = async (mode, appConfig) => { const serverEnabled = appConfig.server.enabled; const clientEnabled = appConfig.client.enabled; const clientOutputPath = serverEnabled ? import_path5.default.join(appConfig.output.dir, "client") : appConfig.output.dir; await removeFolder_default(cwd_default(appConfig.output.dir)); clientEnabled && await buildClient(mode, { ...appConfig, output: { ...appConfig.output, dir: clientOutputPath } }); if (serverEnabled) { await buildServer(mode, appConfig); } }; var build_default = build; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { build, serve, test });