storybook-builder-rsbuild
Version:
Rsbuild builder for Storybook
172 lines (165 loc) • 6.96 kB
JavaScript
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 "./_node-chunks/chunk-L73IVHZJ.js";
// src/preview-preset.ts
import { createRequire } from "node:module";
import { fileURLToPath as fileURLToPath2 } from "node:url";
import { findConfigFile } from "storybook/internal/common";
// src/plugins/rspack-inject-mocker-runtime-plugin.ts
import { getMockerRuntime } from "storybook/internal/mocking-utils";
var PLUGIN_NAME = "RspackInjectMockerRuntimePlugin", RspackInjectMockerRuntimePlugin = class {
getHtmlPlugin(compiler) {
try {
return compiler.options.plugins?.find((plugin) => {
let name = plugin?.constructor?.name;
return name === "HtmlRspackPlugin" || name === "HtmlWebpackPlugin";
})?.constructor;
} catch (error) {
return compiler.getInfrastructureLogger(PLUGIN_NAME).warn(
`Unable to locate HTML plugin for mock runtime injection: ${error}`
), null;
}
}
apply(compiler) {
let HtmlPlugin = this.getHtmlPlugin(compiler);
if (!HtmlPlugin || typeof HtmlPlugin.getHooks != "function") {
compiler.getInfrastructureLogger(PLUGIN_NAME).warn("HTML plugin is not available. Cannot inject mocker runtime.");
return;
}
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
HtmlPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync(
PLUGIN_NAME,
(data, cb) => {
try {
let runtimeScriptContent = getMockerRuntime(), runtimeAssetName = "mocker-runtime-injected.js", Sources = compiler.webpack?.sources;
if (!Sources?.RawSource)
throw new Error(
"rspack sources is not available on compiler.webpack"
);
compilation.emitAsset(
runtimeAssetName,
new Sources.RawSource(runtimeScriptContent)
), data.assets.js.unshift(runtimeAssetName), cb(null, data);
} catch (error) {
cb(error);
}
}
);
});
}
};
// src/plugins/rspack-mock-plugin.ts
import { dirname, isAbsolute } from "node:path";
import { fileURLToPath } from "node:url";
import { rspack } from "@rsbuild/core";
import { findMockRedirect } from "@vitest/mocker/redirect";
import {
babelParser,
extractMockCalls,
getIsExternal,
resolveExternalModule,
resolveWithExtensions
} from "storybook/internal/mocking-utils";
var PLUGIN_NAME2 = "RspackMockPlugin";
function normalizePath(filePath) {
return filePath.replace(/\\/g, "/");
}
var RspackMockPlugin = class {
constructor(options) {
this.mockMap = /* @__PURE__ */ new Map();
if (!options.previewConfigPath)
throw new Error(`[${PLUGIN_NAME2}] \`previewConfigPath\` is required.`);
this.options = options;
}
apply(compiler) {
let logger = compiler.getInfrastructureLogger(PLUGIN_NAME2), updateMocks = () => {
this.mockMap = new Map(
this.extractAndResolveMocks(compiler).flatMap((mock) => [
[normalizePath(mock.absolutePath), mock],
[normalizePath(mock.absolutePath.replace(/\.[^.]+$/, "")), mock]
])
), logger.info(`Mock map updated with ${this.mockMap.size / 2} mocks.`);
};
compiler.hooks.beforeRun.tap(PLUGIN_NAME2, updateMocks), compiler.hooks.watchRun.tap(PLUGIN_NAME2, updateMocks), new rspack.NormalModuleReplacementPlugin(/.*/, (resource) => {
try {
let path = resource.request, importer = resource.context, absolutePath = getIsExternal(path, importer) ? resolveExternalModule(path, importer) : resolveWithExtensions(path, importer), normalizedAbsolutePath = normalizePath(absolutePath);
this.mockMap.has(normalizedAbsolutePath) && (resource.request = this.mockMap.get(
normalizedAbsolutePath
).replacementResource);
} catch {
logger.debug(`Could not resolve mock for "${resource.request}".`);
}
}).apply(compiler), compiler.hooks.afterCompile.tap(PLUGIN_NAME2, (compilation) => {
compilation.fileDependencies.add(this.options.previewConfigPath);
for (let mock of this.mockMap.values())
isAbsolute(mock.replacementResource) && mock.replacementResource.includes("__mocks__") && compilation.contextDependencies.add(dirname(mock.replacementResource));
});
}
extractAndResolveMocks(compiler) {
let { previewConfigPath, configDir } = this.options, logger = compiler.getInfrastructureLogger(PLUGIN_NAME2), mocks = extractMockCalls(
{
previewConfigPath,
configDir: configDir ?? dirname(previewConfigPath)
},
babelParser,
compiler.context,
findMockRedirect
), resolvedMocks = [];
for (let mock of mocks)
try {
let { absolutePath, redirectPath } = mock, replacementResource;
redirectPath ? replacementResource = redirectPath : replacementResource = `${fileURLToPath(
import.meta.resolve(
"storybook-builder-rsbuild/loaders/rsbuild-automock-loader"
)
)}?spy=${mock.spy}!${absolutePath}`, resolvedMocks.push({
...mock,
replacementResource
});
} catch {
logger.warn(
`Could not resolve mock for "${mock.path}". It will be ignored.`
);
}
return resolvedMocks;
}
};
// src/preview-preset.ts
var require2 = createRequire(import.meta.url), previewMainTemplate = () => require2.resolve("storybook-builder-rsbuild/templates/preview.ejs");
async function rsbuildFinal(config, options) {
let previewConfigPath = findConfigFile("preview", options.configDir);
if (!previewConfigPath)
return config;
let applyMocking = (rspackConfig, utils) => (utils.addRules({
test: /preview\.(t|j)sx?$/,
use: [
{
loader: fileURLToPath2(
import.meta.resolve(
"storybook-builder-rsbuild/loaders/storybook-mock-transform-loader"
)
)
}
]
}), rspackConfig.plugins ??= [], rspackConfig.plugins.push(new RspackMockPlugin({ previewConfigPath })), rspackConfig.plugins.push(new RspackInjectMockerRuntimePlugin()), rspackConfig);
return {
...config,
tools: {
...config.tools,
rspack: Array.isArray(config.tools?.rspack) ? [...config.tools.rspack, applyMocking] : [config.tools?.rspack, applyMocking].filter(
(v) => !!v
)
}
};
}
export {
previewMainTemplate,
rsbuildFinal
};