Skip to content
This repository was archived by the owner on May 6, 2024. It is now read-only.

Commit c823865

Browse files
committed
initial pass at cleaning up webpack
1 parent 4bf859c commit c823865

File tree

8 files changed

+149
-362
lines changed

8 files changed

+149
-362
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ RUN pip install -r requirements-test.txt
8787

8888
COPY . /usr/src/app
8989
RUN pip install -e .
90-
RUN node_modules/.bin/webpack --config=config/webpack.config.dev.js
90+
RUN node_modules/.bin/webpack
9191

9292
ENV REPO_ROOT /workspace/repos
9393
RUN mkdir -p $REPO_ROOT

config/env.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ const paths = require('./paths');
77
// Make sure that including paths.js after env.js will read .env variables.
88
delete require.cache[require.resolve('./paths')];
99

10-
const NODE_ENV = process.env.NODE_ENV;
11-
if (!NODE_ENV) {
12-
throw new Error('The NODE_ENV environment variable is required but was not specified.');
13-
}
10+
const NODE_ENV = process.env.NODE_ENV || 'development';
1411

1512
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
1613
var dotenvFiles = [

config/webpack.config.dev.js renamed to config/webpack.config.js

Lines changed: 143 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const path = require('path');
55
const webpack = require('webpack');
66
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
77
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
8+
const ExtractTextPlugin = require('extract-text-webpack-plugin');
9+
const ManifestPlugin = require('webpack-manifest-plugin');
10+
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
811
const eslintFormatter = require('react-dev-utils/eslintFormatter');
912
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
1013
const getClientEnvironment = require('./env');
@@ -20,26 +23,149 @@ const publicUrl = '';
2023
// Get environment variables to inject into our app.
2124
const env = getClientEnvironment(publicUrl);
2225

26+
// Note: defined here because it will be used more than once.
27+
const cssFilename = 'css/[name].css';
28+
29+
const isProd = env.stringified['process.env'].NODE_ENV === '"production"';
30+
31+
function getPlugins() {
32+
let plugins = [];
33+
34+
// Add module names to factory functions so they appear in browser profiler.
35+
!isProd && plugins.push(new webpack.NamedModulesPlugin());
36+
37+
// Makes some environment variables available to the JS code, for example:
38+
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
39+
plugins.push(new webpack.DefinePlugin(env.stringified));
40+
41+
// This is necessary to emit hot updates (currently CSS only):
42+
!isProd && plugins.push(new webpack.HotModuleReplacementPlugin());
43+
44+
// Watcher doesn't work well if you mistype casing in a path so we use
45+
// a plugin that prints an error when you attempt to do this.
46+
// See https://github.com/facebookincubator/create-react-app/issues/240
47+
!isProd && plugins.push(new CaseSensitivePathsPlugin());
48+
49+
// If you require a missing module and then `npm install` it, you still have
50+
// to restart the development server for Webpack to discover it. This plugin
51+
// makes the discovery automatic so you don't have to restart.
52+
// See https://github.com/facebookincubator/create-react-app/issues/186
53+
!isProd && plugins.push(new WatchMissingNodeModulesPlugin(paths.appNodeModules));
54+
55+
// optimize out highlight.js languages we dont need
56+
plugins.push(
57+
new webpack.ContextReplacementPlugin(
58+
/highlight\.js\/lib\/languages$/,
59+
new RegExp(`^./(${['diff'].join('|')})$`)
60+
)
61+
);
62+
63+
// Moment.js is an extremely popular library that bundles large locale files
64+
// by default due to how Webpack interprets its code. This is a practical
65+
// solution that requires the user to opt into importing specific locales.
66+
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
67+
// You can remove this if you don't use Moment.js:
68+
plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));
69+
70+
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
71+
plugins.push(
72+
new ExtractTextPlugin({
73+
filename: cssFilename
74+
})
75+
);
76+
77+
// Generate a manifest file which contains a mapping of all asset filenames
78+
// to their corresponding output file so that tools can pick it up without
79+
// having to parse `index.html`.
80+
isProd &&
81+
plugins.push(
82+
new ManifestPlugin({
83+
fileName: 'asset-manifest.json'
84+
})
85+
);
86+
87+
// Generate a service worker script that will precache, and keep up to date,
88+
// the HTML & assets that are part of the Webpack build.
89+
isProd &&
90+
plugins.push(
91+
new SWPrecacheWebpackPlugin({
92+
// By default, a cache-busting query parameter is appended to requests
93+
// used to populate the caches, to ensure the responses are fresh.
94+
// If a URL is already hashed by Webpack, then there is no concern
95+
// about it being stale, and the cache-busting can be skipped.
96+
dontCacheBustUrlsMatching: /\.\w{8}\./,
97+
filename: 'service-worker.js',
98+
logger(message) {
99+
if (message.indexOf('Total precache size is') === 0) {
100+
// This message occurs for every build and is a bit too noisy.
101+
return;
102+
}
103+
if (message.indexOf('Skipping static resource') === 0) {
104+
// This message obscures real errors so we ignore it.
105+
// https://github.com/facebookincubator/create-react-app/issues/2612
106+
return;
107+
}
108+
console.log(message);
109+
},
110+
minify: true,
111+
// For unknown URLs, fallback to the index page
112+
navigateFallback: publicUrl + '/index.html',
113+
// Ignores URLs starting from /__ (useful for Firebase):
114+
// https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
115+
navigateFallbackWhitelist: [/^(?!\/__).*/],
116+
// Don't precache sourcemaps (they're large) and build asset manifest:
117+
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/]
118+
})
119+
);
120+
121+
// Minify the code.
122+
isProd &&
123+
plugins.push(
124+
new webpack.optimize.UglifyJsPlugin({
125+
compress: {
126+
warnings: false,
127+
// Disabled because of an issue with Uglify breaking seemingly valid code:
128+
// https://github.com/facebookincubator/create-react-app/issues/2376
129+
// Pending further investigation:
130+
// https://github.com/mishoo/UglifyJS2/issues/2011
131+
comparisons: false
132+
},
133+
output: {
134+
comments: false,
135+
// Turned on because emoji and regex is not minified properly using default
136+
// https://github.com/facebookincubator/create-react-app/issues/2488
137+
ascii_only: true
138+
},
139+
sourceMap: true
140+
})
141+
);
142+
return plugins;
143+
}
144+
145+
function getEntry() {
146+
let entry = [];
147+
// We ship a few polyfills by default:
148+
entry.push(require.resolve('./polyfills'));
149+
// Errors should be considered fatal in development
150+
!isProd && entry.push(require.resolve('react-error-overlay'));
151+
// Finally, this is your app's code:
152+
// We include the app code last so that if there is a runtime error during
153+
// initialization
154+
entry.push(paths.appIndexJs);
155+
return entry;
156+
}
157+
23158
// This is the development configuration.
24159
// It is focused on developer experience and fast rebuilds.
25160
// The production configuration is different and lives in a separate file.
26161
module.exports = {
27162
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
28163
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
29-
devtool: 'cheap-module-source-map',
164+
devtool: isProd ? 'source-map' : 'cheap-module-source-map',
30165
// These are the "entry points" to our application.
31166
// This means they will be the "root" imports that are included in JS bundle.
32167
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
33-
entry: [
34-
// We ship a few polyfills by default:
35-
require.resolve('./polyfills'),
36-
// Errors should be considered fatal in development
37-
require.resolve('react-error-overlay'),
38-
// Finally, this is your app's code:
39-
paths.appIndexJs
40-
// We include the app code last so that if there is a runtime error during
41-
// initialization
42-
],
168+
entry: getEntry(),
43169
output: {
44170
// Next line is not used in dev but WebpackDevServer crashes without it:
45171
path: paths.appBuild,
@@ -131,7 +257,7 @@ module.exports = {
131257
],
132258
loader: require.resolve('file-loader'),
133259
options: {
134-
name: 'media/[name].[hash:8].[ext]'
260+
name: 'media/[name].[ext]'
135261
}
136262
},
137263
// "url" loader works like "file" loader except that it embeds assets
@@ -142,7 +268,7 @@ module.exports = {
142268
loader: require.resolve('url-loader'),
143269
options: {
144270
limit: 10000,
145-
name: 'media/[name].[hash:8].[ext]'
271+
name: 'media/[name].[ext]'
146272
}
147273
},
148274
// Process JS with Babel.
@@ -154,7 +280,8 @@ module.exports = {
154280
// This is a feature of `babel-loader` for webpack (not Babel itself).
155281
// It enables caching results in ./node_modules/.cache/babel-loader/
156282
// directory for faster rebuilds.
157-
cacheDirectory: true
283+
cacheDirectory: !isProd,
284+
compact: isProd
158285
}
159286
},
160287
// "postcss" loader applies autoprefixer to our CSS.
@@ -198,35 +325,7 @@ module.exports = {
198325
// Remember to add the new extension(s) to the "file" loader exclusion list.
199326
]
200327
},
201-
plugins: [
202-
// Add module names to factory functions so they appear in browser profiler.
203-
new webpack.NamedModulesPlugin(),
204-
// Makes some environment variables available to the JS code, for example:
205-
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
206-
new webpack.DefinePlugin(env.stringified),
207-
// This is necessary to emit hot updates (currently CSS only):
208-
new webpack.HotModuleReplacementPlugin(),
209-
// Watcher doesn't work well if you mistype casing in a path so we use
210-
// a plugin that prints an error when you attempt to do this.
211-
// See https://github.com/facebookincubator/create-react-app/issues/240
212-
new CaseSensitivePathsPlugin(),
213-
// If you require a missing module and then `npm install` it, you still have
214-
// to restart the development server for Webpack to discover it. This plugin
215-
// makes the discovery automatic so you don't have to restart.
216-
// See https://github.com/facebookincubator/create-react-app/issues/186
217-
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
218-
// Moment.js is an extremely popular library that bundles large locale files
219-
// by default due to how Webpack interprets its code. This is a practical
220-
// solution that requires the user to opt into importing specific locales.
221-
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
222-
// You can remove this if you don't use Moment.js:
223-
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
224-
// optimize out highlight.js languages we dont need
225-
new webpack.ContextReplacementPlugin(
226-
/highlight\.js\/lib\/languages$/,
227-
new RegExp(`^./(${['diff'].join('|')})$`)
228-
)
229-
],
328+
plugins: getPlugins(),
230329
// Some libraries import Node modules but don't use them in the browser.
231330
// Tell Webpack to provide empty mocks for them so importing them works.
232331
node: {
@@ -239,6 +338,6 @@ module.exports = {
239338
// splitting or minification in interest of speed. These warnings become
240339
// cumbersome.
241340
performance: {
242-
hints: false
341+
hints: isProd
243342
}
244343
};

0 commit comments

Comments
 (0)