Files
emaui/node_modules/@nx/react/plugins/storybook/index.js
2026-05-29 15:23:46 +03:00

177 lines
7.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.webpack = exports.core = void 0;
const devkit_1 = require("@nx/devkit");
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
const config_1 = require("@nx/webpack/src/utils/config");
const fs_1 = require("fs");
const path_1 = require("path");
const webpack_1 = require("webpack");
const with_react_1 = require("../with-react");
const merge_plugins_1 = require("./merge-plugins");
// This is shamelessly taken from CRA and modified for NX use
// https://github.com/facebook/create-react-app/blob/4784997f0682e75eb32a897b4ffe34d735912e6c/packages/react-scripts/config/env.js#L71
function getClientEnvironment(mode) {
// Grab NODE_ENV and NX_* and STORYBOOK_* environment variables and prepare them to be
// injected into the application via DefinePlugin in webpack configuration.
const NX_PREFIX = /^NX_PUBLIC_/i;
const STORYBOOK_PREFIX = /^STORYBOOK_/i;
const raw = Object.keys(process.env)
.filter((key) => NX_PREFIX.test(key) || STORYBOOK_PREFIX.test(key))
.reduce((env, key) => {
env[key] = process.env[key];
return env;
}, {
// Useful for determining whether were running in production mode.
NODE_ENV: process.env.NODE_ENV || mode,
// Environment variables for Storybook
// https://github.com/storybookjs/storybook/blob/bdf9e5ed854b8d34e737eee1a4a05add88265e92/lib/core-common/src/utils/envs.ts#L12-L21
NODE_PATH: process.env.NODE_PATH || '',
STORYBOOK: process.env.STORYBOOK || 'true',
// This is to support CRA's public folder feature.
// In production we set this to dot(.) to allow the browser to access these assets
// even when deployed inside a subpath. (like in GitHub pages)
// In development this is just empty as we always serves from the root.
PUBLIC_URL: mode === 'production' ? '.' : '',
});
// Stringify all values so we can feed into webpack DefinePlugin
const stringified = Object.keys(raw).reduce((env, key) => {
env[`process.env.${key}`] = JSON.stringify(raw[key]);
return env;
},
// Provide a fallback for process.env itself to handle cases where code
// accesses process.env directly (e.g., in Cypress component testing)
{ 'process.env': '({})' });
return { stringified };
}
const core = (prev, options) => ({
...prev,
disableWebpackDefaults: true,
});
exports.core = core;
const getProjectData = async (storybookOptions) => {
const fallbackData = {
workspaceRoot: storybookOptions.configDir,
projectRoot: '',
sourceRoot: '',
};
// Edge-case: not running from Nx
if (!process.env.NX_WORKSPACE_ROOT)
return fallbackData;
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
const projectNode = projectGraph.nodes[process.env.NX_TASK_TARGET_PROJECT];
return projectNode
? {
workspaceRoot: process.env.NX_WORKSPACE_ROOT,
projectRoot: projectNode.data.root,
sourceRoot: (0, ts_solution_setup_1.getProjectSourceRoot)(projectNode.data),
projectNode,
}
: // Edge-case: missing project node
fallbackData;
};
const fixBabelConfigurationIfNeeded = (webpackConfig, projectData) => {
if (!projectData.projectNode)
return;
const isUsingBabelUpwardRootMode = Object.keys(projectData.projectNode.data.targets).find((k) => {
const targetConfig = projectData.projectNode.data.targets[k];
return (targetConfig.executor === '@nx/webpack:webpack' &&
targetConfig.options?.babelUpwardRootMode);
});
if (isUsingBabelUpwardRootMode)
return;
let babelrcPath;
for (const ext of ['', '.json', '.js', '.cjs', '.mjs', '.cts']) {
const candidate = (0, path_1.join)(projectData.workspaceRoot, projectData.projectRoot, `.babelrc${ext}`);
if ((0, fs_1.existsSync)(candidate)) {
babelrcPath = candidate;
break;
}
}
// Unexpected setup, skip.
if (!babelrcPath)
return;
let babelRuleItem;
for (const rule of webpackConfig.module.rules) {
if (typeof rule === 'string')
continue;
if (!rule || !Array.isArray(rule.use))
continue;
for (const item of rule.use) {
if (typeof item !== 'string' && item['loader'].includes('babel-loader')) {
babelRuleItem = item;
break;
}
}
}
if (babelRuleItem) {
babelRuleItem.options.configFile = babelrcPath;
}
};
const webpack = async (storybookWebpackConfig = {}, options) => {
devkit_1.logger.info('=> Loading Nx React Storybook Addon from "@nx/react/plugins/storybook"');
// In case anyone is missing dep and did not run migrations.
// See: https://github.com/nrwl/nx/issues/14455
try {
require.resolve('@nx/webpack');
}
catch {
throw new Error(`'@nx/webpack' package is not installed. Install it and try again.`);
}
const { withNx, withWeb } = require('@nx/webpack');
const projectData = await getProjectData(options);
const tsconfigPath = (0, fs_1.existsSync)((0, path_1.join)(projectData.projectRoot, 'tsconfig.storybook.json'))
? (0, path_1.join)(projectData.projectRoot, 'tsconfig.storybook.json')
: (0, path_1.join)(projectData.projectRoot, 'tsconfig.json');
// The 'tsconfig.json' is mainly for the cypress test to be able to run
// because it will look into the cypress project dir and it will not find tsconfig.storybook.json
fixBabelConfigurationIfNeeded(storybookWebpackConfig, projectData);
const builderOptions = {
...options,
root: projectData.workspaceRoot,
projectRoot: projectData.projectRoot,
sourceRoot: (0, ts_solution_setup_1.getProjectSourceRoot)(projectData.projectNode.data),
fileReplacements: [],
sourceMap: true,
styles: options.styles ?? [],
optimization: {},
tsConfig: tsconfigPath,
extractCss: storybookWebpackConfig.mode === 'production',
target: 'web',
};
// ESM build for modern browsers.
let baseWebpackConfig = {};
const configure = (0, config_1.composePluginsSync)(withNx({ target: 'web', skipTypeChecking: true }), (0, with_react_1.withReact)());
const finalConfig = configure(baseWebpackConfig, {
options: builderOptions,
// TODO(JamesHenry): replace as any type assertion with as ExecutorContext once the nx repo is updated to use https://github.com/nrwl/nx/pull/33095
context: { root: devkit_1.workspaceRoot }, // The context is not used here.
});
return {
...storybookWebpackConfig,
module: {
...storybookWebpackConfig.module,
rules: [
...storybookWebpackConfig.module.rules,
...finalConfig.module.rules,
],
},
resolve: {
...storybookWebpackConfig.resolve,
fallback: {
...storybookWebpackConfig.resolve?.fallback,
// Next.js and other React frameworks may have server-code that uses these modules.
// They are not meant for client-side components so skip the fallbacks.
assert: false,
path: false,
util: false,
},
plugins: (0, merge_plugins_1.mergePlugins)(...(storybookWebpackConfig.resolve.plugins ??
[]), ...(finalConfig.resolve
.plugins ?? [])),
},
plugins: (0, merge_plugins_1.mergePlugins)(new webpack_1.DefinePlugin(getClientEnvironment(storybookWebpackConfig.mode).stringified), ...(storybookWebpackConfig.plugins ?? []), ...(finalConfig.plugins ?? [])),
};
};
exports.webpack = webpack;