Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Add Babel mode v7 #15928

Merged
merged 14 commits into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<h1>Migration</h1>

- [From version 6.3.x to 6.4.0](#from-version-63x-to-640)
- [Babel mode v7](#babel-mode-v7)
- [From version 6.2.x to 6.3.0](#from-version-62x-to-630)
- [Webpack 5 manager build](#webpack-5-manager-build)
- [Angular 12 upgrade](#angular-12-upgrade)
Expand Down Expand Up @@ -162,6 +164,39 @@
- [Packages renaming](#packages-renaming)
- [Deprecated embedded addons](#deprecated-embedded-addons)

## From version 6.3.x to 6.4.0

### Babel mode v7

SB6.4 introduces an opt-in feature flag, `features.babelModeV7`, that reworks the way Babel is configured in Storybook to make it more consistent with the Babel is configured in your app. This breaking change will become the default in SB 7.0, but we encourage you to migrate today.

> NOTE: CRA apps using `@storybook/preset-create-react-app` use CRA's handling, so the new flag has no effect on CRA apps.

In SB6.x and earlier, Storybook provided its own default configuration and inconsistently handled configurations from the user's babelrc file. This resulted in a final configuration that differs from your application's configuration AND is difficult to debug.

In `babelModeV7`, Storybook no longer provides its own default configuration and is primarily configured via babelrc file, with small, incremental updates from Storybook addons.

In 6.x, Storybook supported a `.storybook/babelrc` configuration option. This is no longer supported and it's up to you to reconcile this with your project babelrc.

To activate the v7 mode set the feature flag in your `.storybook/main.js` config:

```js
module.exports = {
// ... your existing config
features: {
babelModeV7: true,
},
};
```

In the new mode, Storybook expects you to provide a configuration file. If you want a configuration file that's equivalent to the 6.x default, you can run the following command in your project directory:

```sh
npx sb@next babelrc
```

This will create a `.babelrc.json` file. This file includes a bunch of babel plugins, so you may need to add new package devDependencies accordingly.

## From version 6.2.x to 6.3.0

### Webpack 5 manager build
Expand Down
4 changes: 2 additions & 2 deletions app/react/src/server/framework-preset-react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ export async function babelDefault(config: TransformOptions) {
return {
...config,
presets: [
...config.presets,
...(config?.presets || []),
[require.resolve('@babel/preset-react'), presetReactOptions],
require.resolve('@babel/preset-flow'),
],
plugins: [...(config.plugins || []), require.resolve('babel-plugin-add-react-displayname')],
plugins: [...(config?.plugins || []), require.resolve('babel-plugin-add-react-displayname')],
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { Configuration } from 'webpack';
import type { Options } from '@storybook/core-common';

export function webpack(config: Configuration) {
export function webpack(config: Configuration, options: Options) {
const babelrcOptions = options.features?.babelModeV7 ? null : { babelrc: false };
config.module.rules.push({
test: [
new RegExp(`src(.*)\\.js$`),
Expand Down Expand Up @@ -30,7 +32,7 @@ export function webpack(config: Configuration) {
},
],
],
babelrc: false,
...babelrcOptions,
},
},
});
Expand Down
67 changes: 66 additions & 1 deletion docs/configure/babel.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,21 @@
title: 'Babel'
---

Storybook’s webpack config by [default](#default-configuration) sets up [Babel](https://babeljs.io/) for ES6 transpiling. Storybook works with evergreen browsers by default.
Storybook’s webpack config by [default](#default-configuration) sets up [Babel](https://babeljs.io/) for ES6 transpiling.

It has three different modes:

- **CRA** - the mode for Create React App apps specifically
- **V6** - the default mode for version 6.x and below
- **V7** - a new mode slated to become the default in SB7.x

## CRA mode

CRA apps configured with `@storybook/preset-create-react-app` use CRA's babel handling to behave as close as possible to your actual application. None of the other documentation on this page applies.

## V6 mode

Storybook works with evergreen browsers by default.

If you want to run Storybook in IE11, make sure to [disable](../essentials/introduction#disabling-addons) the docs-addon that is part of `@storybook/addon-essentials`, as this currently [causes issues in IE11](https://github.com/storybookjs/storybook/issues/8884).

Expand Down Expand Up @@ -37,3 +51,54 @@ module.exports = {
}),
};
```

## V7 Mode

V7 mode is a new option available in Storybook 6.4+ behind a feature flag.

Its goal is to make Babel configuration simpler, less buggy, easier to troubleshoot, and more consistent with the rest of the JS ecosystem.

In V7 mode, you are responsible for configuring Babel using your `.babelrc` file and Storybook does not provide any default. Storybook's frameworks and addons may provide small programmatic modifications to the babel configuration.

### Activating

To activate V7 mode, set the feature flag in your `.storybook/main.js` config:

```js
module.exports = {
// ... your existing config
features: {
babelModeV7: true,
},
};
```

### Migrating from V6

For detailed instructions on how to migrate from `V6` mode please see [MIGRATION.md](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#babel-mode-v7).

### Generate a babelrc

If your app does not use a babelrc and you need one, you can generate a babelrc file by running the following command in your project directory:

```sh
npx sb@next babelrc
```

This will create a `.babelrc.json` file. You may need to add package dependencies.

### Troubleshooting

To troubleshoot your babel configuration, set the `BABEL_SHOW_CONFIG_FOR` environment variable.

For example, to see how Storybook is transpiling your `.storybook/preview.js` config:

```sh
BABEL_SHOW_CONFIG_FOR=.storybook/preview.js yarn storybook
```

This will print out the babel configuration for `.storybook/preview.js`, which can be used to debug when files fail to transpile or transpile incorrectly.

> NOTE: Due to what appears to be a Babel bug, setting this flag causes Babel transpilation to fail on the file provided. Thus you cannot actually _RUN_ storybook using this command. However, it will print out the configuration information as advertised and thus you can use this to debug your Storybook. You'll need to remove the flag to actually run your Storybook.

For more info, please refer to the [Babel documentation](https://babeljs.io/docs/en/configuration#print-effective-configs).
1 change: 1 addition & 0 deletions examples/react-ts/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const config: StorybookConfig = {
postcss: false,
previewCsfV3: true,
buildStoriesJson: true,
babelModeV7: true,
},
};

Expand Down
2 changes: 1 addition & 1 deletion lib/builder-webpack4/src/preview/base-webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path from 'path';
import { logger } from '@storybook/node-logger';
import deprecate from 'util-deprecate';
import dedent from 'ts-dedent';
import type { BuilderOptions, LoadedPreset, Options } from '@storybook/core-common';
import type { LoadedPreset, Options } from '@storybook/core-common';

const warnImplicitPostcssPlugins = deprecate(
() => ({
Expand Down
1 change: 1 addition & 0 deletions lib/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@storybook/codemod": "6.4.0-alpha.32",
"@storybook/core-common": "6.4.0-alpha.32",
"@storybook/node-logger": "6.4.0-alpha.32",
"@storybook/semver": "^7.3.2",
"boxen": "^4.2.0",
Expand Down
41 changes: 41 additions & 0 deletions lib/cli/src/babel-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { writeFile, access } from 'fs-extra';
import { logger } from '@storybook/node-logger';
import { getStorybookBabelConfig } from '@storybook/core-common';
import path from 'path';
import prompts from 'prompts';

export const generateStorybookBabelConfigInCWD = async () => {
const target = process.cwd();
return generateStorybookBabelConfig({ target });
};
export const generateStorybookBabelConfig = async ({ target }: { target: string }) => {
logger.info(`Generating the storybook default babel config at ${target}`);

const config = getStorybookBabelConfig({ local: true });
const contents = JSON.stringify(config, null, 2);

const fileName = '.babelrc.json';
const location = path.join(target, fileName);

const exists = await access(location).then(
() => true,
() => false
);

if (exists) {
const { overwrite } = await prompts({
type: 'confirm',
initial: true,
name: 'overwrite',
message: `${fileName} already exists. Would you like overwrite it?`,
});

if (overwrite === false) {
logger.warn(`Cancelled, babel config file was NOT written to file-system.`);
return;
}
}

logger.info(`Writing file to ${location}`);
await writeFile(location, contents);
};
8 changes: 7 additions & 1 deletion lib/cli/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import chalk from 'chalk';
import envinfo from 'envinfo';
import leven from 'leven';
import { sync } from 'read-pkg-up';
import initiate from './initiate';
import { initiate } from './initiate';
import { add } from './add';
import { migrate } from './migrate';
import { extract } from './extract';
import { upgrade } from './upgrade';
import { repro } from './repro';
import { link } from './link';
import { generateStorybookBabelConfigInCWD } from './babel-config';

const pkg = sync({ cwd: __dirname }).packageJson;

Expand All @@ -37,6 +38,11 @@ program
.option('-s --skip-postinstall', 'Skip package specific postinstall config modifications')
.action((addonName, options) => add(addonName, options));

program
.command('babelrc')
.description('generate the default storybook babel config into your current working directory')
.action(() => generateStorybookBabelConfigInCWD());

program
.command('upgrade')
.description('Upgrade your Storybook packages to the latest')
Expand Down
12 changes: 12 additions & 0 deletions lib/cli/src/generators/baseGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import fse from 'fs-extra';
import { getStorybookBabelDependencies } from '@storybook/core-common';
import { NpmOptions } from '../NpmOptions';
import {
StoryFormat,
Expand All @@ -9,6 +11,7 @@ import {
import { getBabelDependencies, copyComponents } from '../helpers';
import { configure } from './configure';
import { getPackageDetails, JsPackageManager } from '../js-package-manager';
import { generateStorybookBabelConfigInCWD } from '../babel-config';

export type GeneratorOptions = {
language: SupportedLanguage;
Expand Down Expand Up @@ -91,6 +94,11 @@ export async function baseGenerator(
const yarn2Dependencies =
packageManager.type === 'yarn2' ? ['@storybook/addon-docs', '@mdx-js/react'] : [];

const files = await fse.readdir(process.cwd());
const isNewFolder = !files.some(
(fname) => fname.startsWith('.babel') || fname.startsWith('babel') || fname === 'package.json'
);

const packageJson = packageManager.retrievePackageJson();
const installedDependencies = new Set(Object.keys(packageJson.dependencies));

Expand Down Expand Up @@ -129,6 +137,10 @@ export async function baseGenerator(
}

const babelDependencies = addBabel ? await getBabelDependencies(packageManager, packageJson) : [];
if (isNewFolder) {
babelDependencies.push(...getStorybookBabelDependencies());
await generateStorybookBabelConfigInCWD();
}
packageManager.addDependencies({ ...npmOptions, packageJson }, [
...versionedPackages,
...babelDependencies,
Expand Down
2 changes: 1 addition & 1 deletion lib/cli/src/initiate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ const projectTypeInquirer = async (options: { yes?: boolean }) => {
return Promise.resolve();
};

export default function (options: CommandOptions, pkg: Package): Promise<void> {
export function initiate(options: CommandOptions, pkg: Package): Promise<void> {
const welcomeMessage = 'sb init - the simplest way to add a Storybook to your project.';
logger.log(chalk.inverse(`\n ${welcomeMessage} \n`));

Expand Down
5 changes: 5 additions & 0 deletions lib/core-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ export interface StorybookConfig {
* Activate preview of CSF v3.0
*/
previewCsfV3?: boolean;

/**
* Use Storybook 7.0 babel config scheme
*/
babelModeV7?: boolean;
};
/**
* Tells Storybook where to find stories.
Expand Down
Loading