From 726936a1a3a8b2374fd24c0123347ad674358f06 Mon Sep 17 00:00:00 2001 From: Michael Kohler Date: Thu, 27 Sep 2018 19:53:23 +0200 Subject: [PATCH] Update build tooling to same version as CRA2 has - includes node_modules babeling (#305) --- config/env.js | 4 +- config/paths.js | 14 +- config/polyfills.js | 22 - config/webpack.config.dev.js | 273 +- config/webpack.config.prod.js | 387 +- config/webpackDevServer.config.js | 28 +- package-lock.json | 10067 +++++++++++++++++++--------- package.json | 114 +- src/index.js | 1 - 9 files changed, 7513 insertions(+), 3397 deletions(-) delete mode 100644 config/polyfills.js diff --git a/config/env.js b/config/env.js index 30a6c7f1..b0344c5a 100644 --- a/config/env.js +++ b/config/env.js @@ -42,12 +42,12 @@ dotenvFiles.forEach(dotenvFile => { // We support resolving modules according to `NODE_PATH`. // This lets you use absolute paths in imports inside large monorepos: -// https://github.com/facebookincubator/create-react-app/issues/253. +// https://github.com/facebook/create-react-app/issues/253. // It works similar to `NODE_PATH` in Node itself: // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. -// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 +// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 // We also resolve them to make sure all tools using them work consistently. const appDirectory = fs.realpathSync(process.cwd()); process.env.NODE_PATH = (process.env.NODE_PATH || '') diff --git a/config/paths.js b/config/paths.js index 6d16efc9..bb13e801 100644 --- a/config/paths.js +++ b/config/paths.js @@ -5,20 +5,20 @@ const fs = require('fs'); const url = require('url'); // Make sure any symlinks in the project folder are resolved: -// https://github.com/facebookincubator/create-react-app/issues/637 +// https://github.com/facebook/create-react-app/issues/637 const appDirectory = fs.realpathSync(process.cwd()); const resolveApp = relativePath => path.resolve(appDirectory, relativePath); const envPublicUrl = process.env.PUBLIC_URL; -function ensureSlash(path, needsSlash) { - const hasSlash = path.endsWith('/'); +function ensureSlash(inputPath, needsSlash) { + const hasSlash = inputPath.endsWith('/'); if (hasSlash && !needsSlash) { - return path.substr(path, path.length - 1); + return inputPath.substr(0, inputPath.length - 1); } else if (!hasSlash && needsSlash) { - return `${path}/`; + return `${inputPath}/`; } else { - return path; + return inputPath; } } @@ -41,6 +41,7 @@ function getServedPath(appPackageJson) { // config after eject: we're in ./config/ module.exports = { dotenv: resolveApp('.env'), + appPath: resolveApp('.'), appBuild: resolveApp('build'), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), @@ -49,6 +50,7 @@ module.exports = { appSrc: resolveApp('src'), yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveApp('src/setupTests.js'), + proxySetup: resolveApp('src/setupProxy.js'), appNodeModules: resolveApp('node_modules'), publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')), diff --git a/config/polyfills.js b/config/polyfills.js deleted file mode 100644 index 66dff0a8..00000000 --- a/config/polyfills.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -if (typeof Promise === 'undefined') { - // Rejection tracking prevents a common issue where React gets into an - // inconsistent state due to an error, but it gets swallowed by a Promise, - // and the user has no idea what causes React's erratic future behavior. - require('promise/lib/rejection-tracking').enable(); - window.Promise = require('promise/lib/es6-extensions.js'); -} - -// fetch() polyfill for making API calls. -require('whatwg-fetch'); - -// Object.assign() is commonly used with React. -// It will use the native implementation if it's present and isn't buggy. -Object.assign = require('object-assign'); - -// In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet. -// We don't polyfill it in the browser--this is user's responsibility. -if (process.env.NODE_ENV === 'test') { - require('raf').polyfill(global); -} diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 47ee981d..6034363b 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -1,16 +1,17 @@ 'use strict'; -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('react-dev-utils/InterpolateHtmlPlugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); -const eslintFormatter = require('react-dev-utils/eslintFormatter'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); +const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); const getClientEnvironment = require('./env'); const paths = require('./paths'); +const ManifestPlugin = require('webpack-manifest-plugin'); +const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // Webpack uses `publicPath` to determine where the app is being served from. // In development, we always serve from the root. This makes config easier. @@ -22,19 +23,58 @@ const publicUrl = ''; // Get environment variables to inject into our app. const env = getClientEnvironment(publicUrl); +// style files regexes +const cssRegex = /\.css$/; +const cssModuleRegex = /\.module\.css$/; +const sassRegex = /\.(scss|sass)$/; +const sassModuleRegex = /\.module\.(scss|sass)$/; + +// common function to get style loaders +const getStyleLoaders = (cssOptions, preProcessor) => { + const loaders = [ + require.resolve('style-loader'), + { + loader: require.resolve('css-loader'), + options: cssOptions, + }, + { + // Options for PostCSS as we reference these options twice + // Adds vendor prefixing based on your specified browser support in + // package.json + loader: require.resolve('postcss-loader'), + options: { + // Necessary for external CSS imports to work + // https://github.com/facebook/create-react-app/issues/2677 + ident: 'postcss', + plugins: () => [ + require('postcss-flexbugs-fixes'), + require('postcss-preset-env')({ + autoprefixer: { + flexbox: 'no-2009', + }, + stage: 3, + }), + ], + }, + }, + ]; + if (preProcessor) { + loaders.push(require.resolve(preProcessor)); + } + return loaders; +}; + // 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/facebookincubator/create-react-app/issues/343. + // See the discussion in https://github.com/facebook/create-react-app/issues/343 devtool: 'cheap-module-source-map', // 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 @@ -67,22 +107,34 @@ module.exports = { devtoolModuleFilenameTemplate: info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'), }, + optimization: { + // Automatically split vendor and commons + // https://twitter.com/wSokra/status/969633336732905474 + // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 + splitChunks: { + chunks: 'all', + name: false, + }, + // Keep the runtime chunk seperated to enable long term caching + // https://twitter.com/wSokra/status/969679223278505985 + runtimeChunk: true, + }, 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/facebookincubator/create-react-app/issues/253 - modules: ['node_modules', paths.appNodeModules].concat( + // 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/facebookincubator/create-react-app/issues/290 + // 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'], + extensions: ['.web.js', '.js', '.json', '.web.jsx', '.jsx'], alias: { // Support React Native Web @@ -101,19 +153,18 @@ module.exports = { module: { strictExportPresence: true, rules: [ - // TODO: Disable require.ensure as it's not a standard language feature. - // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176. - // { parser: { requireEnsure: false } }, + // 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)$/, + test: /\.(js|jsx)$/, enforce: 'pre', use: [ { options: { - formatter: eslintFormatter, + formatter: require.resolve('react-dev-utils/eslintFormatter'), eslintPath: require.resolve('eslint'), }, @@ -138,54 +189,135 @@ module.exports = { name: 'static/media/[name].[hash:8].[ext]', }, }, - // Process JS with Babel. + // Process application JS with Babel. + // The preset includes JSX, Flow, and some ESnext features. { - test: /\.(js|jsx|mjs)$/, + test: /\.(js|jsx)$/, include: paths.appSrc, - loader: require.resolve('babel-loader'), - options: { - // 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, - }, + use: [ + // This loader parallelizes code compilation, it is optional but + // improves compile time on larger projects + { + loader: require.resolve('thread-loader'), + options: { + poolTimeout: Infinity, // keep workers alive for more effective watch mode + }, + }, + { + // We need to use our own loader until `babel-loader` supports + // customization + // https://github.com/babel/babel-loader/pull/687 + loader: require.resolve('babel-preset-react-app/loader'), + options: { + + plugins: [ + [ + require.resolve('babel-plugin-named-asset-import'), + { + loaderMap: { + svg: { + ReactComponent: + '@svgr/webpack?-prettier,-svgo![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, + // Don't waste time on Gzipping the cache + cacheCompression: false, + highlightCode: true, + }, + }, + ], + }, + // Process any JS outside of the app with Babel. + // Unlike the application JS, we only compile the standard ES features. + { + test: /\.js$/, + exclude: /@babel(?:\/|\\{1,2})runtime/, + use: [ + // This loader parallelizes code compilation, it is optional but + // improves compile time on larger projects + { + loader: require.resolve('thread-loader'), + options: { + poolTimeout: Infinity, // keep workers alive for more effective watch mode + }, + }, + { + loader: require.resolve('babel-loader'), + options: { + babelrc: false, + compact: false, + presets: [ + [ + require.resolve('babel-preset-react-app/dependencies'), + { helpers: true }, + ], + ], + cacheDirectory: true, + // Don't waste time on Gzipping the cache + cacheCompression: false, + + highlightCode: true, + // If an error happens in a package, it's possible to be + // because it was compiled. Thus, we don't want the browser + // debugger to show the original code. Instead, the code + // being evaluated would be much more helpful. + sourceMaps: false, + }, + }, + ], }, // "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