CHANGE webpack setup to be aligned with other apps

This commit is contained in:
Norbert de Langen 2017-09-12 23:21:26 +02:00
parent 6695d953a6
commit aa1e6b1ca9
10 changed files with 140 additions and 170 deletions

View File

@ -54,6 +54,7 @@
"file-loader": "^0.11.1",
"find-cache-dir": "^1.0.0",
"global": "^4.3.2",
"html-webpack-plugin": "^2.30.1",
"json-loader": "^0.5.4",
"json-stringify-safe": "^5.0.1",
"json5": "^0.5.1",

View File

@ -1,4 +1,4 @@
import { window } from 'global';
import { window, navigator } from 'global';
import { createStore } from 'redux';
import addons from '@storybook/addons';
import createChannel from '@storybook/channel-postmessage';
@ -12,7 +12,6 @@ import { selectStory } from './actions';
import reducer from './reducer';
// check whether we're running on node/browser
const { navigator } = global;
const isBrowser =
navigator &&
navigator.userAgent !== 'storyshots' &&

View File

@ -23,11 +23,15 @@ export function loadEnv(options = {}) {
PUBLIC_URL: JSON.stringify(options.production ? '.' : ''),
};
Object.keys(process.env).filter(name => /^STORYBOOK_/.test(name)).forEach(name => {
env[name] = JSON.stringify(process.env[name]);
});
Object.keys(process.env)
.filter(name => /^STORYBOOK_/.test(name))
.forEach(name => {
env[name] = JSON.stringify(process.env[name]);
});
return {
'process.env': env,
};
}
export const getConfigDir = () => process.env.SBCONFIG_CONFIG_DIR || './.storybook';

View File

@ -1,9 +1,20 @@
import path from 'path';
import webpack from 'webpack';
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import WatchMissingNodeModulesPlugin from './WatchMissingNodeModulesPlugin';
import { nodeModulesPaths, loadEnv, nodePaths, includePaths, excludePaths } from './utils';
import {
getConfigDir,
includePaths,
excludePaths,
nodeModulesPaths,
loadEnv,
nodePaths,
} from './utils';
import babelLoaderConfig from './babel';
import { getPreviewHeadHtml, getManagerHeadHtml } from '../utils';
import { version } from '../../../package.json';
export default function() {
const config = {
@ -22,6 +33,23 @@ export default function() {
publicPath: '/',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
chunks: ['manager'],
data: {
managerHead: getManagerHeadHtml(getConfigDir()),
version,
},
template: require.resolve('../index.html.ejs'),
}),
new HtmlWebpackPlugin({
filename: 'iframe.html',
excludeChunks: ['manager'],
data: {
previewHead: getPreviewHeadHtml(getConfigDir()),
},
template: require.resolve('../iframe.html.ejs'),
}),
new webpack.DefinePlugin(loadEnv()),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),

View File

