UNPKG

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