repacked
Version:
## Initialization
649 lines (623 loc) • 20.3 kB
JavaScript
;
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
});