@esmx/rspack
Version:
A high-performance Rspack integration for Esmx microfrontend framework, providing module federation and SSR capabilities.
134 lines (133 loc) • 4.36 kB
JavaScript
import { moduleLinkPlugin } from "@esmx/rspack-module-link-plugin";
import { rspack } from "@rspack/core";
import RspackChain from "rspack-chain";
import nodeExternals from "webpack-node-externals";
import { HMR_DIR, HMR_JSONP } from "./hmr-config.mjs";
export function createChainConfig(esmx, buildTarget, options) {
const isHot = buildTarget === "client" && !esmx.isProd;
const isClient = buildTarget === "client";
const isServer = buildTarget === "server";
const isNode = buildTarget === "node";
const config = new RspackChain();
config.context(esmx.root);
config.mode(esmx.isProd ? "production" : "development");
config.target(isClient ? "web" : "node24");
config.cache(!esmx.isProd);
config.output.clean(esmx.isProd).filename(
!isNode && esmx.isProd ? "exports/[name].[contenthash:8].final.mjs" : "exports/[name].mjs"
).chunkFilename(
esmx.isProd ? "chunks/[name].[contenthash:8].final.mjs" : "chunks/[name].mjs"
).publicPath(
isClient ? "auto" : `${esmx.basePathPlaceholder}${esmx.basePath}`
).uniqueName(esmx.varName).hotUpdateGlobal(HMR_JSONP).chunkLoadingGlobal(`${HMR_JSONP}_chunk`).hotUpdateChunkFilename(`${HMR_DIR}/[id].[fullhash].hot-update.mjs`).hotUpdateMainFilename(
`${HMR_DIR}/[runtime].[fullhash].hot-update.json`
);
config.output.set(
"cssFilename",
esmx.isProd ? "exports/[name].[contenthash:8].final.css" : "exports/[name].css"
);
config.output.set(
"cssChunkFilename",
esmx.isProd ? "chunks/[name].[contenthash:8].final.css" : "chunks/[name].css"
);
const outputPath = (() => {
switch (buildTarget) {
case "client":
return esmx.resolvePath("dist/client");
case "server":
return esmx.resolvePath("dist/server");
case "node":
return esmx.resolvePath("dist/node");
}
})();
config.output.path(outputPath);
config.plugin("progress").use(rspack.ProgressPlugin, [
{
prefix: buildTarget
}
]);
config.plugin("module-link").use(moduleLinkPlugin, [createModuleLinkConfig(esmx, buildTarget)]);
if (isHot) {
config.plugin("hmr").use(rspack.HotModuleReplacementPlugin);
}
config.module.parser.set("javascript", {
dynamicImportMode: "lazy",
url: isClient ? true : "relative"
});
config.module.generator.set("asset", {
emit: isClient
});
config.module.generator.set("asset/resource", {
emit: isClient
});
config.resolve.alias.set(esmx.name, esmx.root);
config.optimization.minimize(options.minimize ?? esmx.isProd).emitOnErrors(true);
config.externalsPresets({
web: isClient,
node: isServer || isNode
});
config.externalsType("module-import");
if (isNode) {
config.externals([
// @ts-ignore
nodeExternals({
// @ts-ignore
importType: "module-import"
})
]);
}
if (!esmx.isProd) {
config.optimization.splitChunks(false).runtimeChunk(false);
config.module.parser.set("javascript", {
...config.module.parser.get("javascript"),
dynamicImportMode: "eager"
});
}
return config;
}
function createModuleLinkConfig(esmx, buildTarget) {
const isClient = buildTarget === "client";
const isServer = buildTarget === "server";
const isNode = buildTarget === "node";
if (isNode) {
return {
name: esmx.name,
exports: {
"src/entry.node": {
rewrite: false,
file: "./src/entry.node"
}
}
};
}
const exports = {};
for (const [name, item] of Object.entries(esmx.moduleConfig.exports)) {
if (item.inputTarget[buildTarget]) {
exports[name] = {
rewrite: item.rewrite,
file: item.inputTarget[buildTarget]
};
}
}
const preEntries = [];
if (isClient && !esmx.isProd) {
preEntries.push(
`${import.meta.resolve("webpack-hot-middleware/client.js")}?path=/${esmx.name}/hot-middleware`
);
}
return {
name: esmx.name,
injectChunkName: isServer,
imports: esmx.moduleConfig.imports,
deps: Object.keys(esmx.moduleConfig.links),
exports,
preEntries
};
}
export function createRspackConfig(esmx, buildTarget, options) {
const chain = createChainConfig(esmx, buildTarget, options);
options.chain?.({ esmx, options, buildTarget, chain });
const config = chain.toConfig();
options.config?.({ esmx, options, buildTarget, config });
return config;
}