diff --git a/dist/server/build.js b/dist/server/build.js new file mode 100755 index 000000000000..1a11d74290b9 --- /dev/null +++ b/dist/server/build.js @@ -0,0 +1,96 @@ +#!/usr/bin/env node +'use strict'; + +var _webpack = require('webpack'); + +var _webpack2 = _interopRequireDefault(_webpack); + +var _commander = require('commander'); + +var _commander2 = _interopRequireDefault(_commander); + +var _path = require('path'); + +var _path2 = _interopRequireDefault(_path); + +var _fs = require('fs'); + +var _fs2 = _interopRequireDefault(_fs); + +var _shelljs = require('shelljs'); + +var _shelljs2 = _interopRequireDefault(_shelljs); + +var _package = require('../../package.json'); + +var _package2 = _interopRequireDefault(_package); + +var _webpackConfig = require('./webpack.config.prod'); + +var _webpackConfig2 = _interopRequireDefault(_webpackConfig); + +var _config = require('./config'); + +var _config2 = _interopRequireDefault(_config); + +var _index = require('./index.html'); + +var _index2 = _interopRequireDefault(_index); + +var _iframe = require('./iframe.html'); + +var _iframe2 = _interopRequireDefault(_iframe); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +process.env.NODE_ENV = 'production'; + +// avoid ESLint errors +var logger = console; + +_commander2.default.version(_package2.default.version).option('-s, --static-dir [dir-name]', 'Directory where to load static files from').option('-o, --output-dir [dir-name]', 'Directory where to store built files').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').parse(process.argv); + +// create output directory (and the static dir) if not exists +var outputDir = _commander2.default.outputDir || './storybook-static'; +_shelljs2.default.mkdir('-p', _path2.default.resolve(outputDir, 'static')); + +// Write both the storybook UI and IFRAME HTML files to destination path. +_fs2.default.writeFileSync(_path2.default.resolve(outputDir, 'index.html'), (0, _index2.default)()); +_fs2.default.writeFileSync(_path2.default.resolve(outputDir, 'iframe.html'), (0, _iframe2.default)()); + +// copy all static files +if (_commander2.default.staticDir) { + if (!_fs2.default.existsSync(_commander2.default.staticDir)) { + logger.error('Error: no such directory to load static files: ' + _commander2.default.staticDir); + process.exit(-1); + } + logger.log('=> Copying static files from: ' + _commander2.default.staticDir); + _shelljs2.default.cp('-r', _commander2.default.staticDir + '/', outputDir); +} + +// Build the webpack configuration using the `baseConfig` +// custom `.babelrc` file and `webpack.config.js` files +var configDir = _commander2.default.configDir || './.storybook'; +var config = (0, _config2.default)(_webpackConfig2.default, configDir); + +// compile all resources with webpack and write them to the disk +// TODO make sure this section of code does what it says it does +(0, _webpack2.default)(config).compile(function (err, stats) { + for (var filename in stats.assets) { + if (!stats.assets.hasOwnProperty(filename)) { + continue; + } + + var asset = stats.assets[filename]; + if (asset.children && asset.children.length) { + var _source = asset.children[0]._value; + var _dstPath = _path2.default.resolve(outputDir, 'static/' + filename); + _fs2.default.writeFileSync(_dstPath, _source); + continue; + } + + var source = asset._value; + var dstPath = _path2.default.resolve(outputDir, 'static/' + filename); + _fs2.default.writeFileSync(dstPath, source); + } +}); \ No newline at end of file diff --git a/dist/server/config.js b/dist/server/config.js new file mode 100644 index 000000000000..1b9670c35244 --- /dev/null +++ b/dist/server/config.js @@ -0,0 +1,75 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); + +var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +exports.default = function (baseConfig, configDir) { + var config = baseConfig; + + // if user has a .babelrc file in current directory + // use that to extend webpack configurations + if (_fs2.default.existsSync('./.babelrc')) { + var content = _fs2.default.readFileSync('./.babelrc'); + try { + var babelrc = JSON.parse(content); + config.module.loaders[0].query = babelrc; + } catch (e) { + logger.error('=> Error parsing .babelrc file: ' + e.message); + throw e; + } + } + + // Check whether a config.js file exists inside the storybook + // config directory and throw an error if it's not. + var storybookConfigPath = _path2.default.resolve(configDir, 'config.js'); + if (!_fs2.default.existsSync(storybookConfigPath)) { + var err = new Error('=> Create a storybook config file in "' + configDir + '/config.js".'); + throw err; + } + config.entry.preview.push(storybookConfigPath); + + // Check whether user has a custom webpack config file and + // return the (extended) base configuration if it's not available. + var customConfigPath = _path2.default.resolve(configDir, 'webpack.config.js'); + if (!_fs2.default.existsSync(customConfigPath)) { + return config; + } + + var customConfig = require(customConfigPath); + logger.info('=> Loading custom webpack config.'); + + return (0, _extends3.default)({}, customConfig, config, { + // We need to use our and custom plugins. + plugins: [].concat((0, _toConsumableArray3.default)(config.plugins), (0, _toConsumableArray3.default)(customConfig.plugins || [])), + module: (0, _extends3.default)({}, config.module, { + // We need to use our and custom loaders. + loaders: [].concat((0, _toConsumableArray3.default)(config.module.loaders), (0, _toConsumableArray3.default)(customConfig.module.loaders || [])) + }) + }); +}; + +var _fs = require('fs'); + +var _fs2 = _interopRequireDefault(_fs); + +var _path = require('path'); + +var _path2 = _interopRequireDefault(_path); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// avoid ESLint errors +var logger = console; + +// `baseConfig` is a webpack configuration bundled with storybook. +// React Storybook will look in the `configDir` directory +// (inside working directory) if a config path is not provided. \ No newline at end of file diff --git a/dist/server/index.js b/dist/server/index.js index 72813e97c2a5..c1bf16f178e5 100755 --- a/dist/server/index.js +++ b/dist/server/index.js @@ -1,14 +1,6 @@ #!/usr/bin/env node 'use strict'; -var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); - -var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); - -var _extends2 = require('babel-runtime/helpers/extends'); - -var _extends3 = _interopRequireDefault(_extends2); - var _webpack = require('webpack'); var _webpack2 = _interopRequireDefault(_webpack); @@ -45,6 +37,10 @@ var _webpack3 = require('./webpack.config'); var _webpack4 = _interopRequireDefault(_webpack3); +var _config = require('./config'); + +var _config2 = _interopRequireDefault(_config); + var _path = require('path'); var _path2 = _interopRequireDefault(_path); @@ -80,51 +76,15 @@ if (_commander2.default.staticDir) { } } -// add config path to the entry +// Build the webpack configuration using the `baseConfig` +// custom `.babelrc` file and `webpack.config.js` files var configDir = _commander2.default.configDir || './.storybook'; -var configDirPath = _path2.default.resolve(configDir); - -// load babelrc file. -var babelrcPath = _path2.default.resolve('./.babelrc'); -if (_fs2.default.existsSync(babelrcPath)) { - logger.info('=> Using custom .babelrc configurations.'); - var babelrcContent = _fs2.default.readFileSync(babelrcPath); - try { - var babelrc = JSON.parse(babelrcContent); - _webpack4.default.module.loaders[0].query = babelrc; - } catch (ex) { - logger.error('=> Error parsing .babelrc file: ' + ex.message); - throw ex; - } -} - -var storybookConfigPath = _path2.default.resolve(configDirPath, 'config.js'); -if (!_fs2.default.existsSync(storybookConfigPath)) { - logger.error('=> Create a storybook config file in "' + configDir + '/config.js".\n'); - process.exit(0); -} -_webpack4.default.entry.preview.push(storybookConfigPath); - -// load custom webpack configurations -var customConfigPath = _path2.default.resolve(configDirPath, 'webpack.config.js'); -var finalConfig = _webpack4.default; -if (_fs2.default.existsSync(customConfigPath)) { - var customConfig = require(customConfigPath); - logger.info('=> Loading custom webpack config.'); - finalConfig = (0, _extends3.default)({}, customConfig, _webpack4.default, { - // We need to use our and custom plugins. - plugins: [].concat((0, _toConsumableArray3.default)(_webpack4.default.plugins), (0, _toConsumableArray3.default)(customConfig.plugins || [])), - module: (0, _extends3.default)({}, _webpack4.default.module, { - // We need to use our and custom loaders. - loaders: [].concat((0, _toConsumableArray3.default)(_webpack4.default.module.loaders), (0, _toConsumableArray3.default)(customConfig.module.loaders || [])) - }) - }); -} +var config = (0, _config2.default)(_webpack4.default, configDir); -var compiler = (0, _webpack2.default)(finalConfig); +var compiler = (0, _webpack2.default)(config); var devMiddlewareOptions = { noInfo: true, - publicPath: finalConfig.output.publicPath + publicPath: config.output.publicPath }; app.use((0, _webpackDevMiddleware2.default)(compiler, devMiddlewareOptions)); app.use((0, _webpackHotMiddleware2.default)(compiler)); diff --git a/dist/server/webpack.config.prod.js b/dist/server/webpack.config.prod.js new file mode 100644 index 000000000000..d100ca5cee0c --- /dev/null +++ b/dist/server/webpack.config.prod.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _path = require('path'); + +var _path2 = _interopRequireDefault(_path); + +var _webpack = require('webpack'); + +var _webpack2 = _interopRequireDefault(_webpack); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var config = { + devtool: 'cheap-module-source-map', + entry: { + admin: [_path2.default.resolve(__dirname, '../client/init_admin')], + preview: [_path2.default.resolve(__dirname, '../client/init_preview')] + }, + output: { + // path: path.join(__dirname, 'dist'), + path: '/tmp/test', + filename: '[name].bundle.js', + publicPath: '/static/' + }, + plugins: [new _webpack2.default.optimize.OccurenceOrderPlugin()], + module: { + loaders: [{ + test: /\.jsx?$/, + loader: 'babel', + query: { presets: ['react', 'es2015', 'stage-2'] }, + exclude: [_path2.default.resolve('./node_modules'), _path2.default.resolve(__dirname, 'node_modules')], + include: [_path2.default.resolve('./'), __dirname] + }] + } +}; + +exports.default = config; \ No newline at end of file diff --git a/package.json b/package.json index 82aa181e9502..ed44984efd74 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ }, "bin": { "start-storybook": "./dist/server/index.js", - "build-storybook": "./dist/builder/build.js", + "build-storybook": "./dist/server/build.js", "storybook-server": "./dist/server/index.js" } } diff --git a/src/builder/build.js b/src/builder/build.js deleted file mode 100644 index 323f3440d287..000000000000 --- a/src/builder/build.js +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env node - -process.env.NODE_ENV = 'production'; - -import webpack from 'webpack'; -import program from 'commander'; -import path from 'path'; -import fs from 'fs'; -import shelljs from 'shelljs'; -import packageJson from '../../package.json'; -import config from './webpack.config'; -import getIndexHtml from '../server/index.html'; -import getIframeHtml from '../server/iframe.html'; - -const logger = console; - -program - .version(packageJson.version) - .option('-s, --static-dir [dir-name]', 'Directory where to load static files from') - .option('-o, --output-dir [dir-name]', 'Directory where to store built files') - .option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from') - .parse(process.argv); - -// create the output directory if not exists -const outputDir = program.outputDir || './storybook-build'; -const outputDirPath = path.resolve(outputDir); -shelljs.mkdir('-p', path.resolve(outputDirPath, 'static')); - -if (program.staticDir) { - const staticPath = path.resolve(program.staticDir); - if (fs.existsSync(staticPath)) { - logger.log(`=> Copying static files from: ${program.staticDir}`); - shelljs.cp('-r', `${staticPath}/`, outputDirPath); - } else { - logger.error(`Error: no such directory to load static files: ${staticPath}`); - process.exit(-1); - } -} - -// add config path to the entry -const configDir = program.configDir || './.storybook'; -const configDirPath = path.resolve(configDir); - -// load babelrc file. -const babelrcPath = path.resolve('./.babelrc'); -if (fs.existsSync(babelrcPath)) { - logger.info('=> Using custom .babelrc configurations.'); - const babelrcContent = fs.readFileSync(babelrcPath); - try { - const babelrc = JSON.parse(babelrcContent); - config.module.loaders[0].query = babelrc; - } catch (ex) { - logger.error(`=> Error parsing .babelrc file: ${ex.message}`); - throw ex; - } -} - -const storybookConfigPath = path.resolve(configDirPath, 'config.js'); -if (!fs.existsSync(storybookConfigPath)) { - logger.error(`=> Create a storybook config file in "${configDir}/config.js".\n`); - process.exit(0); -} -config.entry.preview.push(storybookConfigPath); - -// load custom webpack configurations -const customConfigPath = path.resolve(configDirPath, 'webpack.config.js'); -let finalConfig = config; -if (fs.existsSync(customConfigPath)) { - const customConfig = require(customConfigPath); - logger.info('=> Loading custom webpack config.'); - finalConfig = { - ...customConfig, - // We'll always load our configurations after the custom config. - // So, we'll always load the stuff we need. - ...config, - // We need to use our and custom plugins. - plugins: [ - ...config.plugins, - ...customConfig.plugins || [], - ], - module: { - ...config.module, - // We need to use our and custom loaders. - loaders: [ - ...config.module.loaders, - ...customConfig.module.loaders || [], - ], - }, - }; -} - -// write both the storybook UI and IFRAME HTML files to destination path -fs.writeFileSync(path.resolve(outputDirPath, 'index.html'), getIndexHtml()); -fs.writeFileSync(path.resolve(outputDirPath, 'iframe.html'), getIframeHtml()); - -// compile all other resources and write them to disk -// TODO this section of the code needs to be verified -// by running with a few different scenarios. -webpack(finalConfig).compile(function (err, stats) { - for (const filename in stats.assets) { - if (!stats.assets.hasOwnProperty(filename)) { - continue; - } - - const asset = stats.assets[filename]; - if (asset.children && asset.children.length) { - // TODO learn more about "RawSource" - const source = asset.children[0]._value; - const dstPath = path.resolve(outputDirPath, `static/${filename}`); - fs.writeFileSync(dstPath, source); - continue; - } - - const source = asset._value; - const dstPath = path.resolve(outputDirPath, `static/${filename}`); - fs.writeFileSync(dstPath, source); - } -}); diff --git a/src/server/build.js b/src/server/build.js new file mode 100644 index 000000000000..245237222b78 --- /dev/null +++ b/src/server/build.js @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = 'production'; + +import webpack from 'webpack'; +import program from 'commander'; +import path from 'path'; +import fs from 'fs'; +import shelljs from 'shelljs'; +import packageJson from '../../package.json'; +import baseConfig from './webpack.config.prod'; +import loadConfig from './config'; +import getIndexHtml from './index.html'; +import getIframeHtml from './iframe.html'; + +// avoid ESLint errors +const logger = console; + +program + .version(packageJson.version) + .option('-s, --static-dir [dir-name]', 'Directory where to load static files from') + .option('-o, --output-dir [dir-name]', 'Directory where to store built files') + .option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from') + .parse(process.argv); + +// create output directory (and the static dir) if not exists +const outputDir = program.outputDir || './storybook-static'; +shelljs.mkdir('-p', path.resolve(outputDir, 'static')); + +// Write both the storybook UI and IFRAME HTML files to destination path. +fs.writeFileSync(path.resolve(outputDir, 'index.html'), getIndexHtml()); +fs.writeFileSync(path.resolve(outputDir, 'iframe.html'), getIframeHtml()); + +// copy all static files +if (program.staticDir) { + if (!fs.existsSync(program.staticDir)) { + logger.error(`Error: no such directory to load static files: ${program.staticDir}`); + process.exit(-1); + } + logger.log(`=> Copying static files from: ${program.staticDir}`); + shelljs.cp('-r', `${program.staticDir}/`, outputDir); +} + +// Build the webpack configuration using the `baseConfig` +// custom `.babelrc` file and `webpack.config.js` files +const configDir = program.configDir || './.storybook'; +const config = loadConfig(baseConfig, configDir); + +// compile all resources with webpack and write them to the disk +// TODO make sure this section of code does what it says it does +webpack(config).compile(function (err, stats) { + for (const filename in stats.assets) { + if (!stats.assets.hasOwnProperty(filename)) { + continue; + } + + const asset = stats.assets[filename]; + if (asset.children && asset.children.length) { + const source = asset.children[0]._value; + const dstPath = path.resolve(outputDir, `static/${filename}`); + fs.writeFileSync(dstPath, source); + continue; + } + + const source = asset._value; + const dstPath = path.resolve(outputDir, `static/${filename}`); + fs.writeFileSync(dstPath, source); + } +}); diff --git a/src/server/config.js b/src/server/config.js new file mode 100644 index 000000000000..9581461e8eac --- /dev/null +++ b/src/server/config.js @@ -0,0 +1,64 @@ +import fs from 'fs'; +import path from 'path'; + +// avoid ESLint errors +const logger = console; + +// `baseConfig` is a webpack configuration bundled with storybook. +// React Storybook will look in the `configDir` directory +// (inside working directory) if a config path is not provided. +export default function (baseConfig, configDir) { + const config = baseConfig; + + // if user has a .babelrc file in current directory + // use that to extend webpack configurations + if (fs.existsSync('./.babelrc')) { + const content = fs.readFileSync('./.babelrc'); + try { + const babelrc = JSON.parse(content); + config.module.loaders[0].query = babelrc; + } catch (e) { + logger.error(`=> Error parsing .babelrc file: ${e.message}`); + throw e; + } + } + + // Check whether a config.js file exists inside the storybook + // config directory and throw an error if it's not. + const storybookConfigPath = path.resolve(configDir, 'config.js'); + if (!fs.existsSync(storybookConfigPath)) { + const err = new Error(`=> Create a storybook config file in "${configDir}/config.js".`); + throw err; + } + config.entry.preview.push(storybookConfigPath); + + // Check whether user has a custom webpack config file and + // return the (extended) base configuration if it's not available. + const customConfigPath = path.resolve(configDir, 'webpack.config.js'); + if (!fs.existsSync(customConfigPath)) { + return config; + } + + const customConfig = require(customConfigPath); + logger.info('=> Loading custom webpack config.'); + + return { + ...customConfig, + // We'll always load our configurations after the custom config. + // So, we'll always load the stuff we need. + ...config, + // We need to use our and custom plugins. + plugins: [ + ...config.plugins, + ...customConfig.plugins || [], + ], + module: { + ...config.module, + // We need to use our and custom loaders. + loaders: [ + ...config.module.loaders, + ...customConfig.module.loaders || [], + ], + }, + }; +} diff --git a/src/server/index.js b/src/server/index.js index bca8c5e99bc3..6bf18b5b89d2 100755 --- a/src/server/index.js +++ b/src/server/index.js @@ -10,7 +10,8 @@ import getIframeHtml from './iframe.html'; import express from 'express'; import program from 'commander'; import packageJson from '../../package.json'; -import config from './webpack.config'; +import baseConfig from './webpack.config'; +import loadConfig from './config'; import path from 'path'; import fs from 'fs'; @@ -42,62 +43,15 @@ if (program.staticDir) { } } -// add config path to the entry +// Build the webpack configuration using the `baseConfig` +// custom `.babelrc` file and `webpack.config.js` files const configDir = program.configDir || './.storybook'; -const configDirPath = path.resolve(configDir); +const config = loadConfig(baseConfig, configDir); -// load babelrc file. -const babelrcPath = path.resolve('./.babelrc'); -if (fs.existsSync(babelrcPath)) { - logger.info('=> Using custom .babelrc configurations.'); - const babelrcContent = fs.readFileSync(babelrcPath); - try { - const babelrc = JSON.parse(babelrcContent); - config.module.loaders[0].query = babelrc; - } catch (ex) { - logger.error(`=> Error parsing .babelrc file: ${ex.message}`); - throw ex; - } -} - -const storybookConfigPath = path.resolve(configDirPath, 'config.js'); -if (!fs.existsSync(storybookConfigPath)) { - logger.error(`=> Create a storybook config file in "${configDir}/config.js".\n`); - process.exit(0); -} -config.entry.preview.push(storybookConfigPath); - -// load custom webpack configurations -const customConfigPath = path.resolve(configDirPath, 'webpack.config.js'); -let finalConfig = config; -if (fs.existsSync(customConfigPath)) { - const customConfig = require(customConfigPath); - logger.info('=> Loading custom webpack config.'); - finalConfig = { - ...customConfig, - // We'll always load our configurations after the custom config. - // So, we'll always load the stuff we need. - ...config, - // We need to use our and custom plugins. - plugins: [ - ...config.plugins, - ...customConfig.plugins || [], - ], - module: { - ...config.module, - // We need to use our and custom loaders. - loaders: [ - ...config.module.loaders, - ...customConfig.module.loaders || [], - ], - }, - }; -} - -const compiler = webpack(finalConfig); +const compiler = webpack(config); const devMiddlewareOptions = { noInfo: true, - publicPath: finalConfig.output.publicPath, + publicPath: config.output.publicPath, }; app.use(webpackDevMiddleware(compiler, devMiddlewareOptions)); app.use(webpackHotMiddleware(compiler)); diff --git a/src/builder/webpack.config.js b/src/server/webpack.config.prod.js similarity index 100% rename from src/builder/webpack.config.js rename to src/server/webpack.config.prod.js