UNPKG

@esmx/rspack

Version:

A high-performance Rspack integration for Esmx microfrontend framework, providing Module Linking and SSR capabilities.

161 lines (160 loc) 6.37 kB
import { rspack } from "@rspack/core"; import NodePolyfillPlugin from "node-polyfill-webpack-plugin"; import { RSPACK_LOADER, createRspackApp } from "../rspack/index.mjs"; import { getTargetSetting } from "./target-setting.mjs"; export async function createRspackHtmlApp(esmx, options) { options = { ...options, css: options?.css ? options.css : esmx.isProd ? "css" : "js" }; return createRspackApp(esmx, { ...options, chain(context) { const { chain, buildTarget, esmx: esmx2 } = context; chain.stats("errors-warnings"); chain.devtool(false); chain.cache(false); configureAssetRules(chain, esmx2); chain.module.rule("json").test(/\.json$/i).type("json"); configureWorkerRule(chain, esmx2, options); configureTypeScriptRule(chain, buildTarget, options); configureOptimization(chain, options); chain.plugin("node-polyfill").use(NodePolyfillPlugin); configureDefinePlugin(chain, buildTarget, options); chain.resolve.extensions.clear().add("...").add(".ts"); configureCssRules(chain, esmx2, options); options?.chain?.(context); } }); } function configureAssetRules(chain, esmx) { chain.module.rule("images").test( /\.(png|jpg|jpeg|gif|svg|bmp|webp|ico|apng|avif|tif|tiff|jfif|pjpeg|pjp|cur)$/i ).type("asset/resource").set("generator", { filename: filename(esmx, "images") }); chain.module.rule("media").test(/\.(mp4|webm|ogg|mov)$/i).type("asset/resource").set("generator", { filename: filename(esmx, "media") }); chain.module.rule("audio").test(/\.(mp3|wav|flac|aac|m4a|opus)$/i).type("asset/resource").set("generator", { filename: filename(esmx, "audio") }); chain.module.rule("fonts").test(/\.(woff|woff2|eot|ttf|otf|ttc)(\?.*)?$/i).type("asset/resource").set("generator", { filename: filename(esmx, "fonts") }); } function configureWorkerRule(chain, esmx, options) { chain.module.rule("worker").test(/\.worker\.(c|m)?(t|j)s$/i).use("worker-loader").loader( options.loaders?.workerRspackLoader ?? RSPACK_LOADER.workerRspackLoader ).options({ esModule: false, filename: `${esmx.name}/workers/[name].[contenthash]${esmx.isProd ? ".final" : ""}.js` }); } function configureTypeScriptRule(chain, buildTarget, options) { const targets = getTargetSetting(options?.target, buildTarget); chain.module.rule("typescript").test(/\.(ts|mts)$/i).use("swc-loader").loader( options.loaders?.builtinSwcLoader ?? RSPACK_LOADER.builtinSwcLoader ).options({ env: { targets, ...options?.swcLoader?.env }, jsc: { parser: { syntax: "typescript", ...options?.swcLoader?.jsc?.parser }, ...options?.swcLoader?.jsc }, ...options?.swcLoader }).end().type("javascript/auto"); } function configureOptimization(chain, options) { chain.optimization.minimizer("swc-js-minimizer").use(rspack.SwcJsMinimizerRspackPlugin, [ { minimizerOptions: { format: { comments: false } } } ]); chain.optimization.minimizer("lightningcss-minimizer").use(rspack.LightningCssMinimizerRspackPlugin, [ { minimizerOptions: { targets: getTargetSetting(options?.target, "client"), errorRecovery: false } } ]); } function configureDefinePlugin(chain, buildTarget, options) { if (options.definePlugin) { const defineOptions = {}; Object.entries(options.definePlugin).forEach(([name, value]) => { const targetValue = typeof value === "string" ? value : value[buildTarget]; if (typeof targetValue === "string" && name !== targetValue) { defineOptions[name] = targetValue; } }); if (Object.keys(defineOptions).length) { chain.plugin("define").use(rspack.DefinePlugin, [defineOptions]); } } } function configureCssRules(chain, esmx, options) { if (options.css === false) { return; } if (options.css === "js") { configureCssInJS(chain, esmx, options); return; } configureCssExtract(chain, options); } function configureCssInJS(chain, esmx, options) { chain.module.rule("css").test(/\.css$/).use("style-loader").loader(options.loaders?.styleLoader ?? RSPACK_LOADER.styleLoader).options(options.styleLoader ?? {}).end().use("css-loader").loader(options.loaders?.cssLoader ?? RSPACK_LOADER.cssLoader).options(options.cssLoader ?? {}).end().use("lightning-css-loader").loader( options.loaders?.lightningcssLoader ?? RSPACK_LOADER.lightningcssLoader ).options({ targets: getTargetSetting(options?.target, "client"), minify: esmx.isProd }).end().type("javascript/auto"); const lessRule = chain.module.rule("less").test(/\.less$/).use("style-loader").loader(options.loaders?.styleLoader ?? RSPACK_LOADER.styleLoader).options(options.styleLoader ?? {}).end().use("css-loader").loader(options.loaders?.cssLoader ?? RSPACK_LOADER.cssLoader).options(options.cssLoader ?? {}).end().use("lightning-css-loader").loader( options.loaders?.lightningcssLoader ?? RSPACK_LOADER.lightningcssLoader ).options({ targets: getTargetSetting(options?.target, "client"), minify: esmx.isProd }).end().use("less-loader").loader(options.loaders?.lessLoader ?? RSPACK_LOADER.lessLoader).options(options.lessLoader ?? {}).end(); if (options.styleResourcesLoader) { lessRule.use("style-resources-loader").loader( options.loaders?.styleResourcesLoader ?? RSPACK_LOADER.styleResourcesLoader ).options(options.styleResourcesLoader); } lessRule.type("javascript/auto"); } function configureCssExtract(chain, options) { chain.set("experiments", { ...chain.get("experiments") ?? {}, css: true }); const experiments = chain.get("experiments"); if (!experiments || !experiments.css) { return; } const lessRule = chain.module.rule("less").test(/\.less$/).use("less-loader").loader(options.loaders?.lessLoader ?? RSPACK_LOADER.lessLoader).options(options.lessLoader ?? {}).end(); if (options.styleResourcesLoader) { lessRule.use("style-resources-loader").loader( options.loaders?.styleResourcesLoader ?? RSPACK_LOADER.styleResourcesLoader ).options(options.styleResourcesLoader); } lessRule.type("css"); } function filename(esmx, name, ext = "[ext]") { return esmx.isProd ? `${name}/[name].[contenthash:8].final${ext}` : `${name}/[path][name]${ext}`; }