Skip to content

Commit 6681eee

Browse files
committed
Bake-in support for webpack DLLs #1201
1 parent 7e52e1a commit 6681eee

File tree

12 files changed

+212
-21
lines changed

12 files changed

+212
-21
lines changed

.eslintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"__SERVER__": true,
5252
"__DISABLE_SSR__": true,
5353
"__DEVTOOLS__": true,
54+
"__DLLS__": true,
5455
"socket": true,
5556
"webpackIsomorphicTools": true
5657
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ dist/
55
webpack-assets.json
66
webpack-stats.json
77
npm-debug.log
8+
.happypack
9+
webpack/dlls/manifests/*.json

bin/server.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ global.__CLIENT__ = false;
99
global.__SERVER__ = true;
1010
global.__DISABLE_SSR__ = false; // <----- DISABLES SERVER SIDE RENDERING FOR ERROR DEBUGGING
1111
global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';
12+
global.__DLLS__ = process.env.WEBPACK_DLLS === '1';
1213

1314
if (__DEVELOPMENT__) {
1415
if (!require('piping')({

karma.conf.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = function(config) {
1111

1212
files: [
1313
'./node_modules/phantomjs-polyfill/bind-polyfill.js',
14+
process.env.WEBPACK_DLLS === '1' ? './static/dist/dlls/dll__vendor.js' : null,
1415
'tests.webpack.js'
1516
],
1617

@@ -56,7 +57,8 @@ module.exports = function(config) {
5657
__CLIENT__: true,
5758
__SERVER__: false,
5859
__DEVELOPMENT__: true,
59-
__DEVTOOLS__: false // <-------- DISABLE redux-devtools HERE
60+
__DEVTOOLS__: false, // <-------- DISABLE redux-devtools HERE
61+
__DLLS__: process.env.WEBPACK_DLLS === '1'
6062
})
6163
]
6264
},

package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"start-prod": "better-npm-run start-prod",
2929
"start-prod-api": "better-npm-run start-prod-api",
3030
"build": "better-npm-run build",
31-
"postinstall": "npm run build",
31+
"build-dlls": "webpack --verbose --colors --display-error-details --config webpack/vendor.config.js",
32+
"postinstall": "npm run build && npm run build-dlls",
3233
"lint": "eslint -c .eslintrc src api",
3334
"start-dev": "better-npm-run start-dev",
3435
"start-dev-api": "better-npm-run start-dev-api",
@@ -62,7 +63,8 @@
6263
"NODE_PATH": "./src",
6364
"NODE_ENV": "development",
6465
"PORT": 3000,
65-
"APIPORT": 3030
66+
"APIPORT": 3030,
67+
"WEBPACK_DLLS": 1
6668
}
6769
},
6870
"start-dev-api": {
@@ -79,7 +81,8 @@
7981
"UV_THREADPOOL_SIZE": 100,
8082
"NODE_PATH": "./src",
8183
"PORT": 3000,
82-
"APIPORT": 3030
84+
"APIPORT": 3030,
85+
"WEBPACK_DLLS": 1
8386
}
8487
},
8588
"build": {
@@ -167,6 +170,7 @@
167170
"extract-text-webpack-plugin": "^1.0.1",
168171
"font-awesome": "^4.4.0",
169172
"font-awesome-webpack": "0.0.4",
173+
"happypack": "^2.1.1",
170174
"json-loader": "^0.5.4",
171175
"karma": "^0.13.10",
172176
"karma-cli": "^1.0.0",

src/containers/App/App.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@ import { asyncConnect } from 'redux-connect';
2828
}
2929
}])
3030
@connect(
31-
state => ({ user: state.auth.user }),
31+
state => ({
32+
notifs: state.notifs,
33+
user: state.auth.user
34+
}),
3235
{ logout, pushState: push })
3336
export default class App extends Component {
3437
static propTypes = {
3538
children: PropTypes.object.isRequired,
3639
user: PropTypes.object,
40+
notifs: PropTypes.object,
3741
logout: PropTypes.func.isRequired,
3842
pushState: PropTypes.func.isRequired
3943
};
@@ -58,7 +62,7 @@ export default class App extends Component {
5862
};
5963

6064
render() {
61-
const { user } = this.props;
65+
const { user, notifs } = this.props;
6266
const styles = require('./App.scss');
6367

6468
return (
@@ -117,13 +121,13 @@ export default class App extends Component {
117121
</Navbar>
118122

119123
<div className={styles.appContent}>
120-
<div className="container">
124+
{notifs.global && <div className="container">
121125
<Notifs
122126
className={styles.notifs}
123127
namespace="global"
124128
NotifComponent={props => <Alert bsStyle={props.kind}>{props.message}</Alert>}
125129
/>
126-
</div>
130+
</div>}
127131

128132
{this.props.children}
129133
</div>

src/helpers/Html.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export default class Html extends Component {
5252
dangerouslySetInnerHTML={{ __html: `window.__data=${serialize(store.getState())};` }}
5353
charSet="UTF-8"
5454
/>
55+
{__DLLS__ && <script key="dlls__vendor" src="/dist/dlls/dll__vendor.js" charSet="UTF-8" />}
5556
<script src={assets.javascript.main} charSet="UTF-8" />
5657

5758
{/* (will be present only in development mode) */}

