Skip to content

Commit

Permalink
Angular: Consider style inject option
Browse files Browse the repository at this point in the history
Currently, every kind of style is injected into the iframe HTML, although some of them are marked with inject:false to not inject them, but rather to leave it to the user to dynamically load them if required
  • Loading branch information
valentinpalkovic committed May 15, 2024
1 parent 99501d2 commit cca91fc
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 377 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { dirname, join, resolve } from 'path';
import { DefinePlugin, HotModuleReplacementPlugin, ProgressPlugin, ProvidePlugin } from 'webpack';
import type { Configuration } from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';

// @ts-expect-error (I removed this on purpose, because it's incorrect)
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import TerserWebpackPlugin from 'terser-webpack-plugin';
Expand Down Expand Up @@ -53,7 +54,11 @@ const storybookPaths: Record<string, string> = {
};

export default async (
options: Options & { typescriptOptions: TypescriptOptions }
options: Options & {
typescriptOptions: TypescriptOptions;
/* Build entries, which should not be linked in the iframe HTML file */
excludeChunks?: string[];
}
): Promise<Configuration> => {
const {
outputDir = join('.', 'public'),
Expand All @@ -64,6 +69,7 @@ export default async (
previewUrl,
typescriptOptions,
features,
excludeChunks = [],
} = options;

const isProd = configType === 'PRODUCTION';
Expand Down Expand Up @@ -172,6 +178,7 @@ export default async (
alwaysWriteToDisk: true,
inject: false,
template,
excludeChunks,
templateParameters: {
version: packageJson.version,
globals: {
Expand Down
183 changes: 71 additions & 112 deletions code/frameworks/angular/src/builders/build-storybook/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
import {
BuilderContext,
BuilderHandlerFn,
BuilderOutput,
BuilderOutputLike,
Target,
createBuilder,
targetFromTargetString,
} from '@angular-devkit/architect';
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { from, of, throwError } from 'rxjs';
import { catchError, map, mapTo, switchMap } from 'rxjs/operators';
import { sync as findUpSync } from 'find-up';
import { sync as readUpSync } from 'read-pkg-up';
import { BrowserBuilderOptions, StylePreprocessorOptions } from '@angular-devkit/build-angular';
import { StylePreprocessorOptions } from '@angular-devkit/build-angular';

import { CLIOptions } from '@storybook/types';
import { getEnvConfig, versions } from '@storybook/core-common';
Expand All @@ -22,11 +12,13 @@ import { buildStaticStandalone, withTelemetry } from '@storybook/core-server';
import {
AssetPattern,
SourceMapUnion,
StyleClass,
StyleElement,
} from '@angular-devkit/build-angular/src/builders/browser/schema';
import { StandaloneOptions } from '../utils/standalone-options';
import { runCompodoc } from '../utils/run-compodoc';
import { errorSummary, printErrorDetails } from '../utils/error-handler';
import { setup } from '../utils/setup';

addToGlobalContext('cliVersion', versions.storybook);

Expand Down Expand Up @@ -59,119 +51,86 @@ export type StorybookBuilderOptions = JsonObject & {

export type StorybookBuilderOutput = JsonObject & BuilderOutput & { [key: string]: any };

type StandaloneBuildOptions = StandaloneOptions & { outputDir: string };

const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = (
options,
context
): BuilderOutputLike => {
const builder = from(setup(options, context)).pipe(
switchMap(({ tsConfig }) => {
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
const runCompodoc$ = options.compodoc
? runCompodoc(
{ compodocArgs: options.compodocArgs, tsconfig: docTSConfig ?? tsConfig },
context
).pipe(mapTo({ tsConfig }))
: of({});

return runCompodoc$.pipe(mapTo({ tsConfig }));
}),
map(({ tsConfig }) => {
getEnvConfig(options, {
staticDir: 'SBCONFIG_STATIC_DIR',
outputDir: 'SBCONFIG_OUTPUT_DIR',
configDir: 'SBCONFIG_CONFIG_DIR',
});

const {
browserTarget,
stylePreprocessorOptions,
styles,
configDir,
docs,
loglevel,
test,
outputDir,
quiet,
enableProdMode = true,
webpackStatsJson,
statsJson,
debugWebpack,
disableTelemetry,
assets,
previewUrl,
sourceMap = false,
} = options;

const standaloneOptions: StandaloneBuildOptions = {
packageJson: readUpSync({ cwd: __dirname }).packageJson,
configDir,
...(docs ? { docs } : {}),
loglevel,
outputDir,
test,
quiet,
enableProdMode,
disableTelemetry,
angularBrowserTarget: browserTarget,
angularBuilderContext: context,
angularBuilderOptions: {
...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
...(styles ? { styles } : {}),
...(assets ? { assets } : {}),
sourceMap,
},
tsConfig,
webpackStatsJson,
statsJson,
debugWebpack,
previewUrl,
};

return standaloneOptions;
}),
switchMap((standaloneOptions) => runInstance({ ...standaloneOptions, mode: 'static' })),
map(() => {
return { success: true };
})
);

return builder as any as BuilderOutput;
};
type StandaloneBuildOptions = StandaloneOptions & { outputDir: string; excludeChunks: string[] };

export default createBuilder(commandBuilder);
const commandBuilder = async (
options: StorybookBuilderOptions,
context: BuilderContext
): Promise<BuilderOutput> => {
const { tsConfig, angularBuilderContext, angularBuilderOptions } = await setup(options, context);

async function setup(options: StorybookBuilderOptions, context: BuilderContext) {
let browserOptions: (JsonObject & BrowserBuilderOptions) | undefined;
let browserTarget: Target | undefined;
const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });

if (options.browserTarget) {
browserTarget = targetFromTargetString(options.browserTarget);
browserOptions = await context.validateOptions<JsonObject & BrowserBuilderOptions>(
await context.getTargetOptions(browserTarget),
await context.getBuilderNameForTarget(browserTarget)
if (options.compodoc) {
await runCompodoc(
{ compodocArgs: options.compodocArgs, tsconfig: docTSConfig ?? tsConfig },
context
);
}

return {
tsConfig:
options.tsConfig ??
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
browserOptions.tsConfig,
getEnvConfig(options, {
staticDir: 'SBCONFIG_STATIC_DIR',
outputDir: 'SBCONFIG_OUTPUT_DIR',
configDir: 'SBCONFIG_CONFIG_DIR',
});

const {
configDir,
docs,
loglevel,
test,
outputDir,
quiet,
enableProdMode = true,
webpackStatsJson,
statsJson,
debugWebpack,
disableTelemetry,
previewUrl,
} = options;

const standaloneOptions: StandaloneBuildOptions = {
packageJson: readUpSync({ cwd: __dirname }).packageJson,
configDir,
...(docs ? { docs } : {}),
excludeChunks: angularBuilderOptions.styles
?.filter((style) => typeof style !== 'string' && style.inject === false)
.map((s: StyleClass) => s.bundleName),
loglevel,
outputDir,
test,
quiet,
enableProdMode,
disableTelemetry,
angularBrowserTarget: options.browserTarget,
angularBuilderContext,
angularBuilderOptions,
tsConfig,
webpackStatsJson,
statsJson,
debugWebpack,
previewUrl,
};
}

function runInstance(options: StandaloneBuildOptions) {
return from(
withTelemetry(
await runInstance({ ...standaloneOptions, mode: 'static' });

return { success: true };
};

export default createBuilder(commandBuilder);

async function runInstance(options: StandaloneBuildOptions) {
try {
await withTelemetry(
'build',
{
cliOptions: options,
presetOptions: { ...options, corePresets: [], overridePresets: [] },
printError: printErrorDetails,
},
() => buildStaticStandalone(options)
)
).pipe(catchError((error: any) => throwError(errorSummary(error))));
);
} catch (error) {
throw new Error(errorSummary(error));
}
}
Loading

0 comments on commit cca91fc

Please sign in to comment.