UNPKG

11.6 kBJavaScriptView Raw
1// @remove-on-eject-begin
2/**
3 * Copyright (c) 2015-present, Facebook, Inc.
4 * All rights reserved.
5 *
6 * This source code is licensed under the BSD-style license found in the
7 * LICENSE file in the root directory of this source tree. An additional grant
8 * of patent rights can be found in the PATENTS file in the same directory.
9 */
10// @remove-on-eject-end
11'use strict';
12
13const autoprefixer = require('autoprefixer');
14const webpack = require('webpack');
15const HtmlWebpackPlugin = require('html-webpack-plugin');
16const ExtractTextPlugin = require('extract-text-webpack-plugin');
17const ManifestPlugin = require('webpack-manifest-plugin');
18const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
19const paths = require('./paths');
20const getClientEnvironment = require('./env');
21
22// Webpack uses `publicPath` to determine where the app is being served from.
23// It requires a trailing slash, or the file assets will get an incorrect path.
24const publicPath = paths.servedPath;
25// Some apps do not use client-side routing with pushState.
26// For these, "homepage" can be set to "." to enable relative asset paths.
27const shouldUseRelativeAssetPaths = publicPath === './';
28// `publicUrl` is just like `publicPath`, but we will provide it to our app
29// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
30// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
31const publicUrl = publicPath.slice(0, -1);
32// Get environment variables to inject into our app.
33const env = getClientEnvironment(publicUrl);
34
35// Assert this just to be safe.
36// Development builds of React are slow and not intended for production.
37if (env.stringified['process.env'].NODE_ENV !== '"production"') {
38 throw new Error('Production builds must have NODE_ENV=production.');
39}
40
41// Note: defined here because it will be used more than once.
42const cssFilename = 'static/css/[name].[contenthash:8].css';
43
44// ExtractTextPlugin expects the build output to be flat.
45// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
46// However, our output is structured with css, js and media folders.
47// To have this structure working with relative paths, we have to use custom options.
48const extractTextPluginOptions = shouldUseRelativeAssetPaths
49 ? // Making sure that the publicPath goes back to to build folder.
50 {publicPath: Array(cssFilename.split('/').length).join('../')}
51 : {};
52
53// This is the production configuration.
54// It compiles slowly and is focused on producing a fast and minimal bundle.
55// The development configuration is different and lives in a separate file.
56module.exports = {
57 target: 'electron-renderer',
58
59 // Don't attempt to continue if there are any errors.
60 bail: true,
61 // We generate sourcemaps in production. This is slow but gives good results.
62 // You can exclude the *.map files from the build during deployment.
63 devtool: 'source-map',
64 // In production, we only want to load the polyfills and the app code.
65 entry: [require.resolve('./polyfills'), paths.appIndexJs],
66 output: {
67 // The build folder.
68 path: paths.appBuild,
69 // Generated JS file names (with nested folders).
70 // There will be one main bundle, and one file per asynchronous chunk.
71 // We don't currently advertise code splitting but Webpack supports it.
72 filename: 'static/js/[name].[chunkhash:8].js',
73 chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
74 // We inferred the "public path" (such as / or /my-project) from homepage.
75 publicPath: publicPath,
76 },
77 resolve: {
78 // This allows you to set a fallback for where Webpack should look for modules.
79 // We read `NODE_PATH` environment variable in `paths.js` and pass paths here.
80 // We placed these paths second because we want `node_modules` to "win"
81 // if there are any conflicts. This matches Node resolution mechanism.
82 // https://github.com/facebookincubator/create-react-app/issues/253
83 modules: ['node_modules', paths.appNodeModules].concat(paths.nodePaths),
84 // These are the reasonable defaults supported by the Node ecosystem.
85 // We also include JSX as a common component filename extension to support
86 // some tools, although we do not recommend using it, see:
87 // https://github.com/facebookincubator/create-react-app/issues/290
88 extensions: ['.js', '.json', '.jsx'],
89 alias: {
90 // Support React Native Web
91 // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
92 'react-native': 'react-native-web',
93 },
94 },
95 // @remove-on-eject-begin
96 // Resolve loaders (webpack plugins for CSS, images, transpilation) from the
97 // directory of `react-scripts` itself rather than the project directory.
98 resolveLoader: {
99 modules: [
100 paths.ownNodeModules,
101 // Lerna hoists everything, so we need to look in our app directory
102 paths.appNodeModules,
103 ],
104 },
105 // @remove-on-eject-end
106 module: {
107 rules: [
108 // Disable require.ensure as it's not a standard language feature.
109 {parser: {requireEnsure: false}},
110 // First, run the linter.
111 // It's important to do this before Babel processes the JS.
112 {
113 test: /\.(js|jsx)$/,
114 enforce: 'pre',
115 use: [
116 {
117 // @remove-on-eject-begin
118 // Point ESLint to our predefined config.
119 options: {
120 // TODO: consider separate config for production,
121 // e.g. to enable no-console and no-debugger only in production.
122 baseConfig: {
123 extends: ['react-app'],
124 },
125 useEslintrc: false,
126 },
127 // @remove-on-eject-end
128 loader: 'eslint-loader',
129 },
130 ],
131 include: paths.appSrc,
132 },
133 // ** ADDING/UPDATING LOADERS **
134 // The "url" loader handles all assets unless explicitly excluded.
135 // The `exclude` list *must* be updated with every change to loader extensions.
136 // When adding a new loader, you must add its `test`
137 // as a new entry in the `exclude` list in the "url" loader.
138
139 // "file" loader makes sure those assets end up in the `build` folder.
140 // When you `import` an asset, you get its filename.
141 {
142 exclude: [
143 /\.html$/,
144 /\.(js|jsx)$/,
145 /\.css$/,
146 /\.json$/,
147 /\.bmp$/,
148 /\.gif$/,
149 /\.jpe?g$/,
150 /\.png$/,
151 ],
152 loader: 'file-loader',
153 options: {
154 name: 'static/media/[name].[hash:8].[ext]',
155 },
156 },
157 // "url" loader works just like "file" loader but it also embeds
158 // assets smaller than specified size as data URLs to avoid requests.
159 {
160 test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
161 loader: 'url-loader',
162 options: {
163 limit: 10000,
164 name: 'static/media/[name].[hash:8].[ext]',
165 },
166 },
167 // Process JS with Babel.
168 {
169 test: /\.(js|jsx)$/,
170 include: paths.appSrc,
171 loader: 'babel-loader',
172 // @remove-on-eject-begin
173 options: {
174 babelrc: false,
175 presets: [require.resolve('babel-preset-react-app')],
176 },
177 // @remove-on-eject-end
178 },
179 // The notation here is somewhat confusing.
180 // "postcss" loader applies autoprefixer to our CSS.
181 // "css" loader resolves paths in CSS and adds assets as dependencies.
182 // "style" loader normally turns CSS into JS modules injecting <style>,
183 // but unlike in development configuration, we do something different.
184 // `ExtractTextPlugin` first applies the "postcss" and "css" loaders
185 // (second argument), then grabs the result CSS and puts it into a
186 // separate file in our build process. This way we actually ship
187 // a single CSS file in production instead of JS code injecting <style>
188 // tags. If you use code splitting, however, any async bundles will still
189 // use the "style" loader inside the async code so CSS from them won't be
190 // in the main CSS file.
191 {
192 test: /\.css$/,
193 loader: ExtractTextPlugin.extract(
194 Object.assign(
195 {
196 fallback: 'style-loader',
197 use: [
198 {
199 loader: 'css-loader',
200 options: {
201 importLoaders: 1,
202 },
203 },
204 {
205 loader: 'postcss-loader',
206 options: {
207 ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
208 plugins: () => [
209 autoprefixer({
210 browsers: [
211 '>1%',
212 'last 4 versions',
213 'Firefox ESR',
214 'not ie < 9', // React doesn't support IE8 anyway
215 ],
216 }),
217 ],
218 },
219 },
220 ],
221 },
222 extractTextPluginOptions,
223 ),
224 ),
225 // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
226 },
227 // ** STOP ** Are you adding a new loader?
228 // Remember to add the new extension(s) to the "url" loader exclusion list.
229 ],
230 },
231 plugins: [
232 // Makes some environment variables available in index.html.
233 // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
234 // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
235 // In production, it will be an empty string unless you specify "homepage"
236 // in `package.json`, in which case it will be the pathname of that URL.
237 new InterpolateHtmlPlugin(env.raw),
238 // Generates an `index.html` file with the <script> injected.
239 new HtmlWebpackPlugin({
240 inject: true,
241 template: paths.appHtml,
242 minify: {
243 removeComments: true,
244 collapseWhitespace: true,
245 removeRedundantAttributes: true,
246 useShortDoctype: true,
247 removeEmptyAttributes: true,
248 removeStyleLinkTypeAttributes: true,
249 keepClosingSlash: true,
250 minifyJS: true,
251 minifyCSS: true,
252 minifyURLs: true,
253 },
254 }),
255 // Makes some environment variables available to the JS code, for example:
256 // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
257 // It is absolutely essential that NODE_ENV was set to production here.
258 // Otherwise React will be compiled in the very slow development mode.
259 new webpack.DefinePlugin(env.stringified),
260 // Minify the code.
261 new webpack.optimize.UglifyJsPlugin({
262 compress: {
263 screw_ie8: true, // React doesn't support IE8
264 warnings: false,
265 },
266 mangle: {
267 screw_ie8: true,
268 },
269 output: {
270 comments: false,
271 screw_ie8: true,
272 },
273 sourceMap: true,
274 }),
275 // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
276 new ExtractTextPlugin({
277 filename: cssFilename,
278 }),
279 // Generate a manifest file which contains a mapping of all asset filenames
280 // to their corresponding output file so that tools can pick it up without
281 // having to parse `index.html`.
282 new ManifestPlugin({
283 fileName: 'asset-manifest.json',
284 }),
285 ],
286 // Some libraries import Node modules but don't use them in the browser.
287 // Tell Webpack to provide empty mocks for them so importing them works.
288 node: {
289 fs: 'empty',
290 net: 'empty',
291 tls: 'empty',
292 },
293};