diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aae3fe803c8..b6a82bf083b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ### Bug Fixes -* Core: Support custom PREVIEW URL for block story iframe ([#16773](https://github.com/storybookjs/storybook/pull/16773)) +- Core: Support custom PREVIEW URL for block story iframe ([#16773](https://github.com/storybookjs/storybook/pull/16773)) +- Angular: Support Angular 13.1 ([#16978](https://github.com/storybookjs/storybook/pull/16978)) ## 6.5.0-alpha.2 (December 9, 2021) diff --git a/app/angular/src/server/angular-cli-webpack-13.1.x.js b/app/angular/src/server/angular-cli-webpack-13.1.x.js new file mode 100644 index 000000000000..b7b837eccaad --- /dev/null +++ b/app/angular/src/server/angular-cli-webpack-13.1.x.js @@ -0,0 +1,84 @@ +// Private angular devkit stuff +const { + generateI18nBrowserWebpackConfigFromContext, +} = require('@angular-devkit/build-angular/src/utils/webpack-browser-config'); +const { + getCommonConfig, + getStylesConfig, +} = require('@angular-devkit/build-angular/src/webpack/configs'); +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); + +const { filterOutStylingRules } = require('./utils/filter-out-styling-rules'); + +/** + * Extract webpack config from angular-cli 13.1.x + * ⚠️ This file is in JavaScript to not use TypeScript. Because current storybook TypeScript version is not compatible with Angular CLI. + * FIXME: Try another way with TypeScript on future storybook version (7 maybe 🤞) + * + * @param {*} baseConfig Previous webpack config from storybook + * @param {*} options { builderOptions, builderContext } + */ +exports.getWebpackConfig = async (baseConfig, { builderOptions, builderContext }) => { + /** + * Get angular-cli Webpack config + */ + const { config: cliConfig } = await generateI18nBrowserWebpackConfigFromContext( + { + // Default options + index: 'noop-index', + main: 'noop-main', + outputPath: 'noop-out', + + // Options provided by user + ...builderOptions, + + // Fixed options + optimization: false, + namedChunks: false, + progress: false, + buildOptimizer: false, + aot: false, + }, + builderContext, + (wco) => [getCommonConfig(wco), getStylesConfig(wco)] + ); + + /** + * Merge baseConfig Webpack with angular-cli Webpack + */ + const entry = [ + ...baseConfig.entry, + ...(cliConfig.entry.styles ?? []), + ...(cliConfig.entry.polyfills ?? []), + ]; + + // Don't use storybooks styling rules because we have to use rules created by @angular-devkit/build-angular + // because @angular-devkit/build-angular created rules have include/exclude for global style files. + const rulesExcludingStyles = filterOutStylingRules(baseConfig); + const module = { + ...baseConfig.module, + rules: [...cliConfig.module.rules, ...rulesExcludingStyles], + }; + + const plugins = [...(cliConfig.plugins ?? []), ...baseConfig.plugins]; + + const resolve = { + ...baseConfig.resolve, + modules: Array.from(new Set([...baseConfig.resolve.modules, ...cliConfig.resolve.modules])), + plugins: [ + new TsconfigPathsPlugin({ + configFile: builderOptions.tsConfig, + mainFields: ['browser', 'module', 'main'], + }), + ], + }; + + return { + ...baseConfig, + entry, + module, + plugins, + resolve, + resolveLoader: cliConfig.resolveLoader, + }; +}; diff --git a/app/angular/src/server/framework-preset-angular-cli.ts b/app/angular/src/server/framework-preset-angular-cli.ts index 5f5807f6f20c..bf2cf9fc4256 100644 --- a/app/angular/src/server/framework-preset-angular-cli.ts +++ b/app/angular/src/server/framework-preset-angular-cli.ts @@ -8,6 +8,7 @@ import { logging, JsonObject } from '@angular-devkit/core'; import { moduleIsAvailable } from './utils/module-is-available'; import { getWebpackConfig as getWebpackConfig12_2_x } from './angular-cli-webpack-12.2.x'; import { getWebpackConfig as getWebpackConfig13_x_x } from './angular-cli-webpack-13.x.x'; +import { getWebpackConfig as getWebpackConfig13_1_x } from './angular-cli-webpack-13.1.x'; import { getWebpackConfig as getWebpackConfigOlder } from './angular-cli-webpack-older'; import { PresetOptions } from './options'; import { @@ -35,6 +36,20 @@ export async function webpackFinal(baseConfig: webpack.Configuration, options: P options: PresetOptions ): Promise | webpack.Configuration; }[] = [ + { + info: '=> Loading angular-cli config for angular >= 13.1.0', + condition: semver.satisfies(angularCliVersion, '>=13.1.0'), + getWebpackConfig: async (_baseConfig, _options) => { + const builderContext = getBuilderContext(_options); + const builderOptions = await getBuilderOptions(_options, builderContext); + const legacyDefaultOptions = await getLegacyDefaultBuildOptions(_options); + + return getWebpackConfig13_1_x(_baseConfig, { + builderOptions: { ...builderOptions, ...legacyDefaultOptions }, + builderContext, + }); + }, + }, { info: '=> Loading angular-cli config for angular >= 13.0.0', condition: semver.satisfies(angularCliVersion, '>=13.0.0'), @@ -172,7 +187,9 @@ async function getLegacyDefaultBuildOptions(options: PresetOptions) { browserTarget.target ); - logger.info(`=> Using angular project "${browserTarget.project}:${browserTarget.target}" for configuring Storybook`); + logger.info( + `=> Using angular project "${browserTarget.project}:${browserTarget.target}" for configuring Storybook` + ); return { ...target.options }; } catch (error) { logger.error(`=> Could not find angular project: ${error.message}`);