UNPKG

storybook-builder-rsbuild

Version:
934 lines (910 loc) 40.6 kB
import CJS_COMPAT_NODE_URL_9822f21edcc46e85 from 'node:url'; import CJS_COMPAT_NODE_PATH_9822f21edcc46e85 from 'node:path'; import CJS_COMPAT_NODE_MODULE_9822f21edcc46e85 from "node:module"; var __filename = CJS_COMPAT_NODE_URL_9822f21edcc46e85.fileURLToPath(import.meta.url); var __dirname = CJS_COMPAT_NODE_PATH_9822f21edcc46e85.dirname(__filename); var require = CJS_COMPAT_NODE_MODULE_9822f21edcc46e85.createRequire(import.meta.url); // ------------------------------------------------------------ // end of CJS compatibility banner, injected by Storybook's esbuild configuration // ------------------------------------------------------------ import { __commonJS, __require, __toESM } from "./_node-chunks/chunk-L73IVHZJ.js"; // ../../node_modules/.pnpm/pretty-hrtime@1.0.3/node_modules/pretty-hrtime/index.js var require_pretty_hrtime = __commonJS({ "../../node_modules/.pnpm/pretty-hrtime@1.0.3/node_modules/pretty-hrtime/index.js"(exports, module) { "use strict"; var minimalDesc = ["h", "min", "s", "ms", "\u03BCs", "ns"], verboseDesc = ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"], convert = [3600, 60, 1, 1e6, 1e3, 1]; module.exports = function(source, opts) { var verbose, precise, i, spot, sourceAtStep, valAtStep, decimals, strAtStep, results, totalSeconds; if (verbose = !1, precise = !1, opts && (verbose = opts.verbose || !1, precise = opts.precise || !1), !Array.isArray(source) || source.length !== 2 || typeof source[0] != "number" || typeof source[1] != "number") return ""; for (source[1] < 0 && (totalSeconds = source[0] + source[1] / 1e9, source[0] = parseInt(totalSeconds), source[1] = parseFloat((totalSeconds % 1).toPrecision(9)) * 1e9), results = "", i = 0; i < 6 && (spot = i < 3 ? 0 : 1, sourceAtStep = source[spot], i !== 3 && i !== 0 && (sourceAtStep = sourceAtStep % convert[i - 1]), i === 2 && (sourceAtStep += source[1] / 1e9), valAtStep = sourceAtStep / convert[i], !(valAtStep >= 1 && (verbose && (valAtStep = Math.floor(valAtStep)), precise ? strAtStep = valAtStep.toString() : (decimals = valAtStep >= 10 ? 0 : 2, strAtStep = valAtStep.toFixed(decimals)), strAtStep.indexOf(".") > -1 && strAtStep[strAtStep.length - 1] === "0" && (strAtStep = strAtStep.replace(/\.?0+$/, "")), results && (results += " "), results += strAtStep, verbose ? (results += " " + verboseDesc[i], strAtStep !== "1" && (results += "s")) : results += " " + minimalDesc[i], !verbose))); i++) ; return results; }; } }); // src/index.ts var import_pretty_hrtime = __toESM(require_pretty_hrtime(), 1); import { createServer } from "node:net"; import { dirname as dirname2, join as join4, parse } from "node:path"; import * as rsbuildReal from "@rsbuild/core"; import fs from "fs-extra"; import sirv from "sirv"; import { getPresets, resolveAddonName } from "storybook/internal/common"; import { WebpackInvocationError } from "storybook/internal/server-errors"; // src/chromatic-stats.ts import { isAbsolute, relative } from "node:path"; var isRecord = (val) => val != null && typeof val == "object" && Array.isArray(val) === !1, toPosixPath = (filePath) => filePath.split("\\").join("/"), toNormalizedModulePath = (modulePath) => typeof modulePath != "string" || modulePath.length === 0 ? null : isAbsolute(modulePath) ? toPosixPath(relative(process.cwd(), modulePath)) : toPosixPath(modulePath), toAbsolutePathFromIdentifier = (identifier) => { if (typeof identifier != "string" || identifier.length === 0) return null; let withoutQuery = identifier.slice(identifier.lastIndexOf("!") + 1).split("|")[0].split("?")[0]; return isAbsolute(withoutQuery) ? withoutQuery : null; }, toReasonModuleName = (reason) => { let moduleName = typeof reason.moduleName == "string" ? reason.moduleName : null; if (typeof moduleName == "string" && /\s\+\s\d+\smodules?$/.test(moduleName) === !1) return moduleName; let fallbackAbsolutePath = toAbsolutePathFromIdentifier(reason.resolvedModuleIdentifier) ?? toAbsolutePathFromIdentifier(reason.moduleIdentifier), fallbackModuleName = toNormalizedModulePath(fallbackAbsolutePath); return typeof fallbackModuleName == "string" && fallbackModuleName.includes("node_modules/") === !1 ? fallbackModuleName : moduleName; }, isConcatenatedModuleName = (moduleName) => /\s\+\s\d+\smodules?$/.test(moduleName), toChromaticModule = (moduleInfo) => { let rawName = typeof moduleInfo.name == "string" ? moduleInfo.name : null, normalizedNameForCondition = toNormalizedModulePath( moduleInfo.nameForCondition ), name = moduleInfo.id == null && normalizedNameForCondition ? normalizedNameForCondition : rawName ?? normalizedNameForCondition; if (typeof name != "string") return null; let normalizedId = (typeof moduleInfo.id == "string" || typeof moduleInfo.id == "number" ? moduleInfo.id : null) ?? name, normalizedReasons = Array.isArray(moduleInfo.reasons) ? Array.from( new Set( moduleInfo.reasons.filter(isRecord).map(toReasonModuleName).filter( (moduleName) => typeof moduleName == "string" ) ) ).map((moduleName) => ({ moduleName })) : [], normalizedNestedModules = Array.isArray(moduleInfo.modules) ? Array.from( new Set( moduleInfo.modules.filter(isRecord).map((nestedModule) => toNormalizedModulePath(nestedModule.name)).filter( (nestedModuleName) => typeof nestedModuleName == "string" ) ) ).map((nestedModuleName) => ({ name: nestedModuleName })) : []; return normalizedId === null && normalizedReasons.length === 0 && normalizedNestedModules.length === 0 ? null : { id: normalizedId, name, ...normalizedNestedModules.length > 0 ? { modules: normalizedNestedModules } : {}, ...normalizedReasons.length > 0 ? { reasons: normalizedReasons } : {} }; }, collectModuleEntries = (moduleEntries, collected) => { for (let entry of moduleEntries) isRecord(entry) && (collected.push(entry), Array.isArray(entry.children) && collectModuleEntries(entry.children, collected), Array.isArray(entry.modules) && collectModuleEntries(entry.modules, collected)); }, withChromaticMinimalContract = (statsJson) => { if (!isRecord(statsJson)) return statsJson; let modules = statsJson.modules; if (!Array.isArray(modules)) return statsJson; let normalizedStatsJson = statsJson, flattenedModules = []; collectModuleEntries(modules, flattenedModules); let normalizedModules = [], visited = /* @__PURE__ */ new Set(); for (let moduleInfo of flattenedModules) { let normalizedModule = toChromaticModule(moduleInfo); if (!normalizedModule) continue; let moduleKey = `${String(normalizedModule.id)}::${normalizedModule.name}`; if (!visited.has(moduleKey) && (visited.add(moduleKey), normalizedModules.push(normalizedModule), isConcatenatedModuleName(normalizedModule.name) && Array.isArray(normalizedModule.modules))) for (let nestedModule of normalizedModule.modules) { let nestedModuleKey = `${nestedModule.name}::${nestedModule.name}`; visited.has(nestedModuleKey) || (visited.add(nestedModuleKey), normalizedModules.push({ id: nestedModule.name, name: nestedModule.name, ...Array.isArray(normalizedModule.reasons) && normalizedModule.reasons.length > 0 ? { reasons: normalizedModule.reasons } : {} })); } } return normalizedStatsJson.modules = normalizedModules, normalizedStatsJson; }, withStatsJsonCompat = (stats) => { let originalToJsonCandidate = stats.toJson; if (typeof originalToJsonCandidate != "function") return stats; let originalToJson = originalToJsonCandidate.bind(stats), toJsonWithCompat = (options, forToString) => { if (options == null || typeof options == "object") { let statsJson = originalToJson( { modules: !0, reasons: !0, nestedModules: !0, ...options }, forToString ); return withChromaticMinimalContract(statsJson); } return withChromaticMinimalContract(originalToJson(options, forToString)); }; return stats.toJson = toJsonWithCompat, stats; }; // src/logger.ts import { logger as rsbuildLogger } from "@rsbuild/core"; import picocolors from "picocolors"; import { logger } from "storybook/internal/node-logger"; function overrideRsbuildLogger() { let logWithPrefix = (fn) => (msg) => fn( `${picocolors.black(picocolors.bgBlueBright("Rsbuild"))} ${String(msg)}` ); rsbuildLogger.override({ error: logWithPrefix(logger.error), warn: logWithPrefix(logger.warn), info: logWithPrefix((msg) => logger.log(msg, { spacing: 0 })), start: logWithPrefix(logger.info), ready: logWithPrefix(logger.info), success: logWithPrefix(logger.info), log: logWithPrefix(logger.info), debug: logWithPrefix(logger.debug) }); } // src/preview/iframe-rsbuild.config.ts import { createRequire } from "node:module"; import { dirname, join as join2, resolve as resolve3 } from "node:path"; import { fileURLToPath } from "node:url"; import { loadConfig, mergeRsbuildConfig, rspack } from "@rsbuild/core"; import { pluginTypeCheck } from "@rsbuild/plugin-type-check"; import CaseSensitivePathsPlugin from "case-sensitive-paths-webpack-plugin"; import { pluginHtmlMinifierTerser } from "rsbuild-plugin-html-minifier-terser"; import { getBuilderOptions as getBuilderOptions2, isPreservingSymlinks, normalizeStories as normalizeStories2, stringifyProcessEnvs } from "storybook/internal/common"; import { logger as logger3 } from "storybook/internal/node-logger"; import { globalsNameReferenceMap } from "storybook/internal/preview/globals"; import { dedent } from "ts-dedent"; // src/preview/detect-msw.ts import { existsSync } from "node:fs"; import { isAbsolute as isAbsolute2, resolve } from "node:path"; var MSW_SW_FILE = "mockServiceWorker.js"; async function isMswActive(options) { let staticDirs = await options.presets.apply("staticDirs", []); return Array.isArray(staticDirs) ? staticDirs.some((entry) => { let dir = typeof entry == "string" ? entry : entry?.from; if (typeof dir != "string" || dir.length === 0) return !1; let abs = isAbsolute2(dir) ? dir : resolve(options.configDir, dir); return existsSync(resolve(abs, MSW_SW_FILE)); }) : !1; } // src/preview/virtual-module-mapping.ts import { join, resolve as resolve2 } from "node:path"; // ../../node_modules/.pnpm/slash@5.1.0/node_modules/slash/index.js function slash(path) { return path.startsWith("\\\\?\\") ? path : path.replace(/\\/g, "/"); } // src/preview/virtual-module-mapping.ts import { getBuilderOptions, loadPreviewOrConfigFile, normalizeStories, readTemplate } from "storybook/internal/common"; // compiled/@storybook/core-webpack/index.js import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "module"; import * as __WEBPACK_EXTERNAL_MODULE_storybook_internal_common_7991bda6__ from "storybook/internal/common"; import * as __WEBPACK_EXTERNAL_MODULE_storybook_internal_node_logger_87de4309__ from "storybook/internal/node-logger"; var __webpack_modules__ = { 980: (__unused_webpack_module, exports) => { var __webpack_unused_export__; __webpack_unused_export__ = { value: !0 }, exports.TW = void 0; function dedent2(templ) { for (var values = [], _i = 1; _i < arguments.length; _i++) values[_i - 1] = arguments[_i]; var strings = Array.from(typeof templ == "string" ? [templ] : templ); strings[strings.length - 1] = strings[strings.length - 1].replace( /\r?\n([\t ]*)$/, "" ); var indentLengths = strings.reduce(function(arr, str) { var matches = str.match(/\n([\t ]+|(?!\s).)/g); return matches ? arr.concat( matches.map(function(match) { var _a, _b; return (_b = (_a = match.match(/[\t ]/g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; }) ) : arr; }, []); if (indentLengths.length) { var pattern_1 = new RegExp( ` [ ]{` + Math.min.apply(Math, indentLengths) + "}", "g" ); strings = strings.map(function(str) { return str.replace(pattern_1, ` `); }); } strings[0] = strings[0].replace(/^\r?\n/, ""); var string = strings[0]; return values.forEach(function(value, i) { var endentations = string.match(/(?:^|\n)( *)$/), endentation = endentations ? endentations[1] : "", indentedValue = value; typeof value == "string" && value.includes(` `) && (indentedValue = String(value).split(` `).map(function(str, i2) { return i2 === 0 ? str : "" + endentation + str; }).join(` `)), string += indentedValue + strings[i + 1]; }), string; } exports.TW = dedent2, __webpack_unused_export__ = dedent2; } }, __webpack_module_cache__ = {}; function __nccwpck_require__(moduleId) { var cachedModule = __webpack_module_cache__[moduleId]; if (cachedModule !== void 0) return cachedModule.exports; var module = __webpack_module_cache__[moduleId] = { exports: {} }, threw = !0; try { __webpack_modules__[moduleId](module, module.exports, __nccwpck_require__), threw = !1; } finally { threw && delete __webpack_module_cache__[moduleId]; } return module.exports; } __nccwpck_require__.d = (exports, definition) => { for (var key in definition) __nccwpck_require__.o(definition, key) && !__nccwpck_require__.o(exports, key) && Object.defineProperty(exports, key, { enumerable: !0, get: definition[key] }); }; __nccwpck_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); typeof __nccwpck_require__ < "u" && (__nccwpck_require__.ab = new URL(".", import.meta.url).pathname.slice( import.meta.url.match(/^file:\/\/\/\w:/) ? 1 : 0, -1 ) + "/"); var __webpack_exports__ = {}; __nccwpck_require__.d(__webpack_exports__, { il: () => checkWebpackVersion, Tu: () => loadCustomWebpackConfig, SV: () => mergeConfigs, T1: () => toImportFn, i8: () => toImportFnPart, sg: () => toRequireContext, HO: () => toRequireContextString, hO: () => webpackIncludeRegexp }); var external_node_url_namespaceObject = __WEBPACK_EXTERNAL_createRequire( import.meta.url )("node:url"), external_node_path_namespaceObject = __WEBPACK_EXTERNAL_createRequire( import.meta.url )("node:path"), external_node_module_namespaceObject = __WEBPACK_EXTERNAL_createRequire( import.meta.url )("node:module"), x = (y) => { var x2 = {}; return __nccwpck_require__.d(x2, y), x2; }; var common_namespaceObject = x({ globToRegexp: () => __WEBPACK_EXTERNAL_MODULE_storybook_internal_common_7991bda6__.globToRegexp, serverRequire: () => __WEBPACK_EXTERNAL_MODULE_storybook_internal_common_7991bda6__.serverRequire }), node_logger_x = (y) => { var x2 = {}; return __nccwpck_require__.d(x2, y), x2; }; var node_logger_namespaceObject = node_logger_x({ logger: () => __WEBPACK_EXTERNAL_MODULE_storybook_internal_node_logger_87de4309__.logger }), dist = __nccwpck_require__(980), dist_filename = external_node_url_namespaceObject.fileURLToPath( import.meta.url ), dist_dirname = external_node_path_namespaceObject.dirname(dist_filename), dist_require = external_node_module_namespaceObject.createRequire( import.meta.url ), webpackConfigs = ["webpack.config", "webpackfile"], loadCustomWebpackConfig = async (configDir) => (0, common_namespaceObject.serverRequire)( webpackConfigs.map( (configName) => (0, external_node_path_namespaceObject.resolve)(configDir, configName) ) ), checkWebpackVersion = (webpack, specifier, caption) => { if (!webpack.version) { node_logger_namespaceObject.logger.info( "Skipping webpack version check, no version available" ); return; } webpack.version !== specifier && node_logger_namespaceObject.logger.warn((0, dist.TW)` Unexpected webpack version in ${caption}: - Received '${webpack.version}' - Expected '${specifier}' If you're using Webpack 5 in SB6.2 and upgrading, consider: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#webpack-5-manager-build For more info about Webpack 5 support: https://gist.github.com/shilman/8856ea1786dcd247139b47b270912324#troubleshooting `); }; function mergePluginsField(defaultPlugins = [], customPlugins = []) { return [...defaultPlugins, ...customPlugins]; } function mergeRulesField(defaultRules = [], customRules = []) { return [...defaultRules, ...customRules]; } function mergeExtensionsField({ extensions: defaultExtensions = [] }, { extensions: customExtensions = [] }) { return [...defaultExtensions, ...customExtensions]; } function mergeAliasField({ alias: defaultAlias = {} }, { alias: customAlias = {} }) { return { ...defaultAlias, ...customAlias }; } function mergeModuleField(a, b) { return { ...a, ...b, rules: mergeRulesField(a.rules || [], b.rules || []) }; } function mergeResolveField({ resolve: defaultResolve = {} }, { resolve: customResolve = {} }) { return { ...defaultResolve, ...customResolve, alias: mergeAliasField(defaultResolve, customResolve), extensions: mergeExtensionsField(defaultResolve, customResolve) }; } function mergeOptimizationField({ optimization: defaultOptimization = {} }, { optimization: customOptimization = {} }) { return { ...defaultOptimization, ...customOptimization }; } function mergeConfigs(config, customConfig) { return { ...customConfig, ...config, devtool: customConfig.devtool || config.devtool, plugins: mergePluginsField(config.plugins, customConfig.plugins), module: mergeModuleField(config.module || {}, customConfig.module || {}), resolve: mergeResolveField(config, customConfig), optimization: mergeOptimizationField(config, customConfig) }; } function importPipeline() { let importGate = Promise.resolve(); return async (importFn) => { await importGate; let moduleExportsPromise = importFn(); return importGate = importGate.then(async () => { await moduleExportsPromise; }), moduleExportsPromise; }; } function adjustRegexToExcludeNodeModules(originalRegex) { let originalRegexString = originalRegex.source, startsWithCaret = originalRegexString.startsWith("^"), excludeNodeModulesPattern = startsWithCaret ? "(?!.*node_modules)" : "^(?!.*node_modules)", adjustedRegexString = startsWithCaret ? `^${excludeNodeModulesPattern}${originalRegexString.substring(1)}` : excludeNodeModulesPattern + originalRegexString; return new RegExp(adjustedRegexString); } function webpackIncludeRegexp(specifier) { let { directory, files } = specifier, directoryWithoutLeadingDots = directory.replace(/^(\.+\/)+/, "/"), webpackIncludeGlob = [".", ".."].includes(directory) ? files : `${directoryWithoutLeadingDots}/${files}`, webpackIncludeRegexpWithCaret = webpackIncludeGlob.includes("node_modules") ? (0, common_namespaceObject.globToRegexp)(webpackIncludeGlob) : adjustRegexToExcludeNodeModules( (0, common_namespaceObject.globToRegexp)(webpackIncludeGlob) ); return new RegExp(webpackIncludeRegexpWithCaret.source.replace(/^\^/, "")); } function toImportFnPart(specifier) { let { directory, importPathMatcher } = specifier; return (0, dist.TW)` async (path) => { if (!${importPathMatcher}.exec(path)) { return; } const pathRemainder = path.substring(${directory.length + 1}); return import( /* webpackChunkName: "[request]" */ /* webpackInclude: ${webpackIncludeRegexp(specifier)} */ '${directory}/' + pathRemainder ); } `; } function toImportFn(stories, { needPipelinedImport } = {}) { let pipelinedImport = "const pipeline = (x) => x();"; return needPipelinedImport && (pipelinedImport = ` const importPipeline = ${importPipeline}; const pipeline = importPipeline(); `), (0, dist.TW)` ${pipelinedImport} const importers = [ ${stories.map(toImportFnPart).join(`, `)} ]; export async function importFn(path) { for (let i = 0; i < importers.length; i++) { const moduleExports = await pipeline(() => importers[i](path)); if (moduleExports) { return moduleExports; } } } `; } var toRequireContext = (specifier) => { let { directory, files } = specifier, match = (0, common_namespaceObject.globToRegexp)(`./${files}`); return { path: directory, recursive: files.includes("**") || files.split("/").length > 1, match }; }, toRequireContextString = (specifier) => { let { path: p, recursive: r, match: m } = toRequireContext(specifier); return `require.context('${p}', ${r}, ${m})`; }, __webpack_exports__checkWebpackVersion = __webpack_exports__.il, __webpack_exports__loadCustomWebpackConfig = __webpack_exports__.Tu, __webpack_exports__mergeConfigs = __webpack_exports__.SV, __webpack_exports__toImportFn = __webpack_exports__.T1, __webpack_exports__toImportFnPart = __webpack_exports__.i8, __webpack_exports__toRequireContext = __webpack_exports__.sg, __webpack_exports__toRequireContextString = __webpack_exports__.HO, __webpack_exports__webpackIncludeRegexp = __webpack_exports__.hO; // src/preview/virtual-module-mapping.ts var getVirtualModules = async (options) => { let virtualModules = {}, builderOptions = await getBuilderOptions(options), workingDir = process.cwd(), isProd = options.configType === "PRODUCTION", nonNormalizedStories = await options.presets.apply("stories", []), entries = [], stories = normalizeStories(nonNormalizedStories, { configDir: options.configDir, workingDir }), previewAnnotations = [ ...(await options.presets.apply( "previewAnnotations", [], options )).map((entry) => typeof entry == "object" ? entry.absolute : slash(entry)), loadPreviewOrConfigFile(options) ].filter(Boolean), storiesFilename = "storybook-stories.js", storiesPath = resolve2(join(workingDir, storiesFilename)), needPipelinedImport = builderOptions.lazyCompilation !== !1 && !isProd; virtualModules[storiesPath] = __webpack_exports__toImportFn(stories, { needPipelinedImport }); let configEntryPath = resolve2(join(workingDir, "storybook-config-entry.js")); return virtualModules[configEntryPath] = (await readTemplate( __require.resolve( "storybook-builder-rsbuild/templates/virtualModuleModernEntry.js" ) )).replaceAll("'{{storiesFilename}}'", `'./${storiesFilename}'`).replaceAll( "'{{previewAnnotations}}'", previewAnnotations.filter(Boolean).map((entry) => `'${entry}'`).join(",") ).replaceAll( "'{{previewAnnotations_requires}}'", previewAnnotations.filter(Boolean).map((entry) => `require('${entry}')`).join(",") ).replace(/\\/g, "\\\\"), entries.push(configEntryPath), { virtualModules, entries }; }; // src/preview/iframe-rsbuild.config.ts var require2 = createRequire(import.meta.url), getAbsolutePath = (input) => { let storybookPath = fileURLToPath( import.meta.resolve("storybook/package.json") ); return dirname( require2.resolve(join2(input, "package.json"), { paths: [dirname(storybookPath)] }) ); }, maybeGetAbsolutePath = (input) => { try { return getAbsolutePath(input); } catch { return !1; } }, builtInResolveExtensions = [ ".mjs", ".js", ".jsx", ".ts", ".tsx", ".json", ".cjs" ], getRspackMajorVersion = (version) => { if (typeof version != "string") return null; let major = Number.parseInt(version.split(".")[0] ?? "", 10); return Number.isNaN(major) ? null : major; }, rspackMajorVersion = getRspackMajorVersion(rspack.rspackVersion), RAW_QUERY_REGEX = /[?&]raw(?:&|=|$)/, globalPath = maybeGetAbsolutePath("@storybook/global"), storybookPaths = { // biome-ignore lint/complexity/useLiteralKeys: dynamic key required for conditional spread ...globalPath ? { "@storybook/global": globalPath } : {} }, iframe_rsbuild_config_default = async (options, extraWebpackConfig) => { let { rsbuildConfigPath, addonDocs } = await getBuilderOptions2(options), webpackConfigFromPresets = await options.presets.apply("webpack", {}, options); addonDocs && console.warn( "`addonDocs` option is deprecated and will be removed in future versions. Please use `@storybook/addon-docs` option instead." ); let { outputDir = join2(".", "public"), quiet, packageJson, configType, presets, previewUrl, typescriptOptions, features } = options, isProd = configType === "PRODUCTION", workingDir = process.cwd(), [ coreOptions, frameworkOptions, envs, logLevel, headHtmlSnippet, bodyHtmlSnippet, template, docsOptions, entries, nonNormalizedStories, _modulesCount, build2, tagsOptions ] = await Promise.all([ presets.apply("core"), presets.apply("frameworkOptions"), presets.apply("env"), presets.apply("logLevel", void 0), presets.apply("previewHead"), presets.apply("previewBody"), presets.apply("previewMainTemplate"), presets.apply("docs"), presets.apply("entries", []), presets.apply("stories", []), options.cache?.get("modulesCount", 1e3), options.presets.apply("build"), presets.apply("tags", {}) ]), stories = normalizeStories2(nonNormalizedStories, { configDir: options.configDir, workingDir }), shouldCheckTs = typescriptOptions.check && !typescriptOptions.skipCompiler, tsCheckOptions = typescriptOptions.checkOptions || {}, builderOptions = await getBuilderOptions2(options), cacheConfig = builderOptions.fsCache ? !0 : void 0, shouldDisableDevFeatures = process.env.SB_RSBUILD_TEST_MINIMAL_DEV === "true", lazyCompilationConfig; isProd || (shouldDisableDevFeatures ? lazyCompilationConfig = !1 : builderOptions.lazyCompilation !== void 0 ? lazyCompilationConfig = builderOptions.lazyCompilation : await isMswActive(options) ? (lazyCompilationConfig = !1, logger3.warn(dedent` Detected mockServiceWorker.js in staticDirs. Lazy compilation has been disabled automatically to avoid a Service Worker race that can leave the preview iframe blank on cold story loads. Set \`lazyCompilation\` explicitly in your builder options to override. `)) : lazyCompilationConfig = { entries: !1 }); let shouldDisableHmr = shouldDisableDevFeatures; if (!template) throw new Error(dedent` Storybook's Webpack5 builder requires a template to be specified. Somehow you've ended up with a falsy value for the template option. Please file an issue at https://github.com/storybookjs/storybook with a reproduction. `); let externals = globalsNameReferenceMap; build2?.test?.disableBlocks && (externals["@storybook/blocks"] = "__STORYBOOK_BLOCKS_EMPTY_MODULE__"); let { virtualModules: virtualModuleMapping, entries: dynamicEntries } = await getVirtualModules(options), contentFromConfig = {}, { content } = await loadConfig({ cwd: workingDir, path: rsbuildConfigPath }), { environments, ...withoutEnv } = content; if (content.environments) { let envCount = Object.keys(content.environments).length; if (envCount === 0) contentFromConfig = withoutEnv; else if (envCount === 1) contentFromConfig = mergeRsbuildConfig( withoutEnv, content.environments[0] ); else { let userEnv = builderOptions.environment; if (typeof userEnv != "string") throw new Error( "You must specify an environment when there are multiple environments in the Rsbuild config." ); if (Object.keys(content.environments).includes(userEnv)) contentFromConfig = mergeRsbuildConfig( withoutEnv, content.environments[userEnv] ); else throw new Error( `The specified environment "${userEnv}" is not found in the Rsbuild config.` ); } } else contentFromConfig = content; let resourceFilename = isProd ? "static/media/[name].[contenthash:8][ext]" : "static/media/[path][name][ext]", rsbuildConfig = mergeRsbuildConfig(contentFromConfig, { output: { cleanDistPath: !1, assetPrefix: "", dataUriLimit: { media: 1e4 }, sourceMap: { js: options.build?.test?.disableSourcemaps ? !1 : "cheap-module-source-map", css: !options.build?.test?.disableSourcemaps }, distPath: { root: resolve3(process.cwd(), outputDir) }, filename: { js: isProd ? "[name].[contenthash:8].iframe.bundle.js" : "[name].iframe.bundle.js", image: resourceFilename, font: resourceFilename, media: resourceFilename }, externals }, server: { // Storybook will handle public directory itself, disable Rsbuild's public dir // feature to prevent overwriting Storybook's public directory. publicDir: !1 }, dev: { assetPrefix: "", progressBar: !quiet, hmr: shouldDisableHmr ? !1 : void 0 }, resolve: { alias: { ...storybookPaths } }, source: { define: { ...stringifyProcessEnvs(envs), NODE_ENV: JSON.stringify(process.env.NODE_ENV) } }, // Rsbuild v1 compatible: `performance.chunkSplit` is deprecated in Rsbuild v2, use top-level `splitChunks` instead. ...rspackMajorVersion === 1 ? { performance: { chunkSplit: { strategy: "custom", splitChunks: { chunks: "all" } }, buildCache: cacheConfig } } : { splitChunks: { preset: "none", chunks: "all" }, performance: { buildCache: cacheConfig } }, plugins: [ shouldCheckTs ? pluginTypeCheck(tsCheckOptions) : null, pluginHtmlMinifierTerser(() => ({ collapseWhitespace: !0, removeComments: !0, removeRedundantAttributes: !0, removeScriptTypeAttributes: !1, removeStyleLinkTypeAttributes: !0, useShortDoctype: !0 })) ].filter(Boolean), tools: { swc: (config) => { config.env ??= {}, config.env.bugfixes = !0; }, rspack: (config, { addRules, appendRules, rspack: rspack2, mergeConfig }) => { if (addRules({ test: /\.stories\.([tj])sx?$|(stories|story)\.mdx$/, exclude: /node_modules/, enforce: "post", use: [ { loader: require2.resolve( "storybook-builder-rsbuild/loaders/export-order-loader" ) } ] }), config.module ??= {}, config.module.parser ??= {}, config.module.parser.javascript ??= {}, config.module.parser.javascript.unknownContextCritical = !1, config.resolve ??= {}, config.resolve.symlinks = !isPreservingSymlinks(), config.resolve.extensions = Array.from( /* @__PURE__ */ new Set([ ...config.resolve.extensions ?? [], ...builtInResolveExtensions ]) ), config.watchOptions = { ignored: /node_modules/ }, config.ignoreWarnings = [ ...config.ignoreWarnings || [], /export '\S+' was not found in 'global'/, /export '\S+' was not found in '@storybook\/global'/ ], config.resolve ??= {}, config.resolve.fallback ??= { stream: !1, path: require2.resolve("path-browserify"), assert: require2.resolve("browser-assert"), util: require2.resolve("util"), url: require2.resolve("url"), fs: !1, constants: require2.resolve("constants-browserify") }, config.optimization ??= {}, config.optimization.runtimeChunk = !0, config.optimization.usedExports = options.build?.test?.disableTreeShaking ? !1 : isProd, config.optimization.moduleIds = "named", config.module ??= {}, config.module.parser ??= {}, config.module.parser.javascript ??= {}, config.module.parser.javascript.exportsPresence = !1, !rspack2.experiments?.VirtualModulesPlugin) throw new Error( "rspack.experiments.VirtualModulesPlugin requires at least 1.5.0 version of @rsbuild/core, please upgrade or downgrade storybook-rsbuild-builder to lower version." ); if (config.plugins ??= [], config.plugins.push( ...[ Object.keys(virtualModuleMapping).length > 0 ? new rspack2.experiments.VirtualModulesPlugin( virtualModuleMapping ) : null, new rspack2.ProvidePlugin({ process: require2.resolve("process/browser.js") }), new CaseSensitivePathsPlugin() ].filter(Boolean) ), rspackMajorVersion === 1) { let experiments = config.experiments ??= {}; experiments.outputModule = !1; } return config.externalsType = "var", config.output ??= {}, config.output.module = !1, config.output.chunkFormat = "array-push", config.output.chunkLoading = "jsonp", lazyCompilationConfig !== void 0 && (config.lazyCompilation = lazyCompilationConfig), appendRules({ resourceQuery: RAW_QUERY_REGEX, type: "asset/source" }), mergeConfig( config, extraWebpackConfig || {}, webpackConfigFromPresets ); }, htmlPlugin: { filename: "iframe.html", // FIXME: `none` isn't a known option chunksSortMode: "none", alwaysWriteToDisk: !0, inject: !1, template, templateParameters: { version: packageJson?.version ?? "0.0.0-storybook-rsbuild-unknown-version", globals: { CONFIG_TYPE: configType, LOGLEVEL: logLevel, FRAMEWORK_OPTIONS: frameworkOptions, CHANNEL_OPTIONS: coreOptions.channelOptions, FEATURES: features, PREVIEW_URL: previewUrl, STORIES: stories.map((specifier) => ({ ...specifier, importPathMatcher: specifier.importPathMatcher.source })), DOCS_OPTIONS: docsOptions, TAGS_OPTIONS: tagsOptions, ...build2?.test?.disableBlocks ? { __STORYBOOK_BLOCKS_EMPTY_MODULE__: {} } : {} }, headHtmlSnippet, bodyHtmlSnippet } } } }); return rsbuildConfig.source ??= {}, rsbuildConfig.source.entry = { main: [...entries ?? [], ...dynamicEntries] }, rsbuildConfig; }; // src/react-shims.ts import { readFile } from "node:fs/promises"; import { isAbsolute as isAbsolute3, join as join3 } from "node:path"; import { resolvePackageDir } from "storybook/internal/common"; var getIsReactVersion18or19 = async (options) => { let { legacyRootApi } = await options.presets.apply( "frameworkOptions" ) || {}; if (legacyRootApi) return !1; let reactDom = (await options.presets.apply( "resolvedReact", {} )).reactDom || resolvePackageDir("react-dom"); if (!isAbsolute3(reactDom)) return !1; let { version } = JSON.parse( await readFile(join3(reactDom, "package.json"), "utf-8") ); return version.startsWith("18") || version.startsWith("19") || version.startsWith("0.0.0"); }, applyReactShims = async (_config, options) => await getIsReactVersion18or19(options) ? {} : { resolve: { alias: { "@storybook/react-dom-shim": "@storybook/react-dom-shim/react-16" } } }; // src/index.ts var corePath = dirname2(__require.resolve("storybook/package.json")), printDuration = (startTime) => (0, import_pretty_hrtime.default)(process.hrtime(startTime)).replace(" ms", " milliseconds").replace(" s", " seconds").replace(" m", " minutes"), executor = { get: async (options) => await options.presets.apply("rsbuildInstance") || rsbuildReal }, isObject = (val) => val != null && typeof val == "object" && Array.isArray(val) === !1; function nonNullables(value) { return value !== void 0; } var rsbuild = async (_, options) => { let { presets } = options, resolvedWebpackAddons = (await presets.apply("webpackAddons") ?? []).map((preset) => { let addonOptions = isObject(preset) && preset.options || void 0, name = isObject(preset) ? preset.name : preset; return resolveAddonName(options.configDir, name, addonOptions); }).filter(nonNullables), { apply } = await getPresets(resolvedWebpackAddons, options), webpackAddonsConfig = await apply( "webpackFinal", // TODO: using empty webpack config as base for now. It's better to using the composed rspack // config in `iframe-rsbuild.config.ts` as base config. But when `tools.rspack` is an async function, // the following `tools.rspack` raise an `Promises are not supported` error. { output: {}, module: {}, plugins: [], resolve: {}, // https://github.com/web-infra-dev/rsbuild/blob/8dc35dc1d1500d2f119875d46b6a07e27986d532/packages/core/src/provider/rspackConfig.ts#L167 devServer: void 0, optimization: {}, performance: {}, externals: {}, experiments: {}, node: {}, stats: {}, entry: {} }, options ), intrinsicRsbuildConfig = await iframe_rsbuild_config_default(options, webpackAddonsConfig), shimsConfig = await applyReactShims(intrinsicRsbuildConfig, options); return intrinsicRsbuildConfig = rsbuildReal.mergeRsbuildConfig( intrinsicRsbuildConfig, shimsConfig ), await presets.apply( "rsbuildFinal", intrinsicRsbuildConfig, options ); }, getConfig = async (options) => { let { presets } = options, typescriptOptions = await presets.apply("typescript", {}, options), frameworkOptions = await presets.apply("frameworkOptions"); return rsbuild({}, { ...options, typescriptOptions, frameworkOptions }); }, server; async function bail() { return server?.close(); } var start = async ({ startTime, options, router, server: storybookServer }) => { overrideRsbuildLogger(); let { createRsbuild } = await executor.get(options), config = await getConfig(options), rsbuildBuild = await createRsbuild({ cwd: process.cwd(), rsbuildConfig: { ...config, server: { ...config.server, port: await getRandomPort(options.host), host: options.host, htmlFallback: !1, printUrls: !1 } } }), rsbuildServer = await rsbuildBuild.createDevServer(), waitFirstCompileDone = new Promise((resolve4) => { rsbuildBuild.onDevCompileDone(({ stats: stats2, isFirstCompile }) => { isFirstCompile && resolve4(stats2); }); }); if (server = rsbuildServer, !rsbuildBuild) throw new WebpackInvocationError({ // eslint-disable-next-line local-rules/no-uncategorized-errors error: new Error("Missing Rsbuild build instance at runtime!") }); let previewDirOrigin = join4(corePath, "dist/preview"); router.use( "/sb-preview", sirv(previewDirOrigin, { maxAge: 3e5, dev: !0, immutable: !0 }) ), router.use(rsbuildServer.middlewares), rsbuildServer.connectWebSocket({ server: storybookServer }); let stats = await waitFirstCompileDone; return await server.afterListen(), { bail, stats, totalTime: process.hrtime(startTime) }; }, build = async ({ options }) => { overrideRsbuildLogger(); let { createRsbuild } = await executor.get(options), config = await getConfig(options), rsbuildBuild = await createRsbuild({ cwd: process.cwd(), rsbuildConfig: config }), previewDirOrigin = join4(corePath, "dist/preview"), previewDirTarget = join4(options.outputDir || "", "sb-preview"), stats; rsbuildBuild.onAfterBuild((params) => { stats = params.stats; }); let previewFiles = fs.copy(previewDirOrigin, previewDirTarget, { filter: (src) => { let { ext } = parse(src); return ext ? ext === ".js" : !0; } }), [{ close }] = await Promise.all([rsbuildBuild.build(), previewFiles]); return await close(), withStatsJsonCompat(stats); }, corePresets = [join4(__dirname, "./preview-preset.js")], previewMainTemplate = () => __require.resolve("storybook-builder-rsbuild/templates/preview.ejs"); function getRandomPort(host) { return new Promise((resolve4, reject) => { let server2 = createServer(); server2.unref(), server2.on("error", reject), server2.listen({ port: 0, host }, () => { let { port } = server2.address(); server2.close(() => { resolve4(port); }); }); }); } export { bail, build, corePresets, executor, getConfig, getVirtualModules, previewMainTemplate, printDuration, start };