Skip to content

Commit 7a9eea7

Browse files
committed
Update webpack configuration for proper vendor chunking, add dotenv to manage env vars, add semantic-ui
1 parent 77a5bc6 commit 7a9eea7

File tree

10 files changed

+627
-391
lines changed

10 files changed

+627
-391
lines changed

.env.example

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Server-side application settings
2+
# The main port to run the server on
3+
APPLICATION_PORT=3000
4+
5+
# The primary asset host for JS, CSS, and images. This can be changed to a CDN
6+
# URL. If serving assets locally, it should be the same as WEBPACK_OUTPUT_PATH
7+
# below. This env variable only takes effect in production mode.
8+
ASSET_HOST=/dist
9+
10+
# The output path for webpack builds.
11+
WEBPACK_OUTPUT_PATH=/dist
12+
13+
# Settings for webpack-dev-server.
14+
DEV_SERVER_PORT=3001
15+
DEV_SERVER_HOSTNAME=localhost

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.env
12
node_modules
23
npm-debug.log*
34
.DS_Store

client/vendor.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Include all Vendor CSS here. It will be bundled as vendor.css.
2+
import 'semantic-ui-css/semantic.min.css';

package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@
130130
"compression-webpack-plugin": "^0.4.0",
131131
"css-loader": "^0.28.0",
132132
"css-modules-require-hook": "^4.0.6",
133+
"dotenv": "^4.0.0",
134+
"dotenv-safe": "^4.0.4",
135+
"dotenv-webpack": "^1.5.0",
133136
"expose-loader": "^0.7.3",
134137
"express": "^4.15.2",
135138
"extract-text-webpack-plugin": "^2.1.0",
@@ -153,10 +156,14 @@
153156
"redux-logger": "^3.0.1",
154157
"resolve-url-loader": "^2.0.2",
155158
"sass-loader": "^6.0.3",
159+
"sass-resources-loader": "^1.2.1",
160+
"semantic-ui-css": "^2.2.10",
161+
"semantic-ui-react": "^0.70.0",
156162
"serve-static": "^1.12.1",
157163
"style-loader": "^0.18.2",
158164
"url-loader": "^0.5.8",
159165
"webpack": "^3.0.0",
166+
"webpack-bundle-analyzer": "^2.8.2",
160167
"webpack-isomorphic-tools": "^3.0.2"
161168
}
162169
}

webpack/base.js

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,47 @@
1+
require('dotenv-safe').load();
2+
13
import path from 'path';
24
import webpack from 'webpack';
35
import mapValues from 'lodash/mapValues';
46
import isomorphicConfig from './isomorphic';
57
import IsomorphicPlugin from 'webpack-isomorphic-tools/plugin';
6-
import { OUTPUT_PATH, ASSET_HOST, RESOLVE_PATHS } from './constants';
8+
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
9+
import Dotenv from 'dotenv-webpack';
10+
import {
11+
ANALYZE, NODE_ENV, WEBPACK_OUTPUT_PATH, ASSET_URL, RESOLVE_PATHS
12+
} from './constants';
713

8-
const isDev = process.env.NODE_ENV === 'development';
9-
const isProd = process.env.NODE_ENV === 'production';
14+
const isDev = NODE_ENV === 'development';
1015
const isomorphicPlugin = new IsomorphicPlugin(isomorphicConfig).development(isDev);
1116

17+
const plugins = [
18+
isomorphicPlugin,
19+
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en|es/),
20+
new Dotenv({ safe: true }),
21+
new webpack.DefinePlugin({
22+
'process.env': {
23+
'NODE_ENV': JSON.stringify(NODE_ENV)
24+
}
25+
})
26+
];
27+
28+
if (ANALYZE) { plugins.push(new BundleAnalyzerPlugin()); }
29+
1230
export default {
1331
context: path.resolve(__dirname, '..'),
1432
entry: {
1533
vendor: [
16-
'babel-polyfill',
17-
'classnames',
18-
'history',
19-
'lodash',
20-
'react',
21-
'react-dom',
22-
'react-redux',
23-
'react-router',
24-
'react-router-redux',
25-
'redux'
34+
// Vendor CSS
35+
'./client/vendor'
2636
],
2737
app: [
2838
'./client/index'
2939
]
3040
},
3141
output: {
32-
path: path.join(__dirname, ('../' + OUTPUT_PATH)),
42+
path: path.join(__dirname, ('../' + WEBPACK_OUTPUT_PATH)),
3343
filename: '[name].js',
34-
publicPath: ASSET_HOST
44+
publicPath: `${ASSET_URL}/`
3545
},
3646
resolve: {
3747
extensions: ['.js', '.jsx', '.scss'],
@@ -69,18 +79,5 @@ export default {
6979
}
7080
]
7181
},
72-
plugins: [
73-
isomorphicPlugin,
74-
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en|es/),
75-
new webpack.DefinePlugin({
76-
'process.env': {
77-
'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
78-
}
79-
}),
80-
new webpack.optimize.CommonsChunkPlugin({
81-
name: 'vendor',
82-
filename: `vendor${isProd ? '.[hash]' : ''}.js`,
83-
minChunks: Infinity
84-
})
85-
]
82+
plugins
8683
};

