diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js
index 43ae889904dd7..8876f2ae6f26f 100644
--- a/src/dev/precommit_hook/casing_check_config.js
+++ b/src/dev/precommit_hook/casing_check_config.js
@@ -17,7 +17,6 @@
* under the License.
*/
-
/**
* These patterns are used to identify files that are not supposed
* to be snake_case because their names are determined by other
@@ -43,22 +42,20 @@ export const IGNORE_FILE_GLOBS = [
'x-pack/docs/**/*',
'src/legacy/ui/public/assets/fonts/**/*',
+ // Files in this directory must match a pre-determined name in some cases.
+ 'x-pack/plugins/canvas/.storybook/*',
+
// filename must match language code which requires capital letters
- '**/translations/*.json'
+ '**/translations/*.json',
];
-
/**
* These patterns are matched against directories and indicate
* folders that must use kebab case.
*
* @type {Array}
*/
-export const KEBAB_CASE_DIRECTORY_GLOBS = [
- 'packages/*',
- 'x-pack',
-];
-
+export const KEBAB_CASE_DIRECTORY_GLOBS = ['packages/*', 'x-pack'];
/**
* These patterns are matched against directories and indicate
@@ -88,7 +85,6 @@ export const IGNORE_DIRECTORY_GLOBS = [
'x-pack/dev-tools',
];
-
/**
* DO NOT ADD FILES TO THIS LIST!!
*
diff --git a/src/dev/sass/build_sass.js b/src/dev/sass/build_sass.js
index fd00e62ce1520..51d6454ac45fb 100644
--- a/src/dev/sass/build_sass.js
+++ b/src/dev/sass/build_sass.js
@@ -22,32 +22,25 @@ import { resolve } from 'path';
import { toArray } from 'rxjs/operators';
import { createFailError } from '../run';
-import { findPluginSpecs } from '../../legacy/plugin_discovery';
-import { collectUiExports } from '../../legacy/ui';
-import { buildAll } from '../../legacy/server/sass/build_all';
+import { findPluginSpecs } from '../../legacy/plugin_discovery';
+import { collectUiExports } from '../../legacy/ui';
+import { buildAll } from '../../legacy/server/sass/build_all';
+import chokidar from 'chokidar';
+import debounce from 'lodash/function/debounce';
-export async function buildSass({ log, kibanaDir }) {
- log.info('running plugin discovery in', kibanaDir);
-
- const scanDirs = [
- resolve(kibanaDir, 'src/legacy/core_plugins')
- ];
-
- const paths = [ resolve(kibanaDir, 'x-pack') ];
-
- const { spec$ } = findPluginSpecs({ plugins: { scanDirs, paths } });
- const enabledPlugins = await spec$.pipe(toArray()).toPromise();
- const uiExports = collectUiExports(enabledPlugins);
- log.info('found %d styleSheetPaths', uiExports.styleSheetPaths.length);
- log.verbose(uiExports.styleSheetPaths);
+// TODO: clintandrewhall - Extract and use FSWatcher from legacy/server/sass
+const build = async ({ log, kibanaDir, styleSheetPaths, watch }) => {
+ if (styleSheetPaths.length === 0) {
+ return;
+ }
let bundleCount = 0;
try {
const bundles = await buildAll({
- styleSheets: uiExports.styleSheetPaths,
+ styleSheets: styleSheetPaths,
log,
buildDir: resolve(kibanaDir, 'built_assets/css'),
- sourceMap: true
+ sourceMap: true,
});
bundles.forEach(bundle => {
@@ -60,5 +53,41 @@ export async function buildSass({ log, kibanaDir }) {
throw createFailError(`${message} on line ${line} of ${file}`);
}
- log.success('%d scss bundles created', bundleCount);
+ log.success('%d scss bundles %s', bundleCount, watch ? 'rebuilt' : 'created');
+};
+
+export async function buildSass({ log, kibanaDir, watch }) {
+ log.info('running plugin discovery in', kibanaDir);
+
+ const scanDirs = [resolve(kibanaDir, 'src/legacy/core_plugins')];
+ const paths = [resolve(kibanaDir, 'x-pack')];
+ const { spec$ } = findPluginSpecs({ plugins: { scanDirs, paths } });
+ const enabledPlugins = await spec$.pipe(toArray()).toPromise();
+ const uiExports = collectUiExports(enabledPlugins);
+ const { styleSheetPaths } = uiExports;
+
+ log.info('%s %d styleSheetPaths', watch ? 'watching' : 'found', styleSheetPaths.length);
+ log.verbose(styleSheetPaths);
+
+ if (watch) {
+ const debouncedBuild = debounce(async path => {
+ let buildPaths = styleSheetPaths;
+ if (path) {
+ buildPaths = styleSheetPaths.filter(styleSheetPath =>
+ path.includes(styleSheetPath.urlImports.publicDir)
+ );
+ }
+ await build({ log, kibanaDir, styleSheetPaths: buildPaths, watch });
+ });
+
+ const watchPaths = styleSheetPaths.map(styleSheetPath => styleSheetPath.urlImports.publicDir);
+
+ await build({ log, kibanaDir, styleSheetPaths });
+
+ chokidar.watch(watchPaths, { ignoreInitial: true }).on('all', (_, path) => {
+ debouncedBuild(path);
+ });
+ } else {
+ await build({ log, kibanaDir, styleSheetPaths });
+ }
}
diff --git a/src/dev/sass/run_build_sass_cli.js b/src/dev/sass/run_build_sass_cli.js
index 5619f4ac63a31..e5e6d076a947a 100644
--- a/src/dev/sass/run_build_sass_cli.js
+++ b/src/dev/sass/run_build_sass_cli.js
@@ -18,23 +18,30 @@
*/
import { run } from '../run';
-import { REPO_ROOT } from '../constants';
+import { REPO_ROOT } from '../constants';
import { buildSass } from './build_sass';
-run(async ({ log, flags: { kibanaDir } }) => {
- await buildSass({
- log,
- kibanaDir
- });
-}, {
- description: 'Simple CLI, useful for building scss files outside of the server',
- flags: {
- default: {
- kibanaDir: REPO_ROOT
- },
- string: ['kibanaDir'],
- help: `
- --kibanaDir The root of the Kibana directory to build sass files in.
- `
+run(
+ async ({ log, flags: { kibanaDir, watch } }) => {
+ await buildSass({
+ log,
+ kibanaDir,
+ watch,
+ });
},
-});
+ {
+ description: 'Simple CLI, useful for building scss files outside of the server',
+ flags: {
+ default: {
+ kibanaDir: REPO_ROOT,
+ watch: false,
+ },
+ string: ['kibanaDir'],
+ boolean: ['watch'],
+ help: `
+ --kibanaDir The root of the Kibana directory to build sass files in.
+ --watch Watch the SASS files and recompile them on save.
+ `,
+ },
+ }
+);
diff --git a/x-pack/package.json b/x-pack/package.json
index caa977c2eb712..91529b3fcbf75 100644
--- a/x-pack/package.json
+++ b/x-pack/package.json
@@ -6,6 +6,7 @@
"license": "Elastic-License",
"scripts": {
"kbn": "node ../scripts/kbn",
+ "kbn:bootstrap": "rm -rf ../built_assets/canvasStorybookDLL",
"start": "gulp dev",
"build": "gulp build",
"testonly": "gulp testonly",
@@ -119,8 +120,7 @@
"pdfjs-dist": "^2.0.943",
"pixelmatch": "4.0.2",
"proxyquire": "1.7.11",
- "react-docgen-typescript-loader": "^3.0.0",
- "react-docgen-typescript-webpack-plugin": "^1.1.0",
+ "react-docgen-typescript-loader": "^3.1.0",
"react-hooks-testing-library": "^0.3.8",
"react-test-renderer": "^16.8.0",
"react-testing-library": "^6.0.0",
diff --git a/x-pack/plugins/canvas/.storybook/config.js b/x-pack/plugins/canvas/.storybook/config.js
index 5e19dbbfa9e51..f4fe1bd3e0230 100644
--- a/x-pack/plugins/canvas/.storybook/config.js
+++ b/x-pack/plugins/canvas/.storybook/config.js
@@ -9,11 +9,6 @@ import { withKnobs } from '@storybook/addon-knobs/react';
import { withInfo } from '@storybook/addon-info';
import { create } from '@storybook/theming';
-// Import dependent CSS
-require('@elastic/eui/dist/eui_theme_light.css');
-require('@kbn/ui-framework/dist/kui_light.css');
-require('../../../../src/legacy/ui/public/styles/bootstrap_light.less');
-
// If we're running Storyshots, be sure to register the require context hook.
// Otherwise, add the other decorators.
if (process.env.NODE_ENV === 'test') {
@@ -39,17 +34,16 @@ if (process.env.NODE_ENV === 'test') {
}
function loadStories() {
- // Pull in the built CSS produced by the Kibana server
- const css = require.context('../../../../built_assets/css', true, /light.css$/);
- css.keys().forEach(filename => css(filename));
+ require('./dll_contexts');
- // Include the legacy styles
- const uiStyles = require.context(
- '../../../../src/legacy/ui/public/styles',
- false,
- /[\/\\](?!mixins|variables|_|\.|bootstrap_(light|dark))[^\/\\]+\.less/
+ // Only gather and require CSS files related to Canvas. The other CSS files
+ // are built into the DLL.
+ const css = require.context(
+ '../../../../built_assets/css',
+ true,
+ /plugins\/(?=canvas).*light\.css/
);
- uiStyles.keys().forEach(key => uiStyles(key));
+ css.keys().forEach(filename => css(filename));
// Find all files ending in *.examples.ts
const req = require.context('./..', true, /.examples.tsx$/);
diff --git a/x-pack/plugins/canvas/.storybook/constants.js b/x-pack/plugins/canvas/.storybook/constants.js
new file mode 100644
index 0000000000000..1a9dac87261ab
--- /dev/null
+++ b/x-pack/plugins/canvas/.storybook/constants.js
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+const path = require('path');
+
+const DLL_NAME = 'canvasStorybookDLL';
+const KIBANA_ROOT = path.resolve(__dirname, '../../../..');
+const BUILT_ASSETS = path.resolve(KIBANA_ROOT, 'built_assets');
+const DLL_OUTPUT = path.resolve(BUILT_ASSETS, DLL_NAME);
+
+module.exports = {
+ DLL_NAME,
+ KIBANA_ROOT,
+ BUILT_ASSETS,
+ DLL_OUTPUT,
+};
diff --git a/x-pack/plugins/canvas/.storybook/dll_contexts.js b/x-pack/plugins/canvas/.storybook/dll_contexts.js
new file mode 100644
index 0000000000000..18d3e61ff61a8
--- /dev/null
+++ b/x-pack/plugins/canvas/.storybook/dll_contexts.js
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+// This file defines CSS and Legacy style contexts for use in the DLL. This file
+// is also require'd in the Storybook config so that the Storybook Webpack instance
+// is aware of them, and can load them from the DLL.
+
+// Pull in the built CSS produced by the Kibana server, but not
+// the Canvas CSS-- we want that in the HMR service.
+const css = require.context(
+ '../../../../built_assets/css',
+ true,
+ /\.\/plugins\/(?!canvas).*light\.css/
+);
+css.keys().forEach(filename => {
+ css(filename);
+});
+
+// Include Legacy styles
+const uiStyles = require.context(
+ '../../../../src/legacy/ui/public/styles',
+ false,
+ /[\/\\](?!mixins|variables|_|\.|bootstrap_(light|dark))[^\/\\]+\.less/
+);
+uiStyles.keys().forEach(key => uiStyles(key));
diff --git a/x-pack/plugins/canvas/.storybook/middleware.js b/x-pack/plugins/canvas/.storybook/middleware.js
index 198ded0f11536..f4526d68686dc 100644
--- a/x-pack/plugins/canvas/.storybook/middleware.js
+++ b/x-pack/plugins/canvas/.storybook/middleware.js
@@ -7,7 +7,7 @@
const serve = require('serve-static');
const path = require('path');
-// Extend the Storybook Middleware to include a route to access ui assets
-module.exports = function (router) {
+// Extend the Storybook Middleware to include a route to access Legacy UI assets
+module.exports = function(router) {
router.get('/ui', serve(path.resolve(__dirname, '../../../../src/legacy/ui/public/assets')));
-}
+};
diff --git a/x-pack/plugins/canvas/.storybook/preview-head.html b/x-pack/plugins/canvas/.storybook/preview-head.html
new file mode 100644
index 0000000000000..bef08a5120a36
--- /dev/null
+++ b/x-pack/plugins/canvas/.storybook/preview-head.html
@@ -0,0 +1,6 @@
+
+
+
diff --git a/x-pack/plugins/canvas/.storybook/storyshots.test.js b/x-pack/plugins/canvas/.storybook/storyshots.test.js
index 43e54fb6736a7..d67e8e8f2c076 100644
--- a/x-pack/plugins/canvas/.storybook/storyshots.test.js
+++ b/x-pack/plugins/canvas/.storybook/storyshots.test.js
@@ -7,11 +7,13 @@
import path from 'path';
import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';
import styleSheetSerializer from 'jest-styled-components/src/styleSheetSerializer';
-import { addSerializer } from 'jest-specific-snapshot'
+import { addSerializer } from 'jest-specific-snapshot';
jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`);
addSerializer(styleSheetSerializer);
+
+// Initialize Storyshots and build the Jest Snapshots
initStoryshots({
configPath: path.resolve(__dirname, './../.storybook'),
test: multiSnapshotWithOptions({}),
diff --git a/x-pack/plugins/canvas/.storybook/webpack.config.js b/x-pack/plugins/canvas/.storybook/webpack.config.js
index ecb25c4bd999e..b6e7159243485 100644
--- a/x-pack/plugins/canvas/.storybook/webpack.config.js
+++ b/x-pack/plugins/canvas/.storybook/webpack.config.js
@@ -5,20 +5,12 @@
*/
const path = require('path');
-const TSDocgenPlugin = require('react-docgen-typescript-webpack-plugin');
-
-// Extend the Storybook Webpack config with some customizations;
-module.exports = async ({ config, _mode }) => {
- // Include the React preset for Storybook JS files.
- config.module.rules.push({
- test: /\.js$/,
- exclude: /node_modules/,
- loaders: 'babel-loader',
- options: {
- presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
- },
- });
+const webpack = require('webpack');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+const { DLL_OUTPUT, KIBANA_ROOT } = require('./constants');
+// Extend the Storybook Webpack config with some customizations
+module.exports = async ({ config }) => {
// Find and alter the CSS rule to replace the Kibana public path string with a path
// to the route we've added in middleware.js
const cssRule = config.module.rules.find(rule => rule.test.source.includes('.css$'));
@@ -31,23 +23,17 @@ module.exports = async ({ config, _mode }) => {
},
});
- // Configure loading LESS files from Kibana
+ // Include the React preset from Kibana for Storybook JS files.
config.module.rules.push({
- test: /\.less$/,
- use: [
- { loader: 'style-loader' },
- { loader: 'css-loader', options: { importLoaders: 2 } },
- {
- loader: 'postcss-loader',
- options: {
- config: { path: path.resolve(__dirname, './../../../../src/optimize/postcss.config.js') },
- },
- },
- { loader: 'less-loader' },
- ],
+ test: /\.js$/,
+ exclude: /node_modules/,
+ loaders: 'babel-loader',
+ options: {
+ presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
+ },
});
- // Support .ts/x files using the tsconfig from Kibana
+ // Handle Typescript files
config.module.rules.push({
test: /\.tsx?$/,
use: [
@@ -57,18 +43,48 @@ module.exports = async ({ config, _mode }) => {
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
},
},
+ ],
+ });
+
+ // Parse props data for .tsx files
+ config.module.rules.push({
+ test: /\.tsx$/,
+ // Exclude example files, as we don't display props info for them
+ exclude: /\.examples.tsx$/,
+ use: [
+ // Parse TS comments to create Props tables in the UI
require.resolve('react-docgen-typescript-loader'),
],
});
- // Include the TSDocgen plugin to display Typescript param comments in the stories.
- config.plugins.push(new TSDocgenPlugin());
+ // Reference the built DLL file of static(ish) dependencies, which are removed
+ // during kbn:bootstrap and rebuilt if missing.
+ config.plugins.push(
+ new webpack.DllReferencePlugin({
+ manifest: path.resolve(DLL_OUTPUT, 'manifest.json'),
+ context: KIBANA_ROOT,
+ })
+ );
+
+ // Copy the DLL files to the Webpack build for use in the Storybook UI
+ config.plugins.push(
+ new CopyWebpackPlugin([
+ {
+ from: path.resolve(DLL_OUTPUT, 'dll.js'),
+ to: 'dll.js',
+ },
+ {
+ from: path.resolve(DLL_OUTPUT, 'dll.css'),
+ to: 'dll.css',
+ },
+ ])
+ );
// Tell Webpack about the ts/x extensions
config.resolve.extensions.push('.ts', '.tsx');
// Alias the any imports from ui/ to the proper directory.
- config.resolve.alias.ui = path.resolve(__dirname, './../../../../src/legacy/ui/public');
+ config.resolve.alias.ui = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public');
return config;
};
diff --git a/x-pack/plugins/canvas/.storybook/webpack.dll.config.js b/x-pack/plugins/canvas/.storybook/webpack.dll.config.js
new file mode 100644
index 0000000000000..3a4b9bd2531e1
--- /dev/null
+++ b/x-pack/plugins/canvas/.storybook/webpack.dll.config.js
@@ -0,0 +1,115 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+const webpack = require('webpack');
+const path = require('path');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+
+const { DLL_NAME, DLL_OUTPUT, KIBANA_ROOT } = require('./constants');
+
+// This is the Webpack config for the DLL of CSS and JS assets that are
+// not expected to change during development. This saves compile and run
+// times considerably.
+module.exports = {
+ context: KIBANA_ROOT,
+ mode: 'development',
+
+ // This is a (potentially growing) list of modules that can be safely
+ // included in the DLL. Only add to this list modules or other code
+ // which Storybook stories and their components would require, but don't
+ // change during development.
+ entry: [
+ '@elastic/eui',
+ '@elastic/eui/dist/eui_theme_light.css',
+ '@kbn/ui-framework/dist/kui_light.css',
+ '@storybook/addon-actions',
+ '@storybook/addon-actions/register',
+ '@storybook/addon-info',
+ '@storybook/addon-knobs',
+ '@storybook/addon-knobs/react',
+ '@storybook/addon-knobs/register',
+ '@storybook/addon-options',
+ '@storybook/addon-options/register',
+ '@storybook/core',
+ '@storybook/core/dist/server/common/polyfills.js',
+ '@storybook/react',
+ '@storybook/theming',
+ 'chroma-js',
+ 'lodash',
+ 'prop-types',
+ 'react-dom',
+ 'react',
+ 'recompose',
+ 'tinycolor2',
+ // Include the DLL UI contexts from Kibana
+ require.resolve('./dll_contexts'),
+ ],
+ plugins: [
+ // Produce the DLL and its manifest
+ new webpack.DllPlugin({
+ name: DLL_NAME,
+ path: path.resolve(DLL_OUTPUT, 'manifest.json'),
+ }),
+ // Produce the DLL CSS file
+ new MiniCssExtractPlugin({
+ filename: 'dll.css',
+ }),
+ ],
+ // Output the DLL JS file
+ output: {
+ path: DLL_OUTPUT,
+ filename: 'dll.js',
+ library: DLL_NAME,
+ },
+ // Include a require alias for legacy UI code and styles
+ resolve: {
+ alias: {
+ ui: path.resolve(KIBANA_ROOT, 'src/legacy/ui/public'),
+ },
+ },
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: [
+ {
+ loader: MiniCssExtractPlugin.loader,
+ options: {},
+ },
+ { loader: 'css-loader' },
+ {
+ loader: 'string-replace-loader',
+ options: {
+ search: '__REPLACE_WITH_PUBLIC_PATH__',
+ replace: '/',
+ flags: 'g',
+ },
+ },
+ ],
+ },
+ {
+ test: /\.less$/,
+ use: [
+ { loader: 'style-loader' },
+ { loader: 'css-loader', options: { importLoaders: 2 } },
+ {
+ loader: 'postcss-loader',
+ options: {
+ config: {
+ path: path.resolve(KIBANA_ROOT, 'src/optimize/postcss.config.js'),
+ },
+ },
+ },
+ { loader: 'less-loader' },
+ ],
+ },
+ {
+ test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/,
+ loader: 'file-loader',
+ },
+ ],
+ },
+};
diff --git a/x-pack/plugins/canvas/scripts/storybook.js b/x-pack/plugins/canvas/scripts/storybook.js
index 6e8715444ba37..03fed628b81e8 100644
--- a/x-pack/plugins/canvas/scripts/storybook.js
+++ b/x-pack/plugins/canvas/scripts/storybook.js
@@ -5,31 +5,38 @@
*/
const path = require('path');
+const devUtils = require('@kbn/dev-utils');
const storybook = require('@storybook/react/standalone');
const execa = require('execa');
-// We have to start up the Kibana server to process CSS files as we change them.
-// This is pretty much a hack for the moment. We can get a separate process up
-// and running in the future.
-execa(
- process.execPath,
- [
- 'scripts/kibana',
- '--optimize.enabled=false',
- '--env.name="development"',
- '--plugins.initialize=false',
- '--server.port=5699',
- ],
- {
- cwd: path.resolve(__dirname, '../../../..'),
- stdio: ['ignore', 'inherit', 'inherit'],
- buffer: false,
- }
-).catch(err => {
- console.log('Kibana server died:', err.message);
- process.exit(1);
+const log = new devUtils.ToolingLog({
+ level: 'info',
+ writeTo: process.stdout,
});
+const options = {
+ stdio: ['ignore', 'inherit', 'inherit'],
+ buffer: false,
+};
+
+execa.sync('node', ['storybook_dll.js'], {
+ cwd: __dirname,
+ ...options,
+});
+
+// Ensure SASS has been built completely before starting Storybook
+execa.sync(process.execPath, ['scripts/build_sass'], {
+ cwd: path.resolve(__dirname, '../../../..'),
+ ...options,
+});
+
+// Now watch the SASS sheets for changes
+execa(process.execPath, ['scripts/build_sass', '--watch'], {
+ cwd: path.resolve(__dirname, '../../../..'),
+ ...options,
+});
+
+log.info('storybook: Starting Storybook');
storybook({
mode: 'dev',
port: 9001,
diff --git a/x-pack/plugins/canvas/scripts/storybook_dll.js b/x-pack/plugins/canvas/scripts/storybook_dll.js
new file mode 100644
index 0000000000000..2e1ac9694faca
--- /dev/null
+++ b/x-pack/plugins/canvas/scripts/storybook_dll.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+const fs = require('fs');
+const path = require('path');
+const execa = require('execa');
+const devUtils = require('@kbn/dev-utils');
+const { DLL_OUTPUT } = require('./../.storybook/constants');
+
+const log = new devUtils.ToolingLog({
+ level: 'info',
+ writeTo: process.stdout,
+});
+
+if (fs.existsSync(DLL_OUTPUT)) {
+ log.info('storybook: DLL exists from previous build');
+} else {
+ log.info('storybook: DLL missing; building');
+ execa.sync(
+ 'yarn',
+ [
+ 'webpack',
+ '--config',
+ 'x-pack/plugins/canvas/.storybook/webpack.dll.config.js',
+ '--progress',
+ '--hide-modules',
+ '--display-entrypoints',
+ 'false',
+ ],
+ {
+ cwd: path.resolve(__dirname, '../../../..'),
+ stdio: ['ignore', 'inherit', 'inherit'],
+ buffer: false,
+ }
+ );
+ log.success('storybook: DLL built');
+}
diff --git a/x-pack/plugins/canvas/scripts/storybook_build.js b/x-pack/plugins/canvas/scripts/storybook_static.js
similarity index 55%
rename from x-pack/plugins/canvas/scripts/storybook_build.js
rename to x-pack/plugins/canvas/scripts/storybook_static.js
index 97ae145e815aa..9c9a29da83b09 100644
--- a/x-pack/plugins/canvas/scripts/storybook_build.js
+++ b/x-pack/plugins/canvas/scripts/storybook_static.js
@@ -5,8 +5,25 @@
*/
const path = require('path');
+const execa = require('execa');
const storybook = require('@storybook/react/standalone');
+const options = {
+ stdio: ['ignore', 'inherit', 'inherit'],
+ buffer: false,
+};
+
+execa.sync('node', ['storybook_dll.js'], {
+ cwd: __dirname,
+ ...options,
+});
+
+// Ensure SASS has been built completely before starting Storybook
+execa.sync(process.execPath, ['scripts/build_sass'], {
+ cwd: path.resolve(__dirname, '../../../..'),
+ ...options,
+});
+
storybook({
mode: 'static',
configDir: path.resolve(__dirname, './../.storybook'),
diff --git a/yarn.lock b/yarn.lock
index e557716f4f1bf..12863d98b1916 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4034,16 +4034,6 @@ ajv@^6.1.0, ajv@^6.5.5:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-ajv@^6.1.1:
- version "6.10.0"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
- integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==
- dependencies:
- fast-deep-equal "^2.0.1"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.4.1"
- uri-js "^4.2.2"
-
ajv@^6.9.1:
version "6.9.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.2.tgz#4927adb83e7f48e5a32b45729744c71ec39c9c7b"
@@ -20213,24 +20203,16 @@ react-dev-utils@^7.0.0, react-dev-utils@^7.0.1:
strip-ansi "5.0.0"
text-table "0.2.0"
-react-docgen-typescript-loader@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/react-docgen-typescript-loader/-/react-docgen-typescript-loader-3.0.0.tgz#4042e2854d29380e4d01e479d438c03ec00de8e8"
- integrity sha512-xtE4bZrU9+7grFFzs8v6gWc+Wl2FCCL59hldHoX2DuQAXOmJIilUm2uPmDmRNA8RpxU1Ax+9Gl0JfUcWgx2QPA==
+react-docgen-typescript-loader@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/react-docgen-typescript-loader/-/react-docgen-typescript-loader-3.1.0.tgz#09cacf872617c97f946ee920d2239f51d543be41"
+ integrity sha512-gY+b7RkRPty5ZN4NMQ+jwx9MzTVuIj6LJCwdWRAi1+nrHJfH2gMMytQfxFdzQ7BlgD4COWnSE8Ixtl2L62kCRw==
dependencies:
"@webpack-contrib/schema-utils" "^1.0.0-beta.0"
- loader-utils "^1.1.0"
- react-docgen-typescript "^1.9.0"
-
-react-docgen-typescript-webpack-plugin@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/react-docgen-typescript-webpack-plugin/-/react-docgen-typescript-webpack-plugin-1.1.0.tgz#4bfb8c3312fce487083924842cf03f66177ab9df"
- integrity sha1-S/uMMxL85IcIOSSELPA/Zhd6ud8=
- dependencies:
- ajv "^6.1.1"
- react-docgen-typescript "^1.2.3"
+ loader-utils "^1.2.3"
+ react-docgen-typescript "^1.12.3"
-react-docgen-typescript@^1.2.3, react-docgen-typescript@^1.9.0:
+react-docgen-typescript@^1.12.3:
version "1.12.3"
resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.12.3.tgz#fe62a5ce82e93573e316366e53adfe8273121c70"
integrity sha512-s1XswWs4ykNdWKsPyfM4qptV5dT8nnjnVi2IcjoS/vGlRNYrc0TkW0scVOrinHZ+ndKhPqA4iVNrdwhxZBzJcg==