From 17bd9211abda1782089360c089f692cd255c0ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20Ro=CC=88der?= Date: Wed, 5 Oct 2022 22:44:31 +0200 Subject: [PATCH 1/2] refactor(angular): drop support for angular < 13 According to the Angular LTS plan, Angular 12 support ends in Nov 2022. A lot of code exists to support Angular < 13 which increases the maintenance effort and decreases the contribution DX of framework/angular. BREAKING CHANGE: Dropped support for Angular 12 --- .../storyshots/storyshots-core/package.json | 4 +- code/frameworks/angular/package.json | 22 +- code/frameworks/angular/src/preset.ts | 1 - .../create-fork-ts-checker-plugin.test.ts | 45 ---- .../src/server/__tests__/ts_config.test.ts | 42 ---- .../server/angular-cli-webpack-12.2.x.d.ts | 7 - .../src/server/angular-cli-webpack-12.2.x.js | 85 ------- .../src/server/angular-cli-webpack-older.ts | 148 ------------ .../server/angular-devkit-build-webpack.ts | 215 ------------------ .../server/create-fork-ts-checker-plugin.ts | 17 -- .../server/framework-preset-angular-cli.ts | 20 -- .../src/server/framework-preset-angular.ts | 84 ------- .../src/server/ngx-template-loader/index.ts | 48 ---- .../angular/src/server/ts_config.ts | 26 --- code/yarn.lock | 26 +-- 15 files changed, 26 insertions(+), 764 deletions(-) delete mode 100644 code/frameworks/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts delete mode 100644 code/frameworks/angular/src/server/__tests__/ts_config.test.ts delete mode 100644 code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.d.ts delete mode 100644 code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.js delete mode 100644 code/frameworks/angular/src/server/angular-cli-webpack-older.ts delete mode 100644 code/frameworks/angular/src/server/angular-devkit-build-webpack.ts delete mode 100644 code/frameworks/angular/src/server/create-fork-ts-checker-plugin.ts delete mode 100644 code/frameworks/angular/src/server/framework-preset-angular.ts delete mode 100644 code/frameworks/angular/src/server/ngx-template-loader/index.ts delete mode 100644 code/frameworks/angular/src/server/ts_config.ts diff --git a/code/addons/storyshots/storyshots-core/package.json b/code/addons/storyshots/storyshots-core/package.json index e4bd83fafd1d..0bf1ed3ecc9c 100644 --- a/code/addons/storyshots/storyshots-core/package.json +++ b/code/addons/storyshots/storyshots-core/package.json @@ -77,8 +77,8 @@ "vue-jest": "^5.0.0-alpha.8" }, "peerDependencies": { - "@angular/core": ">=6.0.0", - "@angular/platform-browser-dynamic": ">=6.0.0", + "@angular/core": ">=13.0.0", + "@angular/platform-browser-dynamic": ">=13.0.0", "@storybook/angular": "*", "@storybook/react": "*", "@storybook/vue": "*", diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index 69bba1ff5255..34f04c2d7309 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -97,17 +97,17 @@ "webpack": "5" }, "peerDependencies": { - "@angular-devkit/architect": ">=0.8.9", - "@angular-devkit/build-angular": ">=0.8.9 || >= 12.0.0", - "@angular-devkit/core": "^0.6.1 || >=7.0.0", - "@angular/cli": ">=6.0.0", - "@angular/common": ">=6.0.0", - "@angular/compiler": ">=6.0.0", - "@angular/compiler-cli": ">=6.0.0", - "@angular/core": ">=6.0.0", - "@angular/forms": ">=6.0.0", - "@angular/platform-browser": ">=6.0.0", - "@angular/platform-browser-dynamic": ">=6.0.0", + "@angular-devkit/architect": ">=0.1300.0", + "@angular-devkit/build-angular": ">=13.0.0", + "@angular-devkit/core": ">=13.0.0", + "@angular/cli": ">=13.0.0", + "@angular/common": ">=13.0.0", + "@angular/compiler": ">=13.0.0", + "@angular/compiler-cli": ">=13.0.0", + "@angular/core": ">=13.0.0", + "@angular/forms": ">=13.0.0", + "@angular/platform-browser": ">=13.0.0", + "@angular/platform-browser-dynamic": ">=13.0.0", "@babel/core": "*", "@nrwl/workspace": "14.6.1", "rxjs": "^6.0.0 || ^7.4.0", diff --git a/code/frameworks/angular/src/preset.ts b/code/frameworks/angular/src/preset.ts index cac9e5702f9b..bd8cfb7c8fe0 100644 --- a/code/frameworks/angular/src/preset.ts +++ b/code/frameworks/angular/src/preset.ts @@ -3,7 +3,6 @@ import type { PresetProperty } from '@storybook/core-common'; import { StorybookConfig } from './types'; export const addons: PresetProperty<'addons', StorybookConfig> = [ - require.resolve('./server/framework-preset-angular'), require.resolve('./server/framework-preset-angular-cli'), require.resolve('./server/framework-preset-angular-ivy'), require.resolve('./server/framework-preset-angular-docs'), diff --git a/code/frameworks/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts b/code/frameworks/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts deleted file mode 100644 index e77d4746097a..000000000000 --- a/code/frameworks/angular/src/server/__tests__/create-fork-ts-checker-plugin.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -// import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; -// import getTsLoaderOptions from '../ts_config'; -// import createForkTsCheckerInstance from '../create-fork-ts-checker-plugin'; - -// // eslint-disable-next-line global-require, jest/no-mocks-import -// jest.mock('fs', () => require('../../../../../__mocks__/fs')); -// // jest.mock('path', () => ({ -// // resolve: () => 'tsconfig.json', -// // posix: { dirname: jest.fn(() => '') }, -// // extname: jest.fn(() => ''), -// // })); -// jest.mock('@storybook/node-logger'); - -// const setupFiles = (files: any) => { -// // eslint-disable-next-line no-underscore-dangle, global-require -// require('fs').__setMockFiles(files); -// }; - -// describe('create-fork-ts-checker-plugin.test', () => { -// it('should create a ForkTsCheckerWebpackPlugin instance', () => { -// setupFiles({ 'tsconfig.json': '{}' }); - -// const tsLoaderOptions = getTsLoaderOptions('.foo'); - -// // todo resolve any -// const instance: any = createForkTsCheckerInstance(tsLoaderOptions); - -// expect(instance).toBeInstanceOf(ForkTsCheckerWebpackPlugin); -// expect(instance.tsconfig).toEqual(tsLoaderOptions.configFile); -// }); - -// it('should create a ForkTsCheckerWebpackPlugin instance without passing options', () => { -// // add proper typing -// const instance = createForkTsCheckerInstance({} as any); -// expect(instance).toBeInstanceOf(ForkTsCheckerWebpackPlugin); -// }); -// }); - -it('work-around', () => { - expect(true).toBe(true); -}); - -// Make it work with --isolatedModules, we need a dummy export -/* eslint-disable jest/no-export */ -export default {}; diff --git a/code/frameworks/angular/src/server/__tests__/ts_config.test.ts b/code/frameworks/angular/src/server/__tests__/ts_config.test.ts deleted file mode 100644 index 1b84a549f06d..000000000000 --- a/code/frameworks/angular/src/server/__tests__/ts_config.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import getTsLoaderOptions from '../ts_config'; - -// eslint-disable-next-line global-require, jest/no-mocks-import -jest.mock('fs', () => require('../../../../../__mocks__/fs')); -jest.mock('path', () => ({ - resolve: () => 'tsconfig.json', -})); -jest.mock('@storybook/node-logger'); - -const setupFiles = (files: any) => { - // eslint-disable-next-line no-underscore-dangle, global-require - require('fs').__setMockFiles(files); -}; - -describe('ts_config', () => { - it('should return the config with the path to the tsconfig.json', () => { - setupFiles({ 'tsconfig.json': '{}' }); - - const config = getTsLoaderOptions('.foo'); - - expect(config).toEqual({ - transpileOnly: true, - compilerOptions: { - emitDecoratorMetadata: true, - }, - configFile: 'tsconfig.json', - }); - }); - - it('should return object with transpileOnly: true when there is no tsconfig.json', () => { - setupFiles({}); - - const config = getTsLoaderOptions('.foo'); - - expect(config).toEqual({ - transpileOnly: true, - compilerOptions: { - emitDecoratorMetadata: true, - }, - }); - }); -}); diff --git a/code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.d.ts b/code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.d.ts deleted file mode 100644 index b2f79e4d963a..000000000000 --- a/code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { JsonObject } from '@angular-devkit/core'; -import { BuilderContext } from '@angular-devkit/architect'; - -export declare function getWebpackConfig( - baseConfig: any, - options: { builderOptions: JsonObject; builderContext: BuilderContext } -): any; diff --git a/code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.js b/code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.js deleted file mode 100644 index bb3f12011b8a..000000000000 --- a/code/frameworks/angular/src/server/angular-cli-webpack-12.2.x.js +++ /dev/null @@ -1,85 +0,0 @@ -// Private angular devkit stuff -const { - generateI18nBrowserWebpackConfigFromContext, -} = require('@angular-devkit/build-angular/src/utils/webpack-browser-config'); -const { - getCommonConfig, - getStylesConfig, - getTypeScriptConfig, -} = 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 12.2.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), getTypeScriptConfig(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/code/frameworks/angular/src/server/angular-cli-webpack-older.ts b/code/frameworks/angular/src/server/angular-cli-webpack-older.ts deleted file mode 100644 index 22519c2e4d4e..000000000000 --- a/code/frameworks/angular/src/server/angular-cli-webpack-older.ts +++ /dev/null @@ -1,148 +0,0 @@ -import webpack, { Configuration } from 'webpack'; -import { logger } from '@storybook/node-logger'; -import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'; -import { targetFromTargetString, Target } from '@angular-devkit/architect'; - -import { workspaces } from '@angular-devkit/core'; -import { - findAngularProjectTarget, - getDefaultProjectName, - readAngularWorkspaceConfig, -} from './angular-read-workspace'; -import { - AngularCliWebpackConfig, - extractAngularCliWebpackConfig, -} from './angular-devkit-build-webpack'; -import { filterOutStylingRules } from './utils/filter-out-styling-rules'; -import type { PresetOptions } from './preset-options'; - -/** - * Old way currently support version lower than 12.2.x - */ -export async function getWebpackConfig( - baseConfig: webpack.Configuration, - options: PresetOptions -): Promise { - const dirToSearch = process.cwd(); - - // Read angular workspace - let workspaceConfig; - try { - workspaceConfig = await readAngularWorkspaceConfig(dirToSearch); - } catch (error) { - logger.error( - `=> Could not find angular workspace config (angular.json) on this path "${dirToSearch}"` - ); - logger.info(`=> Fail to load angular-cli config. Using base config`); - return baseConfig; - } - - // Find angular project target - let project: workspaces.ProjectDefinition; - let target: workspaces.TargetDefinition; - let confName: string; - try { - // Default behavior when `angularBrowserTarget` are not explicitly defined to null - if (options.angularBrowserTarget !== null) { - const browserTarget = options.angularBrowserTarget - ? targetFromTargetString(options.angularBrowserTarget) - : ({ - configuration: undefined, - project: getDefaultProjectName(workspaceConfig), - target: 'build', - } as Target); - - const fondProject = findAngularProjectTarget( - workspaceConfig, - browserTarget.project, - browserTarget.target - ); - project = fondProject.project; - target = fondProject.target; - confName = browserTarget.configuration; - - logger.info( - `=> Using angular project "${browserTarget.project}:${browserTarget.target}${ - confName ? `:${confName}` : '' - }" for configuring Storybook` - ); - } - // Start storybook when only tsConfig is provided. - if (options.angularBrowserTarget === null && options.tsConfig) { - logger.info(`=> Using default angular project with "tsConfig:${options.tsConfig}"`); - - project = { root: '', extensions: {}, targets: undefined }; - target = { builder: '', options: { tsConfig: options.tsConfig } }; - } - } catch (error) { - logger.error(`=> Could not find angular project: ${error.message}`); - logger.info(`=> Fail to load angular-cli config. Using base config`); - return baseConfig; - } - - // Use angular-cli to get some webpack config - let angularCliWebpackConfig: AngularCliWebpackConfig; - try { - angularCliWebpackConfig = await extractAngularCliWebpackConfig( - dirToSearch, - project, - target, - confName - ); - logger.info(`=> Using angular-cli webpack config`); - } catch (error) { - logger.error(`=> Could not get angular cli webpack config`); - throw error; - } - - return mergeAngularCliWebpackConfig(angularCliWebpackConfig, baseConfig); -} - -function mergeAngularCliWebpackConfig( - { cliCommonWebpackConfig, cliStyleWebpackConfig, tsConfigPath }: AngularCliWebpackConfig, - baseConfig: webpack.Configuration -) { - // 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); - - // styleWebpackConfig.entry adds global style files to the webpack context - const entry = [ - ...(baseConfig.entry as string[]), - ...Object.values(cliStyleWebpackConfig.entry).reduce((acc, item) => acc.concat(item), []), - ]; - - const module = { - ...baseConfig.module, - rules: [...cliStyleWebpackConfig.module.rules, ...rulesExcludingStyles], - }; - - // We use cliCommonConfig plugins to serve static assets files. - const plugins = [ - ...cliStyleWebpackConfig.plugins, - ...cliCommonWebpackConfig.plugins, - ...baseConfig.plugins, - ]; - - const resolve = { - ...baseConfig.resolve, - modules: Array.from( - new Set([...baseConfig.resolve.modules, ...cliCommonWebpackConfig.resolve.modules]) - ), - plugins: [ - new TsconfigPathsPlugin({ - configFile: tsConfigPath, - mainFields: ['browser', 'module', 'main'], - }), - ], - }; - - return { - ...baseConfig, - entry, - module, - plugins, - resolve, - resolveLoader: cliCommonWebpackConfig.resolveLoader, - }; -} diff --git a/code/frameworks/angular/src/server/angular-devkit-build-webpack.ts b/code/frameworks/angular/src/server/angular-devkit-build-webpack.ts deleted file mode 100644 index 6189812669bb..000000000000 --- a/code/frameworks/angular/src/server/angular-devkit-build-webpack.ts +++ /dev/null @@ -1,215 +0,0 @@ -/** - * This file is to be watched ! - * The code must be compatible from @angular-devkit version 6.1.0 to the latest supported - * - * It uses code block of angular cli to extract parts of webpack configuration - */ - -import path from 'path'; -import webpack, { Configuration } from 'webpack'; -import { normalize, resolve, workspaces, getSystemPath } from '@angular-devkit/core'; -import { createConsoleLogger } from '@angular-devkit/core/node'; - -// Only type, so not dependent on the client version -import { - WebpackConfigOptions, - BuildOptions, -} from '@angular-devkit/build-angular/src/utils/build-options'; - -import { moduleIsAvailable } from './utils/module-is-available'; -import { normalizeAssetPatterns } from './utils/normalize-asset-patterns'; -import { normalizeOptimization } from './utils/normalize-optimization'; - -const importAngularCliWebpackConfigGenerator = (): { - getCommonConfig: (config: unknown) => webpack.Configuration; - getStylesConfig: (config: unknown) => webpack.Configuration; -} => { - let angularWebpackConfig; - - // First we look for webpack config according to directory structure of Angular 11 - if (moduleIsAvailable('@angular-devkit/build-angular/src/webpack/configs')) { - // eslint-disable-next-line global-require - angularWebpackConfig = require('@angular-devkit/build-angular/src/webpack/configs'); - } - // We fallback on directory structure of Angular 10 (and below) - else if ( - moduleIsAvailable('@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs') - ) { - // eslint-disable-next-line global-require - angularWebpackConfig = require('@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs'); - } else { - throw new Error('Webpack config not found in "@angular-devkit/build-angular"'); - } - - return { - getCommonConfig: angularWebpackConfig.getCommonConfig, - getStylesConfig: angularWebpackConfig.getStylesConfig, - }; -}; - -const importAngularCliReadTsconfigUtil = - (): typeof import('@angular-devkit/build-angular/src/utils/read-tsconfig') => { - // First we look for webpack config according to directory structure of Angular 11 - if (moduleIsAvailable('@angular-devkit/build-angular/src/utils/read-tsconfig')) { - // eslint-disable-next-line global-require - return require('@angular-devkit/build-angular/src/utils/read-tsconfig'); - } - // We fallback on directory structure of Angular 10 (and below) - if ( - moduleIsAvailable( - '@angular-devkit/build-angular/src/angular-cli-files/utilities/read-tsconfig' - ) - ) { - // eslint-disable-next-line global-require - return require('@angular-devkit/build-angular/src/angular-cli-files/utilities/read-tsconfig'); - } - throw new Error('ReadTsconfig not found in "@angular-devkit/build-angular"'); - }; - -const buildWebpackConfigOptions = async ( - dirToSearch: string, - project: workspaces.ProjectDefinition, - target: workspaces.TargetDefinition, - confName?: string -): Promise => { - let conf: Record = {}; - - if (confName) { - if (!target.configurations) { - throw new Error('Missing "configurations" section in project target'); - } - if (!target.configurations[confName]) { - throw new Error(`Missing required configuration in project target. Check "${confName}"`); - } - conf = target.configurations[confName]; - } - - const projectBuildOptions = { ...target.options, ...conf }; - - const requiredOptions = ['tsConfig']; - if (!requiredOptions.every((key) => !!projectBuildOptions[key])) { - throw new Error( - `Missing required options in project target. Check "${requiredOptions.join(', ')}"` - ); - } - - const workspaceRootNormalized = normalize(dirToSearch); - const projectRootNormalized = resolve( - workspaceRootNormalized, - normalize((project.root as string) || '') - ); - const sourceRootNormalized = project.sourceRoot - ? resolve(workspaceRootNormalized, normalize(project.sourceRoot)) - : undefined; - - const tsConfigPath = path.resolve( - getSystemPath(workspaceRootNormalized), - projectBuildOptions.tsConfig as string - ); - const tsConfig = await importAngularCliReadTsconfigUtil().readTsconfig(tsConfigPath); - - const ts = await import('typescript'); - const scriptTarget = tsConfig.options.target || ts.ScriptTarget.ES5; - - const buildOptions: BuildOptions = { - // Default options - budgets: [], - fileReplacements: [], - main: '', - outputPath: 'dist/storybook-angular', - scripts: [], - sourceMap: {}, - styles: [], - // Deleted in angular 12. Keep for compatibility with versions lower than angular 12 - lazyModules: [], - - // Project Options - ...projectBuildOptions, - assets: normalizeAssetPatterns( - (projectBuildOptions.assets as any[]) || [], - workspaceRootNormalized, - projectRootNormalized, - sourceRootNormalized - ), - optimization: normalizeOptimization(projectBuildOptions.optimization as any), - - // Forced options - statsJson: false, - - // Deleted in angular 12. Keep for compatibility with versions lower than angular 12 - // @ts-expect-error (Converted from ts-ignore) - forkTypeChecker: false, - }; - - return { - projectName: 'this-is-just-a-fake-name-for-getting-rid-of-the-error', - root: getSystemPath(workspaceRootNormalized), - // The dependency of `@angular-devkit/build-angular` to `@angular-devkit/core` is not exactly the same version as the one for storybook (node modules of node modules ^^) - logger: createConsoleLogger() as unknown as WebpackConfigOptions['logger'], - projectRoot: getSystemPath(projectRootNormalized), - sourceRoot: sourceRootNormalized ? getSystemPath(sourceRootNormalized) : undefined, - buildOptions, - tsConfig, - tsConfigPath, - scriptTarget, - }; -}; - -export type AngularCliWebpackConfig = { - cliCommonWebpackConfig: { - plugins: Configuration['plugins']; - resolve: { - modules: string[]; - }; - resolveLoader: Configuration['resolveLoader']; - }; - cliStyleWebpackConfig: { - entry: Configuration['entry']; - module: { - rules: Configuration['module']['rules']; - }; - plugins: Configuration['plugins']; - }; - tsConfigPath: string; -}; - -/** - * Uses angular cli to extract webpack configuration. - * The `AngularCliWebpackConfig` type lists the parts used by storybook - */ -export async function extractAngularCliWebpackConfig( - dirToSearch: string, - project: workspaces.ProjectDefinition, - target: workspaces.TargetDefinition, - confName?: string -): Promise { - const { getCommonConfig, getStylesConfig } = importAngularCliWebpackConfigGenerator(); - - const webpackConfigOptions = await buildWebpackConfigOptions( - dirToSearch, - project, - target, - confName - ); - - const cliCommonConfig = getCommonConfig(webpackConfigOptions); - const cliStyleConfig = getStylesConfig(webpackConfigOptions); - - return { - cliCommonWebpackConfig: { - plugins: cliCommonConfig.plugins, - resolve: { - modules: cliCommonConfig.resolve?.modules, - }, - resolveLoader: cliCommonConfig.resolveLoader, - }, - cliStyleWebpackConfig: { - entry: cliStyleConfig.entry, - module: { - rules: [...cliStyleConfig.module.rules], - }, - plugins: cliStyleConfig.plugins, - }, - tsConfigPath: webpackConfigOptions.tsConfigPath, - }; -} diff --git a/code/frameworks/angular/src/server/create-fork-ts-checker-plugin.ts b/code/frameworks/angular/src/server/create-fork-ts-checker-plugin.ts deleted file mode 100644 index 807ce15ec1cf..000000000000 --- a/code/frameworks/angular/src/server/create-fork-ts-checker-plugin.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* eslint-disable func-names */ -import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; -import { logger } from '@storybook/node-logger'; - -import { Options } from 'ts-loader'; - -export default function (tsLoaderOptions: Partial) { - if (tsLoaderOptions && tsLoaderOptions.configFile) { - return new ForkTsCheckerWebpackPlugin({ - typescript: { configFile: tsLoaderOptions.configFile }, - async: true, - }); - } - - logger.info('=> Using default options for ForkTsCheckerWebpackPlugin'); - return new ForkTsCheckerWebpackPlugin(); -} diff --git a/code/frameworks/angular/src/server/framework-preset-angular-cli.ts b/code/frameworks/angular/src/server/framework-preset-angular-cli.ts index 584b86074820..b997c59047cb 100644 --- a/code/frameworks/angular/src/server/framework-preset-angular-cli.ts +++ b/code/frameworks/angular/src/server/framework-preset-angular-cli.ts @@ -8,9 +8,7 @@ import { dedent } from 'ts-dedent'; 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 getWebpackConfigOlder } from './angular-cli-webpack-older'; import type { PresetOptions } from './preset-options'; import { getDefaultProjectName, @@ -55,24 +53,6 @@ export async function webpackFinal(baseConfig: webpack.Configuration, options: P }); }, }, - { - info: '=> Loading angular-cli config for angular 12.2.x', - condition: semver.satisfies(angularCliVersion, '12.2.x') && options.angularBuilderContext, - getWebpackConfig: async (_baseConfig, _options) => { - const builderContext = getBuilderContext(_options); - const builderOptions = await getBuilderOptions(_options, builderContext); - - return getWebpackConfig12_2_x(_baseConfig, { - builderOptions, - builderContext, - }); - }, - }, - { - info: '=> Loading angular-cli config for angular lower than 12.2.0', - condition: true, - getWebpackConfig: getWebpackConfigOlder, - }, ]; const webpackGetter = webpackGetterByVersions.find((wg) => wg.condition); diff --git a/code/frameworks/angular/src/server/framework-preset-angular.ts b/code/frameworks/angular/src/server/framework-preset-angular.ts deleted file mode 100644 index 32a20a05b712..000000000000 --- a/code/frameworks/angular/src/server/framework-preset-angular.ts +++ /dev/null @@ -1,84 +0,0 @@ -import path from 'path'; -import semver from '@storybook/semver'; -import { ContextReplacementPlugin, Configuration } from 'webpack'; -import autoprefixer from 'autoprefixer'; -import getTsLoaderOptions from './ts_config'; -import createForkTsCheckerInstance from './create-fork-ts-checker-plugin'; - -export async function webpack( - config: Configuration, - { configDir, angularBuilderContext }: { configDir: string; angularBuilderContext: any } -): Promise { - try { - // Disable all this webpack stuff if we use angular-cli >= 12 - // Angular cli is in charge of doing all the necessary for angular. If there is any additional configuration to add, it must be done in the preset angular-cli versioned. - const angularCliVersion = await import('@angular/cli').then((m) => - semver.coerce(m.VERSION.full) - ); - if ( - (semver.satisfies(angularCliVersion, '12.2.x') && angularBuilderContext) || - semver.satisfies(angularCliVersion, '>=13.0.0') - ) { - return config; - } - } catch (error) { - // do nothing, continue - } - - const tsLoaderOptions = getTsLoaderOptions(configDir); - return { - ...config, - module: { - ...config.module, - rules: [ - ...config.module.rules, - { - test: /\.tsx?$/, - use: [ - { - loader: require.resolve('ts-loader'), - options: tsLoaderOptions, - }, - { loader: path.resolve(__dirname, 'ngx-template-loader') }, - ], - }, - { - test: /[/\\]@angular[/\\]core[/\\].+\.js$/, - parser: { system: false }, - }, - { - test: /\.html$/, - loader: require.resolve('raw-loader'), - exclude: /\.async\.html$/, - }, - { - test: /\.s(c|a)ss$/, - use: [ - { loader: require.resolve('raw-loader') }, - { - loader: require.resolve('postcss-loader'), - options: { - postcssOptions: { - plugins: [autoprefixer()], - }, - }, - }, - { loader: require.resolve('sass-loader') }, - ], - }, - ], - }, - resolve: { - ...config.resolve, - }, - plugins: [ - ...config.plugins, - // See https://github.com/angular/angular/issues/11580#issuecomment-401127742 - new ContextReplacementPlugin( - /@angular(\\|\/)core(\\|\/)(fesm5|bundles)/, - path.resolve(__dirname, '..') - ), - createForkTsCheckerInstance(tsLoaderOptions) as any as Configuration['plugins'][0], - ], - }; -} diff --git a/code/frameworks/angular/src/server/ngx-template-loader/index.ts b/code/frameworks/angular/src/server/ngx-template-loader/index.ts deleted file mode 100644 index 10ff4359f567..000000000000 --- a/code/frameworks/angular/src/server/ngx-template-loader/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * By the time this file was added the repository for angular2-template-loader received no updates in 3 years - * This is just a copy of https://github.com/TheLarkInn/angular2-template-loader/blob/master/index.js in order - * to fix a bug that prevents Storybook from updating raw-loader > ^1.0.0 - * - * As suggested in https://github.com/storybookjs/storybook/issues/7877#issuecomment-536556755 this code was - * modified to be compatible with newer versions of raw-loader as well as backwards compatible with raw-loader ^1.0.0 - */ - -// using: regex, capture groups, and capture group variables. -const templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*([,}]))/gm; -const stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g; -const stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g; - -const replaceStringsWithRequires = (string: string) => { - return string.replace(stringRegex, (match, quote, url) => { - let newUrl = url; - if (url.charAt(0) !== '.') { - newUrl = `./${url}`; - } - const requireString = `(require('${newUrl}').default || require('${newUrl}'))`; - - // without the length check an empty style file will throw - // "Expected 'styles' to be an array of strings" - return `${requireString}.length ? ${requireString} : ''`; - }); -}; - -export default function (source: string) { - const styleProperty = 'styles'; - const templateProperty = 'template'; - - return source - .replace(templateUrlRegex, (_, templateUrlString: string) => { - // replace: templateUrl: './path/to/template.html' - // with: template: require('./path/to/template.html') - // or: templateUrl: require('./path/to/template.html') - // if `keepUrl` query parameter is set to true. - return `${templateProperty}:${replaceStringsWithRequires(templateUrlString)}`; - }) - .replace(stylesRegex, (_, styleUrlsString: string) => { - // replace: stylesUrl: ['./foo.css', "./baz.css", "./index.component.css"] - // with: styles: [require('./foo.css'), require("./baz.css"), require("./index.component.css")] - // or: styleUrls: [require('./foo.css'), require("./baz.css"), require("./index.component.css")] - // if `keepUrl` query parameter is set to true. - return `${styleProperty}:${replaceStringsWithRequires(styleUrlsString)}`; - }); -} diff --git a/code/frameworks/angular/src/server/ts_config.ts b/code/frameworks/angular/src/server/ts_config.ts deleted file mode 100644 index 196c42fd9387..000000000000 --- a/code/frameworks/angular/src/server/ts_config.ts +++ /dev/null @@ -1,26 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { logger } from '@storybook/node-logger'; -import { Options } from 'ts-loader'; - -function resolveTsConfig(tsConfigPath: string): string | undefined { - if (fs.existsSync(tsConfigPath)) { - logger.info('=> Found custom tsconfig.json'); - return tsConfigPath; - } - return undefined; -} - -export default function (configDir: string) { - const tsLoaderOptions: Partial = { - transpileOnly: true, - compilerOptions: { - emitDecoratorMetadata: true, - }, - }; - - const configFilePath = resolveTsConfig(path.resolve(configDir, 'tsconfig.json')); - if (configFilePath) tsLoaderOptions.configFile = configFilePath; - - return tsLoaderOptions; -} diff --git a/code/yarn.lock b/code/yarn.lock index 2d03badfa75f..c69f79916ee1 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6876,8 +6876,8 @@ __metadata: ts-dedent: ^2.0.0 vue-jest: ^5.0.0-alpha.8 peerDependencies: - "@angular/core": ">=6.0.0" - "@angular/platform-browser-dynamic": ">=6.0.0" + "@angular/core": ">=13.0.0" + "@angular/platform-browser-dynamic": ">=13.0.0" "@storybook/angular": "*" "@storybook/react": "*" "@storybook/vue": "*" @@ -7119,17 +7119,17 @@ __metadata: util-deprecate: ^1.0.2 webpack: 5 peerDependencies: - "@angular-devkit/architect": ">=0.8.9" - "@angular-devkit/build-angular": ">=0.8.9 || >= 12.0.0" - "@angular-devkit/core": ^0.6.1 || >=7.0.0 - "@angular/cli": ">=6.0.0" - "@angular/common": ">=6.0.0" - "@angular/compiler": ">=6.0.0" - "@angular/compiler-cli": ">=6.0.0" - "@angular/core": ">=6.0.0" - "@angular/forms": ">=6.0.0" - "@angular/platform-browser": ">=6.0.0" - "@angular/platform-browser-dynamic": ">=6.0.0" + "@angular-devkit/architect": ">=0.1300.0" + "@angular-devkit/build-angular": ">=13.0.0" + "@angular-devkit/core": ">=13.0.0" + "@angular/cli": ">=13.0.0" + "@angular/common": ">=13.0.0" + "@angular/compiler": ">=13.0.0" + "@angular/compiler-cli": ">=13.0.0" + "@angular/core": ">=13.0.0" + "@angular/forms": ">=13.0.0" + "@angular/platform-browser": ">=13.0.0" + "@angular/platform-browser-dynamic": ">=13.0.0" "@babel/core": "*" "@nrwl/workspace": 14.6.1 rxjs: ^6.0.0 || ^7.4.0 From 3fc5a297814c6bd7cb5d967c4dd478ffbe0509f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20Ro=CC=88der?= Date: Thu, 6 Oct 2022 10:03:07 +0200 Subject: [PATCH 2/2] docs(migration): add dropped angular 12 support note --- MIGRATION.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index 79150ff185a3..41c3d02c4272 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -23,6 +23,7 @@ - [Removed STORYBOOK_REACT_CLASSES global](#removed-storybook_react_classes-global) - [Icons API changed](#icons-api-changed) - ['config' preset entry replaced with 'previewAnnotations'](#config-preset-entry-replaced-with-previewannotations) + - [Dropped support for Angular 12 and below](#dropped-support-for-angular-12-and-below) - [Docs Changes](#docs-changes) - [Standalone docs files](#standalone-docs-files) - [Referencing stories in docs files](#referencing-stories-in-docs-files) @@ -555,6 +556,13 @@ The preset field `'config'` has been replaced with `'previewAnnotations'`. `'con Additionally, the internal field `'previewEntries'` has been removed. If you need a preview entry, just use a `'previewAnnotations'` file and don't export anything. +#### Dropped support for Angular 12 and below + +Official [Angular 12 LTS support ends Nov 2022](https://angular.io/guide/releases#actively-supported-versions). With that, Storybook also drops its support +for Angular 12 and below. + +In order to use Storybook 7.0, you need to upgrade to at least Angular 13. + #### Vue2 DOM structure changed In 6.x, `@storybook/vue` would replace the "root" element (formerly `#root`, now `#storybook-root`) with a new node that contains the rendered children. This was problematic because it broke the `play` function, which often starts with `within(canvasElement)` and the old `canvasElement` would get replaced out from under the play function.