webpack/constants.js

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,22 @@
1-
/* The webpack dev server's port to use
1+
/* The following are environment variables imported from .env, and their
2+
* defaults. Here, we destructure them from process.env and then export them as
3+
* constants.
24
*/
3-
export const DEV_SERVER_PORT = process.env.DEV_SERVER_PORT || 3001;
5+
export const {
6+
NODE_ENV, DEV_SERVER_PORT, DEV_SERVER_HOSTNAME, WEBPACK_OUTPUT_PATH,
7+
ASSET_HOST, ASSET_PATH, ANALYZE
8+
} = process.env;
49

5-
/* The hostname to use for the webpack dev server
6-
*/
7-
export const DEV_SERVER_HOSTNAME = process.env.DEV_SERVER_HOSTNAME || 'localhost';
8-
9-
/* The URL of the dev server including the hostname and port
10-
*/
10+
// The URL of the dev server including the hostname and port
1111
export const DEV_SERVER_HOST_URL = `http://${DEV_SERVER_HOSTNAME}:${DEV_SERVER_PORT}`;
1212

13-
/* The output path of the completed webpack build
14-
*/
15-
export const OUTPUT_PATH = process.env.OUTPUT_PATH || 'dist/';
16-
17-
/* The asset host to use inside the built webpack files. In product, set the
18-
* ASSET_HOST environment variable.
19-
*/
20-
export const ASSET_HOST = (
21-
process.env.NODE_ENV === 'production'
22-
? process.env.ASSET_HOST || '/dist/'
23-
: process.env.ASSET_HOST || (DEV_SERVER_HOST_URL + '/' + OUTPUT_PATH)
24-
);
13+
// The asset host to use for webpack files. In development, we will always use
14+
// the dev server's URL.
15+
export const ASSET_URL = (
16+
NODE_ENV === 'development'
17+
? `${DEV_SERVER_HOST_URL}${WEBPACK_OUTPUT_PATH}`
18+
: ASSET_HOST
19+
);
2520

