From 011baad9815826d61d5ad494742ee39e89486185 Mon Sep 17 00:00:00 2001 From: Pedro Nauck Date: Mon, 30 Jul 2018 00:59:42 -0300 Subject: [PATCH] fix(docz-core): remove babel plugin/presets when needed --- packages/docz-core/package.json | 1 + packages/docz-core/src/Bundler.ts | 6 +- packages/docz-core/src/Plugin.ts | 2 +- .../docz-core/src/bundlers/webpack/config.ts | 47 ++++----- packages/docz-core/src/commands/args.ts | 2 +- packages/docz-core/src/commands/build.ts | 2 +- packages/docz-core/src/commands/dev.ts | 3 +- packages/docz-core/src/index.ts | 2 +- packages/docz-core/src/utils/babel-config.ts | 99 +++++++++++++++++++ packages/docz-core/src/utils/babelrc.ts | 56 ----------- packages/docz-core/src/utils/load-config.ts | 2 +- packages/docz-core/templates/root.tpl.js | 9 +- 12 files changed, 141 insertions(+), 90 deletions(-) create mode 100644 packages/docz-core/src/utils/babel-config.ts delete mode 100644 packages/docz-core/src/utils/babelrc.ts diff --git a/packages/docz-core/package.json b/packages/docz-core/package.json index 1e022dd5a..16ca80d7f 100644 --- a/packages/docz-core/package.json +++ b/packages/docz-core/package.json @@ -23,6 +23,7 @@ }, "dependencies": { "@babel/core": "7.0.0-beta.55", + "@babel/plugin-syntax-dynamic-import": "^7.0.0-beta.55", "@babel/preset-typescript": "^7.0.0-beta.55", "@babel/runtime": "^7.0.0-beta.55", "@mdx-js/loader": "^0.15.0-1", diff --git a/packages/docz-core/src/Bundler.ts b/packages/docz-core/src/Bundler.ts index 2d9557d67..0865eb02b 100644 --- a/packages/docz-core/src/Bundler.ts +++ b/packages/docz-core/src/Bundler.ts @@ -4,7 +4,7 @@ import logger from 'signale' import { Plugin } from './Plugin' import { Config as Args, Env } from './commands/args' -import { babelrc, BabelRC } from './utils/babelrc' +import { getBabelConfig, BabelRC } from './utils/babel-config' import * as paths from './config/paths' export interface Server { @@ -54,8 +54,8 @@ export class Bundler { this.builder = build } - public getConfig(env: Env): C { - const babelConfig = babelrc(this.args, env) + public async getConfig(env: Env): Promise { + const babelConfig = await getBabelConfig(this.args, env) const config = this.mountConfig(this.config(babelConfig), env) return this.args.modifyBundlerConfig(config, !this.isProd(env), this.args) diff --git a/packages/docz-core/src/Plugin.ts b/packages/docz-core/src/Plugin.ts index af7c62db1..200bd4107 100644 --- a/packages/docz-core/src/Plugin.ts +++ b/packages/docz-core/src/Plugin.ts @@ -2,7 +2,7 @@ import get from 'lodash.get' import { Config } from './commands/args' import { isFn } from './utils/helpers' -import { BabelRC } from './utils/babelrc' +import { BabelRC } from './utils/babel-config' export type SetConfig = (config: Config) => Config export type ModifyBundlerConfig = ( diff --git a/packages/docz-core/src/bundlers/webpack/config.ts b/packages/docz-core/src/bundlers/webpack/config.ts index f766a12c2..9f3e75395 100644 --- a/packages/docz-core/src/bundlers/webpack/config.ts +++ b/packages/docz-core/src/bundlers/webpack/config.ts @@ -8,7 +8,7 @@ import manifestPlugin from 'webpack-manifest-plugin' import UglifyJs from 'uglifyjs-webpack-plugin' import { Config as Args, Env } from '../../commands/args' -import { BabelRC } from '../../utils/babelrc' +import { BabelRC } from '../../utils/babel-config' import * as paths from '../../config/paths' import * as loaders from './loaders' @@ -126,28 +126,30 @@ export const createConfig = (args: Args, env: Env) => ( path.dirname(require.resolve('@babel/runtime/package.json')) ) - const addExtensions = (resolve: any) => { - resolve.extensions - .add('.web.js') - .add('.mjs') - .add('.js') - .add('.json') - .add('.web.jsx') - .add('.jsx') - .add('.mdx') + config.when(isProd, cfg => + cfg.resolve.alias.set( + 'webpack-hot-client/client', + require.resolve('webpack-hot-client/client') + ) + ) + + config.resolve.extensions + .add('.web.js') + .add('.mjs') + .add('.js') + .add('.json') + .add('.web.jsx') + .add('.jsx') + .add('.mdx') + .end() + + if (args.typescript) { + config.resolve.extensions + .prepend('.ts') + .prepend('.tsx') .end() - - if (args.typescript) { - resolve.extensions - .prepend('.ts') - .prepend('.tsx') - .end() - } } - addExtensions(config.resolve) - addExtensions(config.resolveLoader) - config.resolve.modules // prioritize our own .add(paths.ownNodeModules) @@ -170,13 +172,14 @@ export const createConfig = (args: Args, env: Env) => ( loaders.js(config, args) loaders.mdx(config, args) - args.typescript && loaders.ts(config, args) - loaders.setupHappypack(config, args, babelrc) loaders.images(config) loaders.svg(config) loaders.media(config) loaders.fonts(config) + args.typescript && loaders.ts(config, args) + loaders.setupHappypack(config, args, babelrc) + /** * plugins */ diff --git a/packages/docz-core/src/commands/args.ts b/packages/docz-core/src/commands/args.ts index 8f0360e97..bc4f5a3d5 100644 --- a/packages/docz-core/src/commands/args.ts +++ b/packages/docz-core/src/commands/args.ts @@ -4,7 +4,7 @@ import titleize from 'titleize' import envDotProp from 'env-dot-prop' import { Plugin } from '../Plugin' -import { BabelRC } from '../utils/babelrc' +import { BabelRC } from '../utils/babel-config' import * as paths from '../config/paths' const getEnv = (val: string, defaultValue: any = null): any => diff --git a/packages/docz-core/src/commands/build.ts b/packages/docz-core/src/commands/build.ts index 6d971e35b..129db5103 100644 --- a/packages/docz-core/src/commands/build.ts +++ b/packages/docz-core/src/commands/build.ts @@ -24,7 +24,7 @@ export const build = async (args: Config) => { try { await run('onPreBuild') - await bundler.build(bundler.getConfig(env)) + await bundler.build(await bundler.getConfig(env)) await run('onPostBuild') } catch (err) { logger.fatal(err) diff --git a/packages/docz-core/src/commands/dev.ts b/packages/docz-core/src/commands/dev.ts index fc751de7f..c73dbbe0f 100644 --- a/packages/docz-core/src/commands/dev.ts +++ b/packages/docz-core/src/commands/dev.ts @@ -18,7 +18,8 @@ export const dev = async (args: Config) => { const entries = new Entries(config) const bundler = webpack({ ...config, port }, env) - const server = await bundler.createServer(bundler.getConfig(env)) + const bundlerConfig = await bundler.getConfig(env) + const server = await bundler.createServer(bundlerConfig) const { app } = await server.start() const newConfig = { ...config, websocketPort } diff --git a/packages/docz-core/src/index.ts b/packages/docz-core/src/index.ts index b2badb89f..ea8c129e7 100644 --- a/packages/docz-core/src/index.ts +++ b/packages/docz-core/src/index.ts @@ -4,4 +4,4 @@ import { args } from './commands/args' export { commands, args } export { Config } from './commands/args' export { Plugin, createPlugin } from './Plugin' -export { BabelRC } from './utils/babelrc' +export { BabelRC } from './utils/babel-config' diff --git a/packages/docz-core/src/utils/babel-config.ts b/packages/docz-core/src/utils/babel-config.ts new file mode 100644 index 000000000..9a9c42449 --- /dev/null +++ b/packages/docz-core/src/utils/babel-config.ts @@ -0,0 +1,99 @@ +import { load } from 'load-cfg' +import merge from 'deepmerge' + +import { Config, Env } from '../commands/args' +import { Plugin } from '../Plugin' + +export interface BabelRC { + presets: any[] + plugins: any[] + cacheDirectory?: boolean + babelrc?: boolean +} + +/** + * Presets configuration + */ + +const PRESETS_REACT = /@babel\/preset-env|@babel\/preset-react|babel-preset-react-app|next\/babel|razzle/ +const PRESET_TS = /@babel\/preset-typescript/ + +const getPresets = (args: Config, { presets }: BabelRC) => { + const hasPresets = presets && presets.length > 0 + const needReact = !hasPresets || presets.every(p => !PRESETS_REACT.test(p)) + const needTSPreset = !hasPresets || presets.every(p => !PRESET_TS.test(p)) + + const newPresets: any[] = needReact + ? [[require.resolve('babel-preset-react-app'), { flow: !args.typescript }]] + : [] + + if (needTSPreset && args.typescript) { + newPresets.push(require.resolve('@babel/preset-typescript')) + } + + return newPresets +} + +/** + * Plugins configuration + */ + +const PRESETS_WITH_DYNAMIC = /babel-preset-react-app|next\/babel|razzle/ +const DYNAMIC_IMPORT = /@babel\/plugin-syntax-dynamic-import/ +const HOT_LOADER = /react-hot-loader\/babel/ +const DOCGEN = /babel-plugin-react-docgen/ + +const getPlugins = (args: Config, env: Env, { presets, plugins }: BabelRC) => { + const newPlugins: any[] = [] + const isProd = env === 'production' + const hasPresets = presets && presets.length > 0 + + const needHotLoader = plugins.every(p => !HOT_LOADER.test(p)) + const needReactDocgen = plugins.every(p => !DOCGEN.test(p)) + const needBabelDynamicImport = + hasPresets && + presets.every(p => !PRESETS_WITH_DYNAMIC.test(p)) && + plugins.every(p => !DYNAMIC_IMPORT.test(p)) + + if (needHotLoader && !isProd) { + newPlugins.push(require.resolve('react-hot-loader/babel')) + } + + if (needReactDocgen && args.propsParser && !args.typescript) { + newPlugins.push([ + require.resolve('babel-plugin-react-docgen'), + { resolver: 'findAllExportedComponentDefinitions' }, + ]) + } + + if (needBabelDynamicImport) { + newPlugins.push(require.resolve('@babel/plugin-syntax-dynamic-import')) + } + + return newPlugins +} + +/** + * Exporting .babelrc config used on docz + */ + +export const getBabelConfig = async ( + args: Config, + env: Env +): Promise => { + const localBabelRc = load('babel', { presets: [], plugins: [] }) + const presets = getPresets(args, localBabelRc) + const plugins = getPlugins(args, env, localBabelRc) + + const config = merge(localBabelRc, { + presets, + plugins, + cacheDirectory: !args.debug, + babelrc: false, + }) + + const reduce = Plugin.reduceFromPlugins(args.plugins) + const newConfig = reduce('modifyBabelRc', config, args) + + return args.modifyBabelRc(newConfig, args) +} diff --git a/packages/docz-core/src/utils/babelrc.ts b/packages/docz-core/src/utils/babelrc.ts deleted file mode 100644 index b1dc96bd7..000000000 --- a/packages/docz-core/src/utils/babelrc.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { load } from 'load-cfg' -import merge from 'deepmerge' - -import { Config, Env } from '../commands/args' -import { Plugin } from '../Plugin' - -export interface BabelRC { - presets?: any[] - plugins?: any[] - cacheDirectory?: boolean - babelrc?: boolean -} - -const getPresets = (args: Config) => { - const presets: any[] = [ - [require.resolve('babel-preset-react-app'), { flow: !args.typescript }], - ] - - if (args.typescript) presets.push(require.resolve('@babel/preset-typescript')) - return presets -} - -const getPlugins = (args: Config, env: Env) => { - const isProd = env === 'production' - const plugins: any[] = [] - - if (!isProd) { - plugins.push(require.resolve('react-hot-loader/babel')) - } - - if (args.propsParser && !args.typescript) { - plugins.push([ - require.resolve('babel-plugin-react-docgen'), - { resolver: 'findAllExportedComponentDefinitions' }, - ]) - } - - return plugins -} - -export const babelrc = (args: Config, env: Env): BabelRC => { - const presets = getPresets(args) - const plugins = getPlugins(args, env) - - const config = merge(load('babel', null), { - presets, - plugins, - cacheDirectory: !args.debug, - babelrc: false, - }) - - const reduce = Plugin.reduceFromPlugins(args.plugins) - const newConfig = reduce('modifyBabelRc', config, args) - - return args.modifyBabelRc(newConfig, args) -} diff --git a/packages/docz-core/src/utils/load-config.ts b/packages/docz-core/src/utils/load-config.ts index a2a7b054f..3c4fbfdbc 100644 --- a/packages/docz-core/src/utils/load-config.ts +++ b/packages/docz-core/src/utils/load-config.ts @@ -4,7 +4,7 @@ import * as paths from '../config/paths' import { Config } from '../commands/args' import { Plugin } from '../Plugin' import { omit } from './helpers' -import { BabelRC } from './babelrc' +import { BabelRC } from './babel-config' const toOmit = ['_', '$0', 'version', 'help'] diff --git a/packages/docz-core/templates/root.tpl.js b/packages/docz-core/templates/root.tpl.js index b0c96fbe3..501f429c5 100644 --- a/packages/docz-core/templates/root.tpl.js +++ b/packages/docz-core/templates/root.tpl.js @@ -9,9 +9,12 @@ import Theme from '<%- theme %>' <% if (!isProd) {%> class Root extends React.Component { - state = { - config: {}, - entries: {}, + constructor(props, ctx) { + super(props, ctx) + this.state = { + entries: {}, + config: {}, + } } async componentDidMount() {