fix(storybook): handle output-dir properly for outputs (#21168)

This commit is contained in:
Katerina Skroumpelou 2024-01-17 16:07:12 +02:00 committed by GitHub
parent d966d21b96
commit 01ae336eea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 81 additions and 55 deletions

View File

@ -66,7 +66,9 @@ export async function configurationGenerator(
); );
const { compiler } = findStorybookAndBuildTargetsAndCompiler(targets); const { compiler } = findStorybookAndBuildTargetsAndCompiler(targets);
const viteConfigFilePath = findViteConfig(tree, root); const viteConfig = findViteConfig(tree, root);
const viteConfigFilePath = viteConfig?.fullConfigPath;
const viteConfigFileName = viteConfig?.viteConfigFileName;
const nextConfigFilePath = findNextConfig(tree, root); const nextConfigFilePath = findNextConfig(tree, root);
if (viteConfigFilePath) { if (viteConfigFilePath) {
@ -130,7 +132,9 @@ export async function configurationGenerator(
!!nextConfigFilePath, !!nextConfigFilePath,
compiler === 'swc', compiler === 'swc',
usesVite, usesVite,
viteConfigFilePath viteConfigFilePath,
hasPlugin,
viteConfigFileName
); );
if (schema.uiFramework !== '@storybook/angular') { if (schema.uiFramework !== '@storybook/angular') {

View File

@ -536,7 +536,9 @@ export function createProjectStorybookDir(
isNextJs?: boolean, isNextJs?: boolean,
usesSwc?: boolean, usesSwc?: boolean,
usesVite?: boolean, usesVite?: boolean,
viteConfigFilePath?: string viteConfigFilePath?: string,
hasPlugin?: boolean,
viteConfigFileName?: string
) { ) {
let projectDirectory = let projectDirectory =
projectType === 'application' projectType === 'application'
@ -579,6 +581,8 @@ export function createProjectStorybookDir(
usesVite, usesVite,
isRootProject: projectIsRootProjectInStandaloneWorkspace, isRootProject: projectIsRootProjectInStandaloneWorkspace,
viteConfigFilePath, viteConfigFilePath,
hasPlugin,
viteConfigFileName,
}); });
if (js) { if (js) {
@ -699,13 +703,19 @@ export async function getE2EProjectName(
export function findViteConfig( export function findViteConfig(
tree: Tree, tree: Tree,
projectRoot: string projectRoot: string
): string | undefined { ): {
fullConfigPath: string | undefined;
viteConfigFileName: string | undefined;
} {
const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts']; const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts'];
for (const ext of allowsExt) { for (const ext of allowsExt) {
const viteConfigPath = joinPathFragments(projectRoot, `vite.config.${ext}`); const viteConfigPath = joinPathFragments(projectRoot, `vite.config.${ext}`);
if (tree.exists(viteConfigPath)) { if (tree.exists(viteConfigPath)) {
return viteConfigPath; return {
fullConfigPath: viteConfigPath,
viteConfigFileName: `vite.config.${ext}`,
};
} }
} }
} }

View File

@ -14,7 +14,11 @@ const config: StorybookConfig = {
framework: { framework: {
name: '<%= uiFramework %>', name: '<%= uiFramework %>',
options: { options: {
<% if (usesVite && viteConfigFilePath) { %> <% if (usesVite && viteConfigFilePath && hasPlugin) { %>
builder: {
viteConfigPath: '<%= viteConfigFileName %>',
},
<% } %><% if (usesVite && viteConfigFilePath && !hasPlugin) { %>
builder: { builder: {
viteConfigPath: '<%= viteConfigFilePath %>', viteConfigPath: '<%= viteConfigFilePath %>',
}, },

View File

@ -13,7 +13,12 @@ const config = {
framework: { framework: {
name: '<%= uiFramework %>', name: '<%= uiFramework %>',
options: { options: {
<% if (usesVite && viteConfigFilePath) { %> <% if (usesVite && viteConfigFilePath && hasPlugin) { %>
builder: {
viteConfigPath: '<%= viteConfigFileName %>',
},
<% } %>
<% if (usesVite && viteConfigFilePath && !hasPlugin) { %>
builder: { builder: {
viteConfigPath: '<%= viteConfigFilePath %>', viteConfigPath: '<%= viteConfigFilePath %>',
}, },

View File

@ -72,10 +72,17 @@ describe('@nx/storybook/plugin', () => {
expect( expect(
nodes?.['projects']?.['my-app']?.targets?.['build-storybook'] nodes?.['projects']?.['my-app']?.targets?.['build-storybook']
).toMatchObject({ ).toMatchObject({
command: command: 'storybook build',
'storybook build --config-dir my-app/.storybook --output-dir dist/storybook/my-app', options: {
cwd: 'my-app',
},
cache: true, cache: true,
outputs: ['{workspaceRoot}/dist/storybook/{projectRoot}'], outputs: [
'{workspaceRoot}/{projectRoot}/static-storybook',
'{options.output-dir}',
'{options.outputDir}',
'{options.o}',
],
inputs: [ inputs: [
'production', 'production',
'^production', '^production',
@ -86,12 +93,12 @@ describe('@nx/storybook/plugin', () => {
expect( expect(
nodes?.['projects']?.['my-app']?.targets?.['storybook'] nodes?.['projects']?.['my-app']?.targets?.['storybook']
).toMatchObject({ ).toMatchObject({
command: 'storybook dev --config-dir my-app/.storybook', command: 'storybook dev',
}); });
expect( expect(
nodes?.['projects']?.['my-app']?.targets?.['test-storybook'] nodes?.['projects']?.['my-app']?.targets?.['test-storybook']
).toMatchObject({ ).toMatchObject({
command: 'test-storybook --config-dir my-app/.storybook', command: 'test-storybook',
}); });
}); });
@ -128,13 +135,18 @@ describe('@nx/storybook/plugin', () => {
).toMatchObject({ ).toMatchObject({
executor: '@storybook/angular:build-storybook', executor: '@storybook/angular:build-storybook',
options: { options: {
outputDir: 'dist/storybook/my-ng-app', outputDir: 'my-ng-app/static-storybook',
configDir: 'my-ng-app/.storybook', configDir: 'my-ng-app/.storybook',
browserTarget: 'my-ng-app:build-storybook', browserTarget: 'my-ng-app:build-storybook',
compodoc: false, compodoc: false,
}, },
cache: true, cache: true,
outputs: ['{workspaceRoot}/dist/storybook/{projectRoot}'], outputs: [
'{workspaceRoot}/{projectRoot}/static-storybook',
'{options.output-dir}',
'{options.outputDir}',
'{options.o}',
],
inputs: [ inputs: [
'production', 'production',
'^production', '^production',
@ -161,7 +173,7 @@ describe('@nx/storybook/plugin', () => {
expect( expect(
nodes?.['projects']?.['my-ng-app']?.targets?.['test-storybook'] nodes?.['projects']?.['my-ng-app']?.targets?.['test-storybook']
).toMatchObject({ ).toMatchObject({
command: 'test-storybook --config-dir my-ng-app/.storybook', command: 'test-storybook',
}); });
}); });
}); });

View File

@ -64,6 +64,7 @@ export const createNodes: CreateNodes<StorybookPluginOptions> = [
if (projectRoot === '') { if (projectRoot === '') {
projectRoot = '.'; projectRoot = '.';
} }
// Do not create a project if package.json and project.json isn't there. // Do not create a project if package.json and project.json isn't there.
const siblingFiles = readdirSync(join(context.workspaceRoot, projectRoot)); const siblingFiles = readdirSync(join(context.workspaceRoot, projectRoot));
if ( if (
@ -101,7 +102,7 @@ export const createNodes: CreateNodes<StorybookPluginOptions> = [
}, },
}; };
// For root projects, the name is not inferred from root package.json, so we need to manually set it. // For root projects, the name is not inferred from root package.json, so we need to manually set it.
// TODO(jack): We should handle this in core and remove this workaround. // TODO(katerina): Remove this workaround once Craigory's PR (https://github.com/nrwl/nx/pull/21125) is merged
if (projectRoot === '.') { if (projectRoot === '.') {
result.projects[projectRoot]['name'] = projectName; result.projects[projectRoot]['name'] = projectName;
} }
@ -130,19 +131,20 @@ function buildStorybookTargets(
targets[options.buildStorybookTargetName] = buildTarget( targets[options.buildStorybookTargetName] = buildTarget(
namedInputs, namedInputs,
buildOutputs, buildOutputs,
configFilePath,
projectRoot, projectRoot,
frameworkIsAngular, frameworkIsAngular,
projectName projectName,
configFilePath
); );
targets[options.serveStorybookTargetName] = serveTarget( targets[options.serveStorybookTargetName] = serveTarget(
configFilePath, projectRoot,
frameworkIsAngular, frameworkIsAngular,
projectName projectName,
configFilePath
); );
targets[options.testStorybookTargetName] = testTarget(configFilePath); targets[options.testStorybookTargetName] = testTarget(projectRoot);
targets[options.staticStorybookTargetName] = serveStaticTarget( targets[options.staticStorybookTargetName] = serveStaticTarget(
options, options,
@ -157,23 +159,21 @@ function buildTarget(
[inputName: string]: any[]; [inputName: string]: any[];
}, },
outputs: string[], outputs: string[],
configFilePath: string,
projectRoot: string, projectRoot: string,
frameworkIsAngular: boolean, frameworkIsAngular: boolean,
projectName: string projectName: string,
configFilePath: string
) { ) {
const outputDir = joinPathFragments('dist/storybook', projectRoot);
let targetConfig: TargetConfiguration; let targetConfig: TargetConfiguration;
if (frameworkIsAngular) { if (frameworkIsAngular) {
targetConfig = { targetConfig = {
executor: '@storybook/angular:build-storybook', executor: '@storybook/angular:build-storybook',
options: { options: {
outputDir: `${outputDir}`,
configDir: `${dirname(configFilePath)}`, configDir: `${dirname(configFilePath)}`,
browserTarget: `${projectName}:build-storybook`, browserTarget: `${projectName}:build-storybook`,
compodoc: false, compodoc: false,
outputDir: joinPathFragments(projectRoot, 'static-storybook'),
}, },
cache: true, cache: true,
outputs, outputs,
@ -192,9 +192,8 @@ function buildTarget(
}; };
} else { } else {
targetConfig = { targetConfig = {
command: `storybook build --config-dir ${dirname( command: `storybook build`,
configFilePath options: { cwd: projectRoot },
)} --output-dir ${outputDir}`,
cache: true, cache: true,
outputs, outputs,
inputs: [ inputs: [
@ -212,9 +211,10 @@ function buildTarget(
} }
function serveTarget( function serveTarget(
configFilePath: string, projectRoot: string,
frameworkIsAngular: boolean, frameworkIsAngular: boolean,
projectName: string projectName: string,
configFilePath: string
) { ) {
if (frameworkIsAngular) { if (frameworkIsAngular) {
return { return {
@ -227,14 +227,16 @@ function serveTarget(
}; };
} else { } else {
return { return {
command: `storybook dev --config-dir ${dirname(configFilePath)}`, command: `storybook dev`,
options: { cwd: projectRoot },
}; };
} }
} }
function testTarget(configFilePath: string) { function testTarget(projectRoot: string) {
const targetConfig: TargetConfiguration = { const targetConfig: TargetConfiguration = {
command: `test-storybook --config-dir ${dirname(configFilePath)}`, command: `test-storybook`,
options: { cwd: projectRoot },
inputs: [ inputs: [
{ {
externalDependencies: ['storybook', '@storybook/test-runner'], externalDependencies: ['storybook', '@storybook/test-runner'],
@ -253,8 +255,7 @@ function serveStaticTarget(
executor: '@nx/web:file-server', executor: '@nx/web:file-server',
options: { options: {
buildTarget: `${options.buildStorybookTargetName}`, buildTarget: `${options.buildStorybookTargetName}`,
// TODO(katerina): need to read the output from CLI args staticFilePath: joinPathFragments(projectRoot, 'static-storybook'),
staticFilePath: joinPathFragments('dist/storybook', projectRoot),
}, },
}; };
@ -316,12 +317,14 @@ function getStorybookConfig(
} }
function getOutputs(_projectRoot: string): string[] { function getOutputs(_projectRoot: string): string[] {
// TODO(katerina): need to read the output from CLI args
// const outputPath = <output path as read from CLI>;
const normalizedOutputPath = normalizeOutputPath(undefined, _projectRoot); const normalizedOutputPath = normalizeOutputPath(undefined, _projectRoot);
const outputs = [normalizedOutputPath]; const outputs = [
normalizedOutputPath,
`{options.output-dir}`,
`{options.outputDir}`,
`{options.o}`,
];
return outputs; return outputs;
} }
@ -330,22 +333,10 @@ function normalizeOutputPath(
outputPath: string | undefined, outputPath: string | undefined,
projectRoot: string projectRoot: string
): string | undefined { ): string | undefined {
if (!outputPath) { if (projectRoot === '.') {
if (projectRoot === '.') { return `{projectRoot}/static-storybook`;
return `{projectRoot}/dist/storybook`;
} else {
return `{workspaceRoot}/dist/storybook/{projectRoot}`;
}
} else { } else {
if (isAbsolute(outputPath)) { return `{workspaceRoot}/{projectRoot}/static-storybook`;
return `{workspaceRoot}/${relative(workspaceRoot, outputPath)}`;
} else {
if (outputPath.startsWith('..')) {
return join('{workspaceRoot}', join(projectRoot, outputPath));
} else {
return join('{projectRoot}', outputPath);
}
}
} }
} }