// @remove-on-eject-begin /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ // @remove-on-eject-end var autoprefixer = require('autoprefixer'); var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); var ManifestPlugin = require('webpack-manifest-plugin'); var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); var paths = require('./paths'); var getClientEnvironment = require('./env'); // @remove-on-eject-begin // `path` is not used after eject - see https://github.com/facebookincubator/create-react-app/issues/1174 var path = require('path'); // @remove-on-eject-end // Webpack uses `publicPath` to determine where the app is being served from. // It requires a trailing slash, or the file assets will get an incorrect path. var publicPath = paths.servedPath; // Some apps do not use client-side routing with pushState. // For these, "homepage" can be set to "." to enable relative asset paths. var shouldUseRelativeAssetPaths = publicPath === './'; // `publicUrl` is just like `publicPath`, but we will provide it to our app // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz. var publicUrl = publicPath.slice(0, -1); // Get environment variables to inject into our app. var env = getClientEnvironment(publicUrl); // Assert this just to be safe. // Development builds of React are slow and not intended for production. if (env.stringified['process.env'].NODE_ENV !== '"production"') { throw new Error('Production builds must have NODE_ENV=production.'); } // Note: defined here because it will be used more than once. const cssFilename = 'static/css/[name].[contenthash:8].css'; // ExtractTextPlugin expects the build output to be flat. // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27) // However, our output is structured with css, js and media folders. // To have this structure working with relative paths, we have to use custom options. const extractTextPluginOptions = shouldUseRelativeAssetPaths // Making sure that the publicPath goes back to to build folder. ? {publicPath: Array(cssFilename.split('/').length).join('../')} : {}; // This is the production configuration. // It compiles slowly and is focused on producing a fast and minimal bundle. // The development configuration is different and lives in a separate file. module.exports = { // Don't attempt to continue if there are any errors. bail: true, // We generate sourcemaps in production. This is slow but gives good results. // You can exclude the *.map files from the build during deployment. devtool: 'source-map', // In production, we only want to load the polyfills and the app code. entry: [ require.resolve('./polyfills'), paths.appIndexJs ], output: { // The build folder. path: paths.appBuild, // Generated JS file names (with nested folders). // There will be one main bundle, and one file per asynchronous chunk. // We don't currently advertise code splitting but Webpack supports it. filename: 'static/js/[name].[chunkhash:8].js', chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js', // We inferred the "public path" (such as / or /my-project) from homepage. publicPath: publicPath }, resolve: { // This allows you to set a fallback for where Webpack should look for modules. // We read `NODE_PATH` environment variable in `paths.js` and pass paths here. // We placed these paths second because we want `node_modules` to "win" // if there are any conflicts. This matches Node resolution mechanism. // https://github.com/facebookincubator/create-react-app/issues/253 modules: ['node_modules'].concat(paths.nodePaths), // These are the reasonable defaults supported by the Node ecosystem. // We also include JSX as a common component filename extension to support // some tools, although we do not recommend using it, see: // https://github.com/facebookincubator/create-react-app/issues/290 extensions: ['.js', '.json', '.jsx'], alias: { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ 'react-native': 'react-native-web' } }, // @remove-on-eject-begin // Resolve loaders (webpack plugins for CSS, images, transpilation) from the // directory of `react-scripts` itself rather than the project directory. resolveLoader: { modules: [ paths.ownNodeModules, // Lerna hoists everything, so we need to look in our app directory paths.appNodeModules ] }, // @remove-on-eject-end module: { rules: [ // Disable require.ensure as it's not a standard language feature. { parser: { requireEnsure: false } }, // First, run the linter. // It's important to do this before Babel processes the JS. { test: /\.(js|jsx)$/, enforce: 'pre', use: [{ // @remove-on-eject-begin // Point ESLint to our predefined config. options: { // TODO: consider separate config for production, // e.g. to enable no-console and no-debugger only in production. configFile: path.join(__dirname, '../.eslintrc'), useEslintrc: false }, // @remove-on-eject-end loader: 'eslint-loader' }], include: paths.appSrc }, // ** ADDING/UPDATING LOADERS ** // The "url" loader handles all assets unless explicitly excluded. // The `exclude` list *must* be updated with every change to loader extensions. // When adding a new loader, you must add its `test` // as a new entry in the `exclude` list in the "url" loader. // "url" loader embeds assets smaller than specified size as data URLs to avoid requests. // Otherwise, it acts like the "file" loader. { exclude: [ /\.html$/, /\.(js|jsx)$/, /\.css$/, /\.json$/, /\.svg$/ ], loader: 'url-loader', options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' } }, // Process JS with Babel. { test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel-loader', // @remove-on-eject-begin options: { babelrc: false, presets: [require.resolve('babel-preset-react-app')], }, // @remove-on-eject-end }, // The notation here is somewhat confusing. // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. // "style" loader normally turns CSS into JS modules injecting <style>, // but unlike in development configuration, we do something different. // `ExtractTextPlugin` first applies the "postcss" and "css" loaders // (second argument), then grabs the result CSS and puts it into a // separate file in our build process. This way we actually ship // a single CSS file in production instead of JS code injecting <style> // tags. If you use code splitting, however, any async bundles will still // use the "style" loader inside the async code so CSS from them won't be // in the main CSS file. { test: /\.css$/, loader: ExtractTextPlugin.extract(Object.assign({ fallback: 'style-loader', use: [ { loader: 'css-loader', options: { importLoaders: 1 } }, { loader: 'postcss-loader', options: { ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options plugins: function () { return [ autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ] }) ] } } } ] }, extractTextPluginOptions)) // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, // "file" loader for svg { test: /\.svg$/, loader: 'file-loader', options: { name: 'static/media/[name].[hash:8].[ext]' } } // ** STOP ** Are you adding a new loader? // Remember to add the new extension(s) to the "url" loader exclusion list. ] }, plugins: [ // Makes some environment variables available in index.html. // The public URL is available as %PUBLIC_URL% in index.html, e.g.: // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> // In production, it will be an empty string unless you specify "homepage" // in `package.json`, in which case it will be the pathname of that URL. new InterpolateHtmlPlugin(env.raw), // Generates an `index.html` file with the <script> injected. new HtmlWebpackPlugin({ inject: true, template: paths.appHtml, minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true } }), // Makes some environment variables available to the JS code, for example: // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`. // It is absolutely essential that NODE_ENV was set to production here. // Otherwise React will be compiled in the very slow development mode. new webpack.DefinePlugin(env.stringified), // Minify the code. new webpack.optimize.UglifyJsPlugin({ compress: { screw_ie8: true, // React doesn't support IE8 warnings: false }, mangle: { screw_ie8: true }, output: { comments: false, screw_ie8: true }, sourceMap: true }), // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`. new ExtractTextPlugin({ filename: cssFilename }), // Generate a manifest file which contains a mapping of all asset filenames // to their corresponding output file so that tools can pick it up without // having to parse `index.html`. new ManifestPlugin({ fileName: 'asset-manifest.json' }) ], // Some libraries import Node modules but don't use them in the browser. // Tell Webpack to provide empty mocks for them so importing them works. node: { fs: 'empty', net: 'empty', tls: 'empty' } };