@ -1,7 +1,10 @@
import path from 'path';
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import babelLoaderConfig from './babel.prod';
import { includePaths, excludePaths, loadEnv, nodePaths } from './utils';
import { getConfigDir, includePaths, excludePaths, loadEnv, nodePaths } from './utils';
import { getPreviewHeadHtml, getManagerHeadHtml } from '../utils';
import { version } from '../../../package.json';
export default function() {
const entries = {
@ -23,6 +26,23 @@ export default function() {
publicPath: '',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
chunks: ['manager'],
data: {
managerHead: getManagerHeadHtml(getConfigDir()),
version,
},
template: require.resolve('../index.html.ejs'),
}),
new HtmlWebpackPlugin({
filename: 'iframe.html',
excludeChunks: ['manager'],
data: {
previewHead: getPreviewHeadHtml(getConfigDir()),
},
template: require.resolve('../iframe.html.ejs'),
}),
new webpack.DefinePlugin(loadEnv({ production: true })),
new webpack.optimize.UglifyJsPlugin({
compress: {
@ -35,6 +55,10 @@ export default function() {
screw_ie8: true,
},
}),
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)@angular/,
path.resolve(__dirname, '../src')
),
],
module: {
rules: [
@ -45,6 +69,15 @@ export default function() {
include: includePaths,
exclude: excludePaths,
},
{
test: /\.ts?$/,
loaders: [require.resolve('ts-loader'), require.resolve('angular2-template-loader')],
},
{
test: /\.(html|css)$/,
loader: 'raw-loader',
exclude: /\.async\.(html|css)$/,
},
],
},
resolve: {

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base target="_parent">
<script>
if (window.parent !== window) {
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
}
</script>
<title>Storybook</title>
<%= htmlWebpackPlugin.options.data.previewHead %>
</head>
<body>
<my-app></my-app>
</body>
</html>

View File

@ -1,72 +0,0 @@
import url from 'url';
// assets.preview will be:
// - undefined
// - string e.g. 'static/preview.9adbb5ef965106be1cc3.bundle.js'
// - array of strings e.g.
// [ 'static/preview.9adbb5ef965106be1cc3.bundle.js',
// 'preview.0d2d3d845f78399fd6d5e859daa152a9.css',
// 'static/preview.9adbb5ef965106be1cc3.bundle.js.map',
// 'preview.0d2d3d845f78399fd6d5e859daa152a9.css.map' ]
const urlsFromAssets = assets => {
if (!assets) {
return {
js: ['static/preview.bundle.js'],
css: [],
};
}
const urls = {
js: [],
css: [],
};
const re = /.+\.(\w+)$/;
Object.keys(assets)
// Don't load the manager script in the iframe
.filter(key => key !== 'manager')
.forEach(key => {
const asset = assets[key];
if (typeof asset === 'string') {
urls[re.exec(asset)[1]].push(asset);
} else {
const assetUrl = asset.find(u => re.exec(u)[1] !== 'map');
urls[re.exec(assetUrl)[1]].push(assetUrl);
}
});
return urls;
};
export default function({ assets, publicPath, headHtml }) {
const urls = urlsFromAssets(assets);
const cssTags = urls.css
.map(u => `<link rel='stylesheet' type='text/css' href='${url.resolve(publicPath, u)}'>`)
.join('\n');
const scriptTags = urls.js
.map(u => `<script src="${url.resolve(publicPath, u)}"></script>`)
.join('\n');
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
if (window.parent !== window) {
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
}
</script>
<title>Storybook</title>
${headHtml}
${cssTags}
</head>
<body>
<my-app></my-app>
${scriptTags}
</body>
</html>
`;
}

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="storybook-version" content="<%= htmlWebpackPlugin.options.data.version %>">
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
<title>Storybook</title>
<style>
/*
When resizing panels, the drag event breaks if the cursor
moves over the iframe. Add the 'dragging' class to the body
at drag start and remove it when the drag ends.
*/
.dragging iframe {
pointer-events: none;
}
/* Styling the fuzzy search box placeholders */
.searchBox::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: #ddd;
font-size: 16px;
}
.searchBox::-moz-placeholder { /* Firefox 19+ */
color: #ddd;
font-size: 16px;
}
.searchBox:focus{
border-color: #EEE !important;
}
.btn:hover{
background-color: #eee
}
</style>
<%= htmlWebpackPlugin.options.data.managerHead %>
</head>
<body style="margin: 0;">
<div id="root"></div>
</body>
</html>

View File

@ -1,79 +0,0 @@
import url from 'url';
import { version } from '../../package.json';
// assets.manager will be:
// - undefined
// - string e.g. 'static/manager.9adbb5ef965106be1cc3.bundle.js'
// - array of strings e.g.
// assets.manager will be something like:
// [ 'static/manager.c6e6350b6eb01fff8bad.bundle.js',
// 'static/manager.c6e6350b6eb01fff8bad.bundle.js.map' ]
const managerUrlsFromAssets = assets => {
if (!assets || !assets.manager) {
return {
js: 'static/manager.bundle.js',
};
}
if (typeof assets.manager === 'string') {
return {
js: assets.manager,
};
}
return {
js: assets.manager.find(filename => filename.match(/\.js$/)),
css: assets.manager.find(filename => filename.match(/\.css$/)),
};
};
export default function({ assets, publicPath, headHtml }) {
const managerUrls = managerUrlsFromAssets(assets);
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="storybook-version" content="${version}">
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
<title>Storybook</title>
<style>
/*
When resizing panels, the drag event breaks if the cursor
moves over the iframe. Add the 'dragging' class to the body
at drag start and remove it when the drag ends.
*/
.dragging iframe {
pointer-events: none;
}
/* Styling the fuzzy search box placeholders */
.searchBox::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: #ddd;
font-size: 16px;
}
.searchBox::-moz-placeholder { /* Firefox 19+ */
color: #ddd;
font-size: 16px;
}
.searchBox:focus{
border-color: #EEE !important;
}
.btn:hover{
background-color: #eee
}
</style>
${headHtml}
</head>
<body style="margin: 0;">
<div id="root"></div>
<script src="${url.resolve(publicPath, managerUrls.js)}"></script>
</body>
</html>
`;
}

View File

@ -1,12 +1,11 @@
import path from 'path';
import { Router } from 'express';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import getBaseConfig from './config/webpack.config';
import loadConfig from './config';
import getIndexHtml from './index.html';
import getIframeHtml from './iframe.html';
import { getPreviewHeadHtml, getManagerHeadHtml, getMiddleware } from './utils';
import { getMiddleware } from './utils';
let webpackResolve = () => {};
let webpackReject = () => {};
@ -44,19 +43,14 @@ export default function(configDir) {
middlewareFn(router);
webpackDevMiddlewareInstance.waitUntilValid(stats => {
const data = {
publicPath: config.output.publicPath,
assets: stats.toJson().assetsByChunkName,
};
router.get('/', (req, res) => {
const headHtml = getManagerHeadHtml(configDir);
res.send(getIndexHtml({ publicPath, headHtml }));
res.set('Content-Type', 'text/html');
res.sendFile(path.join(`${__dirname}/public/index.html`));
});
router.get('/iframe.html', (req, res) => {
const headHtml = getPreviewHeadHtml(configDir);
res.send(getIframeHtml({ ...data, headHtml, publicPath }));
res.set('Content-Type', 'text/html');
res.sendFile(path.join(`${__dirname}/public/iframe.html`));
});
if (stats.toJson().errors.length) {