2621
/* The identifier to use for css-modules.
2722
*/
@@ -43,6 +38,7 @@ export const RESOLVE_PATHS = {
4338
constants: 'common/js/constants',
4439
css: 'common/css',
4540
fonts: 'common/fonts',
41+
gql: 'common/gql',
4642
images: 'common/images',
4743
layouts: 'common/layouts',
4844
lib: 'common/js/lib',
@@ -52,3 +48,28 @@ export const RESOLVE_PATHS = {
5248
selectors: 'common/js/selectors',
5349
store: 'common/js/store'
5450
};
51+
52+
// Loader options to use for .scss files. This is here to avoid repetition
53+
// between different webpack config files.
54+
export const SCSS_LOADERS = {
55+
fallback: 'style-loader',
56+
use: [
57+
{
58+
loader: 'css-loader',
59+
options: {
60+
modules: true,
61+
minimize: false,
62+
importLoaders: 1,
63+
localIdentName: CSS_MODULES_IDENTIFIER
64+
}
65+
},
66+
{ loader: 'postcss-loader' },
67+
{ loader: 'sass-loader' },
68+
{
69+
loader: 'sass-resources-loader',
70+
options: {
71+
resources: './common/css/utils/*.scss'
72+
}
73+
}
74+
]
75+
};

webpack/development.hot.js

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
/* eslint-disable no-console */
2-
import { DEV_SERVER_PORT, DEV_SERVER_HOSTNAME, DEV_SERVER_HOST_URL, CSS_MODULES_IDENTIFIER } from './constants';
2+
import { DEV_SERVER_PORT, DEV_SERVER_HOSTNAME, DEV_SERVER_HOST_URL, SCSS_LOADERS } from './constants';
33
import WebpackDevServer from 'webpack-dev-server';
4-
import path from 'path';
54
import webpack from 'webpack';
65
import baseConfig from './base';
7-
import packageJson from '../package.json';
86

97
// Webpack Entry Point for dev server
108
const entry = [
@@ -15,6 +13,11 @@ const entry = [
1513

1614
// Additional plugins
1715
const plugins = [
16+
new webpack.optimize.CommonsChunkPlugin({
17+
name: 'vendor',
18+
filename: '[name].js',
19+
minChunks: module => /node_modules/.test(module.resource)
20+
}),
1821
new webpack.HotModuleReplacementPlugin(),
1922
new webpack.NoEmitOnErrorsPlugin(),
2023
new webpack.NamedModulesPlugin()
@@ -24,33 +27,13 @@ const plugins = [
2427
const loaders = [
2528
{
2629
test: /\.css$/,
27-
use: [
28-
'style-loader',
29-
{
30-
loader: 'css-loader',
31-
options: {
32-
modules: true,
33-
importLoaders: 3,
34-
localIdentName: CSS_MODULES_IDENTIFIER
35-
}
36-
},
37-
'postcss-loader'
38-
]
30+
use: [ 'style-loader', 'css-loader' ]
3931
},
4032
{
4133
test: /\.scss$/,
4234
use: [
4335
'style-loader',
44-
{
45-
loader: 'css-loader',
46-
options: {
47-
modules: true,
48-
importLoaders: 3,
49-
localIdentName: CSS_MODULES_IDENTIFIER
50-
}
51-
},
52-
'postcss-loader',
53-
'sass-loader'
36+
...SCSS_LOADERS.use
5437
]
5538
}
5639
];
@@ -64,7 +47,8 @@ const config = Object.assign({}, baseConfig, {
6447
]
6548
}),
6649
plugins: [
67-
...baseConfig.plugins,
50+
// don't use the first plugin (isomorphic plugin)
51+
...baseConfig.plugins.slice(1),
6852
...plugins
6953
],
7054
module: Object.assign({}, baseConfig.module, {

webpack/development.js

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,50 @@
11
import baseConfig from './base';
2+
import webpack from 'webpack';
23
import ExtractTextPlugin from 'extract-text-webpack-plugin';
3-
import { CSS_MODULES_IDENTIFIER } from './constants';
4+
import { SCSS_LOADERS } from './constants';
45

56
const plugins = [
6-
new ExtractTextPlugin('styles.css')
7+
new ExtractTextPlugin('[name].css'),
8+
new webpack.optimize.CommonsChunkPlugin({
9+
name: 'vendor',
10+
filename: '[name].js',
11+
minChunks: module => /node_modules/.test(module.resource)
12+
}),
13+
new webpack.optimize.ModuleConcatenationPlugin()
714
];
815

916
const loaders = [
1017
{
1118
test: /\.jsx$|\.js$/,
1219
loader: 'babel-loader',
13-
exclude: /node_modules/
20+
exclude: /node_modules/,
21+
options: {
22+
presets: [
23+
[ 'es2015', { modules: false } ]
24+
]
25+
}
1426
},
1527
{
16-
test: /\.(css|scss)$/,
28+
test: /\.css$/,
1729
loader: ExtractTextPlugin.extract({
1830
fallback: 'style-loader',
19-
use: [
20-
{
21-
loader: 'css-loader',
22-
options: {
23-
modules: true,
24-
minimize: false,
25-
importLoaders: 1,
26-
localIdentName: CSS_MODULES_IDENTIFIER
27-
}
28-
},
29-
{ loader: 'postcss-loader' },
30-
{ loader: 'sass-loader' }
31-
]
31+
use: [ 'css-loader' ]
3232
})
33+
},
34+
{
35+
test: /\.scss$/,
36+
loader: ExtractTextPlugin.extract(SCSS_LOADERS)
3337
}
3438
];
3539

3640
export default {
3741
...baseConfig,
42+
entry: {
43+
...baseConfig.entry,
44+
vendor: [
45+
...baseConfig.entry.vendor
46+
]
47+
},
3848
devtool: 'source-map',
3949
plugins: [
4050
...baseConfig.plugins,

0 commit comments

Comments
 (0)