webpack/dev.config.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var webpack = require('webpack');
77
var assetsPath = path.resolve(__dirname, '../static/dist');
88
var host = (process.env.HOST || 'localhost');
99
var port = (+process.env.PORT + 1) || 3001;
10+
var { installVendorDLL, createSourceLoader, createHappyPlugin } = require('./helpers');
1011

1112
// https://github.com/halt-hammerzeit/webpack-isomorphic-tools
1213
var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');
@@ -61,7 +62,7 @@ reactTransform[1].transforms.push({
6162
locals: ['module']
6263
});
6364

64-
module.exports = {
65+
var webpackConfig = module.exports = {
6566
devtool: 'inline-source-map',
6667
context: path.resolve(__dirname, '..'),
6768
entry: {
@@ -80,20 +81,27 @@ module.exports = {
8081
},
8182
module: {
8283
loaders: [
83-
{
84+
createSourceLoader({
85+
happy: { id: 'jsx' },
8486
test: /\.jsx?$/,
8587
exclude: /node_modules/,
86-
loaders: ['babel?' + JSON.stringify(babelLoaderQuery), 'eslint-loader']
87-
},
88-
{ test: /\.json$/, loader: 'json-loader' },
89-
{
88+
loaders: ['babel?' + JSON.stringify(babelLoaderQuery), 'eslint-loader'],
89+
}),
90+
createSourceLoader({
91+
happy: { id: 'json' },
92+
test: /\.json$/,
93+
loader: 'json-loader',
94+
}),
95+
createSourceLoader({
96+
happy: { id: 'less' },
9097
test: /\.less$/,
91-
loader: 'style!css?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!less?outputStyle=expanded&sourceMap'
92-
},
93-
{
98+
loader: 'style!css?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!less?outputStyle=expanded&sourceMap',
99+
}),
100+
createSourceLoader({
101+
happy: { id: 'sass' },
94102
test: /\.scss$/,
95-
loader: 'style!css?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap'
96-
},
103+
loader: 'style!css?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap',
104+
}),
97105
{ test: /\.woff2?(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/font-woff" },
98106
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
99107
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
@@ -119,6 +127,15 @@ module.exports = {
119127
__DEVELOPMENT__: true,
120128
__DEVTOOLS__: true // <-------- DISABLE redux-devtools HERE
121129
}),
122-
webpackIsomorphicToolsPlugin.development()
130+
webpackIsomorphicToolsPlugin.development(),
131+
132+
createHappyPlugin('jsx'),
133+
createHappyPlugin('json'),
134+
createHappyPlugin('less'),
135+
createHappyPlugin('sass'),
123136
]
124137
};
138+
139+
if (process.env.WEBPACK_DLLS === '1') {
140+
installVendorDLL(webpackConfig, 'vendor');
141+
}

webpack/dlls/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Files in this directory are auto-generated. DO NOT EDIT!

webpack/helpers.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
var path = require('path');
2+
var projectRootPath = path.resolve(__dirname, '../');
3+
var webpack = require('webpack');
4+
var HappyPack = require('happypack');
5+
var happyThreadPool = HappyPack.ThreadPool({ size: 5 });
6+
7+
module.exports = {
8+
createSourceLoader,
9+
createHappyPlugin,
10+
installVendorDLL
11+
};
12+
13+
// restrict loader to files under /src
14+
function createSourceLoader(spec) {
15+
return Object.keys(spec).reduce(function (x, key) {
16+
x[key] = spec[key];
17+
18+
return x;
19+
}, {
20+
include: [path.resolve(__dirname, '../src')]
21+
});
22+
}
23+
24+
function createHappyPlugin(id) {
25+
return new HappyPack({
26+
id: id,
27+
threadPool: happyThreadPool,
28+
29+
// disable happypack with HAPPY=0
30+
enabled: process.env.HAPPY !== '0',
31+
32+
// disable happypack caching with HAPPY_CACHE=0
33+
cache: process.env.HAPPY_CACHE !== '0',
34+
35+
// make happypack more verbose with HAPPY_VERBOSE=1
36+
verbose: process.env.HAPPY_VERBOSE === '1',
37+
});
38+
}
39+
40+
function installVendorDLL(config, dllName) {
41+
if (process.env.WEBPACK_DLLS === '1') {
42+
var manifest = loadDLLManifest(path.join(projectRootPath, `webpack/dlls/${dllName}.json`));
43+
44+
if (manifest) {
45+
console.warn(`Webpack: will be using the ${dllName} DLL.`);
46+
47+
config.plugins.push(new webpack.DllReferencePlugin({
48+
context: projectRootPath,
49+
manifest: manifest
50+
}));
51+
}
52+
}
53+
};
54+
55+
function loadDLLManifest(filePath) {
56+
try {
57+
return require(filePath);
58+
}
59+
catch (e) {
60+
process.env.WEBPACK_DLLS = '0';
61+
62+
console.error(`========================================================================
63+
Environment Error
64+
------------------------------------------------------------------------
65+
You have requested to use webpack DLLs (env var WEBPACK_DLLS=1) but a
66+
manifest could not be found. This likely means you have forgotten to
67+
build the DLLs.
68+
You can do that by running:
69+
npm run build-dlls
70+
The request to use DLLs for this build will be ignored.`);
71+
}
72+
73+
return undefined;
74+
}

webpack/prod.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ module.exports = {
7070
__CLIENT__: true,
7171
__SERVER__: false,
7272
__DEVELOPMENT__: false,
73-
__DEVTOOLS__: false
73+
__DEVTOOLS__: false,
74+
__DLLS__: false,
7475
}),
7576

7677
// ignore dev config

webpack/vendor.config.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
var path = require('path');
2+
var webpack = require('webpack');
3+
var projectRootPath = path.resolve(__dirname, '../');
4+
5+
module.exports = {
6+
devtool: process.env.NODE_ENV === 'production' ? null : 'inline-source-map',
7+
8+
output: {
9+
path: path.join(projectRootPath, 'static/dist/dlls'),
10+
filename: 'dll__[name].js',
11+
library: 'DLL_[name]_[hash]'
12+
},
13+
14+
entry: {
15+
vendor: [
16+
'babel-polyfill',
17+
18+
// <babel-runtime>
19+
//
20+
// Generate this list using the following command against the stdout of
21+
// webpack running against the source bundle config (dev/prod.js):
22+
//
23+
// egrep -o 'babel-runtime/\S+' | sed 's/\.js$//' | sort | uniq | wc -l
24+
'babel-runtime/core-js/array/from',
25+
'babel-runtime/core-js/get-iterator',
26+
'babel-runtime/core-js/is-iterable',
27+
'babel-runtime/core-js/json/stringify',
28+
'babel-runtime/core-js/number/is-integer',
29+
'babel-runtime/core-js/number/is-safe-integer',
30+
'babel-runtime/core-js/object/define-property',
31+
'babel-runtime/core-js/object/get-own-property-descriptor',
32+
'babel-runtime/core-js/object/get-own-property-names',
33+
'babel-runtime/core-js/object/get-prototype-of',
34+
'babel-runtime/core-js/promise',
35+
'babel-runtime/helpers/create-class',
36+
'babel-runtime/helpers/createClass',
37+
'babel-runtime/helpers/defineProperty',
38+
'babel-runtime/helpers/get',
39+
'babel-runtime/helpers/possibleConstructorReturn',
40+
'babel-runtime/helpers/slicedToArray',
41+
'babel-runtime/helpers/to-consumable-array',
42+
'babel-runtime/helpers/toConsumableArray',
43+
// </babel-runtime>
44+
45+
'invariant',
46+
'multireducer',
47+
'react',
48+
'react-bootstrap',
49+
'react-dom',
50+
'react-helmet',
51+
'react-inline-css',
52+
'react-redux',
53+
'react-router',
54+
'react-router-bootstrap',
55+
'react-router-redux',
56+
'redux',
57+
'redux-connect',
58+
'redux-form',
59+
'scroll-behavior',
60+
'serialize-javascript',
61+
'socket.io-client',
62+
'superagent',
63+
'warning',
64+
]
65+
},
66+
67+
resolve: {
68+
root: path.resolve(projectRootPath, 'node_modules'),
69+
extensions: ['', '.js'],
70+
postfixes: [],
71+
},
72+
73+
plugins: [
74+
new webpack.DefinePlugin({
75+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
76+
}),
77+
78+
new webpack.DllPlugin({
79+
path: path.join(projectRootPath, 'webpack/dlls/[name].json'),
80+
name: 'DLL_[name]_[hash]'
81+
})
82+
]
83+
};

0 commit comments

Comments
 (0)