Skip to content

Instantly share code, notes, and snippets.

@vire
Created September 18, 2018 09:07

Revisions

  1. vire created this gist Sep 18, 2018.
    336 changes: 336 additions & 0 deletions webpack.config.dev.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,336 @@
    const autoprefixer = require('autoprefixer');
    const path = require('path');
    const webpack = require('webpack');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
    const InterpolateHtmlPlugin = require('interpolate-html-plugin');
    const eslintFormatter = require('react-dev-utils/eslintFormatter');
    const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
    const getClientEnvironment = require('./env');
    const paths = require('./paths');

    // Webpack uses `publicPath` to determine where the app is being served from.
    // In development, we always serve from the root. This makes config easier.
    const 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_PATH%/xyz looks better than %PUBLIC_PATH%xyz.
    const publicUrl = '';
    // Get environment variables to inject into our app.
    const env = getClientEnvironment(publicUrl);

    // Options for PostCSS as we reference these options twice
    // Adds vendor prefixing based on your specified browser support in
    // package.json
    const postCSSLoaderOptions = {
    // Necessary for external CSS imports to work
    // https://github.com/facebook/create-react-app/issues/2677
    ident: 'postcss',
    plugins: () => [
    require('postcss-flexbugs-fixes'),
    autoprefixer({
    flexbox: 'no-2009',
    }),
    ],
    };

    // This is the development configuration.
    // It is focused on developer experience and fast rebuilds.
    // The production configuration is different and lives in a separate file.
    module.exports = {
    mode: 'development',
    // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
    // See the discussion in https://github.com/facebook/create-react-app/issues/343.
    // TODO: vire - using `eval` instead of `cheap-module-source-map` make build/rebuild faster
    devtool: 'eval',
    // These are the "entry points" to our application.
    // This means they will be the "root" imports that are included in JS bundle.
    // The first two entry points enable "hot" CSS and auto-refreshes for JS.
    entry: [
    // We ship a few polyfills by default:
    require.resolve('./polyfills'),
    // Include an alternative client for WebpackDevServer. A client's job is to
    // connect to WebpackDevServer by a socket and get notified about changes.
    // When you save a file, the client will either apply hot updates (in case
    // of CSS changes), or refresh the page (in case of JS changes). When you
    // make a syntax error, this client will display a syntax error overlay.
    // Note: instead of the default WebpackDevServer client, we use a custom one
    // to bring better experience for Create React App users. You can replace
    // the line below with these two lines if you prefer the stock client:
    // require.resolve('webpack-dev-server/client') + '?/',
    // require.resolve('webpack/hot/dev-server'),
    require.resolve('react-dev-utils/webpackHotDevClient'),
    // Finally, this is your app's code:
    paths.appIndexJs,
    // We include the app code last so that if there is a runtime error during
    // initialization, it doesn't blow up the WebpackDevServer client, and
    // changing JS code would still trigger a refresh.
    ],
    output: {
    // Add /* filename */ comments to generated require()s in the output.
    pathinfo: true,
    // This does not produce a real file. It's just the virtual path that is
    // served by WebpackDevServer in development. This is the JS bundle
    // containing code from all our entry points, and the Webpack runtime.
    filename: 'static/js/[name].bundle.js',
    // There are also additional JS chunk files if you use code splitting.
    chunkFilename: 'static/js/[name].chunk.js',
    // This is the URL that app is served from. We use "/" in development.
    publicPath,
    // Point sourcemap entries to original disk location (format as URL on Windows)
    devtoolModuleFilenameTemplate: info =>
    path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
    },
    resolve: {
    // This allows you to set a fallback for where Webpack should look for modules.
    // 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/facebook/create-react-app/issues/253
    modules: ['node_modules'].concat(
    // It is guaranteed to exist because we tweak it in `env.js`
    process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
    ),
    // 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/facebook/create-react-app/issues/290
    // `web` extension prefixes have been added for better support
    // for React Native Web.
    extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
    plugins: [
    // Prevents users from importing files from outside of src/ (or node_modules/).
    // This often causes confusion because we only process files within src/ with babel.
    // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
    // please link the files into your node_modules/ and let module-resolution kick in.
    // Make sure your source files are compiled, as they will not be processed in any way.
    new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
    ],
    },
    module: {
    strictExportPresence: true,
    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|mjs)$/,
    enforce: 'pre',
    use: [
    {
    options: {
    formatter: eslintFormatter,
    eslintPath: require.resolve('eslint'),
    },
    loader: require.resolve('eslint-loader'),
    },
    ],
    include: paths.srcPaths,
    exclude: [/[/\\\\]node_modules[/\\\\]/],
    },
    {
    // "oneOf" will traverse all following loaders until one will
    // match the requirements. When no loader matches it will fall
    // back to the "file" loader at the end of the loader list.
    oneOf: [
    // "url" loader works like "file" loader except that it embeds assets
    // smaller than specified limit in bytes as data URLs to avoid requests.
    // A missing `test` is equivalent to a match.
    {
    test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
    loader: require.resolve('url-loader'),
    options: {
    limit: 10000,
    name: 'static/media/[name].[hash:8].[ext]',
    },
    },
    // Process application JS with Babel.
    // The preset includes JSX, Flow, and some ESnext features.
    {
    test: /\.(js|jsx|mjs)$/,
    include: paths.srcPaths,
    exclude: [/[/\\\\]node_modules[/\\\\]/],
    use: [
    // This loader parallelizes code compilation, it is optional but
    // improves compile time on larger projects
    require.resolve('thread-loader'),
    {
    loader: require.resolve('babel-loader'),
    options: {
    presets: [require.resolve('babel-preset-react-app')],
    plugins: [
    [
    require.resolve('babel-plugin-named-asset-import'),
    {
    loaderMap: {
    svg: {
    ReactComponent: 'svgr/webpack![path]',
    },
    },
    },
    ],
    ],
    // This is a feature of `babel-loader` for webpack (not Babel itself).
    // It enables caching results in ./node_modules/.cache/babel-loader/
    // directory for faster rebuilds.
    cacheDirectory: true,
    highlightCode: true,
    },
    },
    ],
    },
    // Process any JS outside of the app with Babel.
    // Unlike the application JS, we only compile the standard ES features.
    {
    test: /\.js$/,
    use: [
    // This loader parallelizes code compilation, it is optional but
    // improves compile time on larger projects
    require.resolve('thread-loader'),
    {
    loader: require.resolve('babel-loader'),
    options: {
    babelrc: false,
    compact: false,
    presets: [
    require.resolve('babel-preset-react-app/dependencies'),
    ],
    cacheDirectory: true,
    highlightCode: true,
    },
    },
    ],
    },
    // "postcss" loader applies autoprefixer to our CSS.
    // "css" loader resolves paths in CSS and adds assets as dependencies.
    // "style" loader turns CSS into JS modules that inject <style> tags.
    // In production, we use a plugin to extract that CSS to a file, but
    // in development "style" loader enables hot editing of CSS.
    // By default we support CSS Modules with the extension .module.css
    {
    test: /\.css$/,
    exclude: /\.module\.css$/,
    use: [
    require.resolve('style-loader'),
    {
    loader: require.resolve('css-loader'),
    options: {
    importLoaders: 1,
    },
    },
    {
    loader: require.resolve('postcss-loader'),
    options: postCSSLoaderOptions,
    },
    ],
    },
    // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
    // using the extension .module.css
    {
    test: /\.module\.css$/,
    use: [
    require.resolve('style-loader'),
    {
    loader: require.resolve('css-loader'),
    options: {
    importLoaders: 1,
    modules: true,
    localIdentName: '[path]__[name]___[local]',
    },
    },
    {
    loader: require.resolve('postcss-loader'),
    options: postCSSLoaderOptions,
    },
    ],
    },
    // The GraphQL loader preprocesses GraphQL queries in .graphql files.
    {
    test: /\.(graphql)$/,
    loader: 'graphql-tag/loader',
    },
    // "file" loader makes sure those assets get served by WebpackDevServer.
    // When you `import` an asset, you get its (virtual) filename.
    // In production, they would get copied to the `build` folder.
    // This loader doesn't use a "test" so it will catch all modules
    // that fall through the other loaders.
    {
    // Exclude `js` files to keep "css" loader working as it injects
    // its runtime that would otherwise be processed through "file" loader.
    // Also exclude `html` and `json` extensions so they get processed
    // by webpacks internal loaders.
    exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
    loader: require.resolve('file-loader'),
    options: {
    name: 'static/media/[name].[hash:8].[ext]',
    },
    },
    ],
    },
    // ** STOP ** Are you adding a new loader?
    // Make sure to add the new loader(s) before the "file" loader.
    ],
    },
    optimization: {
    splitChunks: {
    cacheGroups: {
    commons: {
    test: /[\\/]node_modules[\\/]/,
    name: 'vendor',
    chunks: 'initial',
    },
    },
    },
    },
    plugins: [
    new webpack.LoaderOptionsPlugin({
    options: {
    context: process.cwd(), // or the same value as `context`
    },
    }),
    // Generates an `index.html` file with the <script> injected.
    new HtmlWebpackPlugin({
    inject: true,
    template: paths.appHtml,
    chunksSortMode: 'none',
    }),
    // 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 development, this will be an empty string.
    new InterpolateHtmlPlugin(env.raw),
    // Add module names to factory functions so they appear in browser profiler.
    new webpack.NamedModulesPlugin(),
    // Makes some environment variables available to the JS code, for example:
    // if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
    new webpack.DefinePlugin(env.stringified),
    // This is necessary to emit hot updates (currently CSS only):
    new webpack.HotModuleReplacementPlugin(),
    // Watcher doesn't work well if you mistype casing in a path so we use
    // a plugin that prints an error when you attempt to do this.
    // See https://github.com/facebook/create-react-app/issues/240
    new CaseSensitivePathsPlugin(),
    // Moment.js is an extremely popular library that bundles large locale files
    // by default due to how Webpack interprets its code. This is a practical
    // solution that requires the user to opt into importing specific locales.
    // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
    // You can remove this if you don't use Moment.js:
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    ],
    // 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: {
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty',
    },
    // Turn off performance hints during development because we don't do any
    // splitting or minification in interest of speed. These warnings become
    // cumbersome.
    performance: {
    hints: false,
    },
    };
    416 changes: 416 additions & 0 deletions webpack.config.prod.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,416 @@
    const autoprefixer = require('autoprefixer');
    const path = require('path');
    const webpack = require('webpack');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const ManifestPlugin = require('webpack-manifest-plugin');
    const InterpolateHtmlPlugin = require('interpolate-html-plugin');
    const eslintFormatter = require('react-dev-utils/eslintFormatter');
    const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
    const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');

    const paths = require('./paths');
    const getClientEnvironment = require('./env');

    // 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.
    const 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.
    const shouldUseRelativeAssetPaths = publicPath === './';
    // Source maps are resource heavy and can cause out of memory issue for large source files.
    const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
    // `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.
    const publicUrl = publicPath.slice(0, -1);
    // Get environment variables to inject into our app.
    const 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].[md5:contenthash:hex:20].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('../') }
    : {};

    // Options for PostCSS as we reference these options twice
    // Adds vendor prefixing based on your specified browser support in
    // package.json
    const postCSSLoaderOptions = {
    // Necessary for external CSS imports to work
    // https://github.com/facebook/create-react-app/issues/2677
    ident: 'postcss',
    plugins: () => [
    require('postcss-flexbugs-fixes'),
    autoprefixer({
    flexbox: 'no-2009',
    }),
    ],
    };

    // 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 = {
    mode: 'production',
    // 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: shouldUseSourceMap ? 'source-map' : false,
    // 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,
    // Point sourcemap entries to original disk location (format as URL on Windows)
    devtoolModuleFilenameTemplate: info =>
    path
    .relative(paths.appSrc, info.absoluteResourcePath)
    .replace(/\\/g, '/'),
    },
    resolve: {
    // This allows you to set a fallback for where Webpack should look for modules.
    // 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/facebook/create-react-app/issues/253
    modules: ['node_modules'].concat(
    // It is guaranteed to exist because we tweak it in `env.js`
    process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
    ),
    // 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/facebook/create-react-app/issues/290
    // `web` extension prefixes have been added for better support
    // for React Native Web.
    extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
    plugins: [
    // Prevents users from importing files from outside of src/ (or node_modules/).
    // This often causes confusion because we only process files within src/ with babel.
    // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
    // please link the files into your node_modules/ and let module-resolution kick in.
    // Make sure your source files are compiled, as they will not be processed in any way.
    new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
    ],
    },
    module: {
    strictExportPresence: true,
    rules: [
    // Disable require.ensure as it's not a standard language feature.
    { parser: { requireEnsure: false } },
    {
    test: /\.(js|jsx|mjs)$/,
    enforce: 'pre',
    use: [
    {
    options: {
    formatter: eslintFormatter,
    eslintPath: require.resolve('eslint'),
    // TODO: consider separate config for production,
    // e.g. to enable no-console and no-debugger only in production.
    },
    loader: require.resolve('eslint-loader'),
    },
    ],
    include: paths.srcPaths,
    exclude: [/[/\\\\]node_modules[/\\\\]/],
    },
    {
    // "oneOf" will traverse all following loaders until one will
    // match the requirements. When no loader matches it will fall
    // back to the "file" loader at the end of the loader list.
    oneOf: [
    // "url" loader works just like "file" loader but it also embeds
    // assets smaller than specified size as data URLs to avoid requests.
    {
    test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
    loader: require.resolve('url-loader'),
    options: {
    limit: 10000,
    name: 'static/media/[name].[hash:8].[ext]',
    },
    },
    // Process application JS with Babel.
    // The preset includes JSX, Flow, and some ESnext features.
    {
    test: /\.(js|jsx|mjs)$/,
    include: paths.srcPaths,
    exclude: [/[/\\\\]node_modules[/\\\\]/],
    use: [
    // This loader parallelizes code compilation, it is optional but
    // improves compile time on larger projects
    require.resolve('thread-loader'),
    {
    loader: require.resolve('babel-loader'),
    options: {
    presets: [require.resolve('babel-preset-react-app')],
    plugins: [
    [
    require.resolve('babel-plugin-named-asset-import'),
    {
    loaderMap: {
    svg: {
    ReactComponent: 'svgr/webpack![path]',
    },
    },
    },
    ],
    ],
    compact: true,
    highlightCode: true,
    },
    },
    ],
    },
    // Process any JS outside of the app with Babel.
    // Unlike the application JS, we only compile the standard ES features.
    {
    test: /\.js$/,
    use: [
    // This loader parallelizes code compilation, it is optional but
    // improves compile time on larger projects
    require.resolve('thread-loader'),
    {
    loader: require.resolve('babel-loader'),
    options: {
    babelrc: false,
    compact: false,
    presets: [
    require.resolve('babel-preset-react-app/dependencies'),
    ],
    cacheDirectory: true,
    highlightCode: true,
    },
    },
    ],
    },
    // 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.
    // By default we support CSS Modules with the extension .module.css
    {
    test: /\.css$/,
    exclude: /\.module\.css$/,
    loader: ExtractTextPlugin.extract(
    Object.assign(
    {
    fallback: {
    loader: require.resolve('style-loader'),
    options: {
    hmr: false,
    },
    },
    use: [
    {
    loader: require.resolve('css-loader'),
    options: {
    importLoaders: 1,
    minimize: true,
    sourceMap: shouldUseSourceMap,
    },
    },
    {
    loader: require.resolve('postcss-loader'),
    options: postCSSLoaderOptions,
    },
    ],
    },
    extractTextPluginOptions
    )
    ),
    // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
    },
    // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
    // using the extension .module.css
    {
    test: /\.module\.css$/,
    loader: ExtractTextPlugin.extract(
    Object.assign(
    {
    fallback: {
    loader: require.resolve('style-loader'),
    options: {
    hmr: false,
    },
    },
    use: [
    {
    loader: require.resolve('css-loader'),
    options: {
    importLoaders: 1,
    minimize: true,
    sourceMap: shouldUseSourceMap,
    modules: true,
    localIdentName: '[path]__[name]___[local]',
    },
    },
    {
    loader: require.resolve('postcss-loader'),
    options: postCSSLoaderOptions,
    },
    ],
    },
    extractTextPluginOptions
    )
    ),
    // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
    },
    // The GraphQL loader preprocesses GraphQL queries in .graphql files.
    {
    test: /\.(graphql)$/,
    loader: 'graphql-tag/loader',
    },
    // "file" loader makes sure assets end up in the `build` folder.
    // When you `import` an asset, you get its filename.
    // This loader doesn't use a "test" so it will catch all modules
    // that fall through the other loaders.
    {
    loader: require.resolve('file-loader'),
    // Exclude `js` files to keep "css" loader working as it injects
    // it's runtime that would otherwise be processed through "file" loader.
    // Also exclude `html` and `json` extensions so they get processed
    // by webpacks internal loaders.
    exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
    options: {
    name: 'static/media/[name].[hash:8].[ext]',
    },
    },
    // ** STOP ** Are you adding a new loader?
    // Make sure to add the new loader(s) before the "file" loader.
    ],
    },
    ],
    },
    optimization: {
    splitChunks: {
    cacheGroups: {
    commons: {
    test: /[\\/]node_modules[\\/]/,
    name: 'vendor',
    chunks: 'initial',
    },
    },
    },
    minimizer: [
    // Minify the code.
    new UglifyJsPlugin({
    uglifyOptions: {
    compress: {
    // Disabled because of an issue with Uglify breaking seemingly valid code:
    // https://github.com/facebook/create-react-app/issues/2376
    // Pending further investigation:
    // https://github.com/mishoo/UglifyJS2/issues/2011
    comparisons: false,
    },
    output: {
    comments: false,
    // Turned on because emoji and regex is not minified properly using default
    // https://github.com/facebook/create-react-app/issues/2488
    ascii_only: true,
    },
    },
    // Use multi-process parallel running to improve the build speed
    // Default number of concurrent runs: os.cpus().length - 1
    parallel: true,
    // Enable file caching
    cache: true,
    sourceMap: shouldUseSourceMap,
    }),
    ],
    },
    plugins: [
    // TODO: vire - LoaderOptionsPlugin needs to be removed
    // see https://github.com/webpack/webpack/issues/6064
    new webpack.LoaderOptionsPlugin({
    options: {
    context: process.cwd(), // or the same value as `context`
    },
    }),
    // 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 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),
    // 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),

    // 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',
    publicPath,
    }),
    // Moment.js is an extremely popular library that bundles large locale files
    // by default due to how Webpack interprets its code. This is a practical
    // solution that requires the user to opt into importing specific locales.
    // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
    // You can remove this if you don't use Moment.js:
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new SpeedMeasurePlugin(),
    ],
    // 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: {
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty',
    },
    };