packages/brookjs-cli/src/webpack/selectors.ts
File `selectors.ts` has 510 lines of code (exceeds 250 allowed). Consider refactoring.// @todo: readd NpmInstallPlugin// @todo: clean up this file (extra functions, commented out code, etc.)import path from 'path';// import address from 'address';import webpack, { Loader } from 'webpack';import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';import { Plugin as ShakePlugin } from 'webpack-common-shake';import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';import TerserPlugin from 'terser-webpack-plugin';import safePostCssParser from 'postcss-safe-parser';import MiniCssExtractPlugin from 'mini-css-extract-plugin';import postcssNormalize from 'postcss-normalize';import getCSSModuleLocalIdent from 'react-dev-utils/getCSSModuleLocalIdent';import errorOverlayMiddleware from 'react-dev-utils/errorOverlayMiddleware';import evalSourceMapMiddleware from 'react-dev-utils/evalSourceMapMiddleware';import noopServiceWorkerMiddleware from 'react-dev-utils/noopServiceWorkerMiddleware';import ignoredFiles from 'react-dev-utils/ignoredFiles';// import InlineChunkHtmlPlugin from 'react-dev-utils/InlineChunkHtmlPlugin';// import InterpolateHtmlPlugin from 'react-dev-utils/InterpolateHtmlPlugin';// import ModuleNotFoundPlugin from 'react-dev-utils/ModuleNotFoundPlugin';// import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin';import ManifestPlugin from 'webpack-manifest-plugin';import WebpackDevServer from 'webpack-dev-server';import HtmlWebpackPlugin from 'html-webpack-plugin';import { unreachable } from 'brookjs-types';import camelcase from 'camelcase';import { BuildConfig } from './types';// @TODO(mAAdhaTTah) fix require -> import (missing types)// const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');// const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin'); // file regexesconst jsRegex = /\.(js|mjs|jsx|ts|tsx)$/;const cssRegex = /\.css$/;const cssModuleRegex = /\.module\.css$/;const sassRegex = /\.(scss|sass)$/;const sassModuleRegex = /\.module\.(scss|sass)$/; const isEnvDevelopment = (state: BuildConfig) => state.env === 'development';const isEnvProduction = (state: BuildConfig) => state.env === 'production';const isEnvProductionProfile = (/* state: State */) => false;const shouldUseSourceMap = (/* state: State */) => true;const shouldUseRelativeAssetPaths = (state: BuildConfig) => selectPublicPath(state) === './';const selectPublicPath = (state: BuildConfig) => '/';const selectPublicUrlOrPath = (state: BuildConfig) => { return '/'; // return getPublicUrlOrPath(isEnvDevelopment(state));};const selectAppPath = (state: BuildConfig): string => path.join(state.cwd, state.rc?.dir ?? 'src');const selectAppHtml = (state: BuildConfig) => path.join(state.cwd, 'public', 'index.html');// const selectHttpsConfig = (state: State) => false;// const selectProxy = (state: State) => undefined;// const selectHost = (state: State) => '0.0.0.0';// const selectAllowHosts = (state: State) => {// const host = selectHost(state);// const isUnspecifiedHost = host === '0.0.0.0' || host === '::';// let lanUrlForConfig;// if (isUnspecifiedHost) {// try {// // This can only return an IPv4 address// lanUrlForConfig = address.ip();// if (lanUrlForConfig) {// // Check if the address is a private ip// // https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces// if (// !/^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(// lanUrlForConfig// )// ) {// // Address is not private, so we will discard it// lanUrlForConfig = undefined;// }// }// } catch (_e) {// // ignored// }// } // return lanUrlForConfig;// }; // const shouldInlineRuntimeChunk = (state: State) => true;// const selectPublicUrl = (state: State) => {// switch (state.cmd) {// case 'start':// return 'localhost:3000';// case 'build':// return '';// default:// return unreachable(state.cmd);// }// }; // const selectAppNodeModulesPath = (state: State) =>// path.join(state.cwd, 'node_modules'); const defaultBabelConfig = { presets: [require.resolve('babel-preset-brookjs')], plugins: [ [ require.resolve('babel-plugin-named-asset-import'), { loaderMap: { svg: { ReactComponent: '@svgr/webpack?-svgo,+titleProp,+ref![path]', }, }, }, ], ],}; Function `selectStyleLoaders` has 47 lines of code (exceeds 25 allowed). Consider refactoring.const selectStyleLoaders = ( state: BuildConfig, cssLoaderOptions: object, preProcessor?: string,) => { const loaders = [ isEnvDevelopment(state) && require.resolve('style-loader'), isEnvProduction(state) && { loader: MiniCssExtractPlugin.loader, options: shouldUseRelativeAssetPaths(state) ? { publicPath: '../../' } : {}, }, { loader: require.resolve('css-loader'), options: cssLoaderOptions, }, { // 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, }), // Adds PostCSS Normalize as the reset css with default options, // so that it honors browserslist config in package.json // which in turn let's users customize the target behavior as per their needs. postcssNormalize(), ], sourceMap: isEnvProduction(state) && shouldUseSourceMap(), }, }, ].filter(Boolean) as Loader[]; if (preProcessor) { loaders.push( { loader: require.resolve('resolve-url-loader'), options: { sourceMap: isEnvProduction(state) && shouldUseSourceMap(), }, }, { loader: require.resolve(preProcessor), options: { sourceMap: true, }, }, ); } return loaders;}; const selectDefaultRules = (state: BuildConfig) => [ { parser: { requireEnsure: false } }, { test: jsRegex, loader: require.resolve('babel-loader'), include: selectAppPath(state), options: { customize: require.resolve('babel-preset-react-app/webpack-overrides'), babelrc: false, configFile: false, cacheDirectory: true, cacheCompression: false, compact: isEnvProduction(state), ...(state.rc?.babel?.modifier?.(defaultBabelConfig) ?? defaultBabelConfig), }, }, // "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 MiniCSSExtractPlugin 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: cssRegex, exclude: cssModuleRegex, use: selectStyleLoaders(state, { importLoaders: 1, sourceMap: isEnvProduction(state) && shouldUseSourceMap(), }), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. // Remove this when webpack adds a warning or an error for this. // See https://github.com/webpack/webpack/issues/6571 sideEffects: true, }, // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css { test: cssModuleRegex, use: selectStyleLoaders(state, { importLoaders: 1, sourceMap: isEnvProduction(state) && shouldUseSourceMap(), modules: { getLocalIdent: getCSSModuleLocalIdent, }, }), }, // Opt-in support for SASS (using .scss or .sass extensions). // By default we support SASS Modules with the // extensions .module.scss or .module.sass { test: sassRegex, exclude: sassModuleRegex, use: selectStyleLoaders( state, { importLoaders: 3, sourceMap: isEnvProduction(state) && shouldUseSourceMap(), }, require.resolve('sass-loader'), ), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. // Remove this when webpack adds a warning or an error for this. // See https://github.com/webpack/webpack/issues/6571 sideEffects: true, }, // Adds support for CSS Modules, but using SASS // using the extension .module.scss or .module.sass { test: sassModuleRegex, use: selectStyleLoaders( state, { importLoaders: 3, sourceMap: isEnvProduction(state) && shouldUseSourceMap(), modules: { getLocalIdent: getCSSModuleLocalIdent, }, }, require.resolve('sass-loader'), ), },]; const selectEnvRules = (state: BuildConfig) => { switch (state.env) { case 'development': return [ { test: jsRegex, loader: require.resolve('eslint-loader'), include: selectAppPath(state), enforce: 'pre' as const, options: { cache: true, formatter: require.resolve('react-dev-utils/eslintFormatter'), eslintPath: require.resolve('eslint'), baseConfig: { extends: [require.resolve('eslint-config-brookjs')], }, useEslintrc: false, }, }, ]; default: return []; }}; const selectDefaultPlugins = (state: BuildConfig) => [ // @TODO(mAAdhaTTah) readd–rollup gets sad :( // This gives some necessary context to module not found errors, such as // the requesting resource. // new ModuleNotFoundPlugin(selectAppPath(state)), // Generate an asset manifest file with the following content: // - "files" key: Mapping of all asset filenames to their corresponding // output file so that tools can pick it up without having to parse // `index.html` // - "entrypoints" key: Array of files which are included in `index.html`, // can be used to reconstruct the HTML if necessary new ManifestPlugin({ fileName: 'asset-manifest.json', publicPath: selectPublicPath(state), generate: (seed, files, entrypoints) => ({ files: files.reduce((manifest, file) => { if (file.name != null) manifest[file.name] = file.path; return manifest; }, seed as Record<string, string>), entrypoints: Object.entries(entrypoints).reduce( (entries, [key, entry]) => ({ ...entries, [key]: entry.filter(fileName => !fileName.endsWith('.map')), }), {}, ), }), }), // 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$/), // Generates an `index.html` file with the <script> injected. new HtmlWebpackPlugin( Object.assign( {}, { inject: true, template: selectAppHtml(state), }, isEnvProduction(state) ? { minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, } : undefined, ), ), // new InterpolateHtmlPlugin(HtmlWebpackPlugin, { // // Useful for determining whether we’re running in production mode. // // Most importantly, it switches React into the correct mode. // NODE_ENV: process.env.NODE_ENV || 'development', // // Useful for resolving the correct path to static assets in `public`. // // For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />. // // This should only be used as an escape hatch. Normally you would put // // images into the `src` and `import` them in code to get their paths. // PUBLIC_URL: selectPublicUrl(state) // })]; Function `selectEnvPlugins` has 40 lines of code (exceeds 25 allowed). Consider refactoring.const selectEnvPlugins = (state: BuildConfig) => { const plugins = state.watch ? [ // If you require a missing module and then `npm install` it, you still have // to restart the development server for Webpack to discover it. This plugin // makes the discovery automatic so you don't have to restart. // See https://github.com/facebook/create-react-app/issues/186 // @TODO(mAAdhaTTah) readd–rollup gets sad :( // new WatchMissingNodeModulesPlugin(selectAppNodeModulesPath(state)) ] : []; switch (state.env) { case 'development': return [ ...plugins, state.extension === 'ts' && // Only typecheck if we're watching. state.watch && new ForkTsCheckerWebpackPlugin({ async: true, useTypescriptIncrementalApi: true, checkSyntacticErrors: true, tsconfig: path.join(state.cwd, 'tsconfig.json'), reportFiles: [path.join(state.cwd, state.rc?.dir ?? 'src', '**')], silent: true, formatter: require('react-dev-utils/typescriptFormatter'), }), new CaseSensitivePathsPlugin({ debug: false, }), ].filter(Boolean); case 'production': return [ ...plugins, new ShakePlugin({ warnings: { global: false, module: false, }, }), // shouldInlineRuntimeChunk(state) && // new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]), new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional filename: '[name].[contenthash:8].css', chunkFilename: '[name].[contenthash:8].chunk.css', }), ]; default: return plugins; }}; const selectCmdPlugins = (state: BuildConfig) => { switch (state.cmd) { case 'build': return []; case 'start': return [new webpack.HotModuleReplacementPlugin()]; default: return unreachable(state.cmd); }}; const selectWebpackEntry = ( state: BuildConfig,): webpack.Configuration['entry'] => { let entry = state.rc?.webpack?.entry ?? `index`; if (typeof entry === 'string') { return path.join(selectAppPath(state), entry); } if (Array.isArray(entry)) { return entry.map(e => path.join(selectAppPath(state), e)); } if (typeof entry === 'object') { for (const [key, value] of Object.entries(entry)) { entry = { ...entry, [key]: path.join(selectAppPath(state), value), }; } } return entry;}; const selectFilename = (state: BuildConfig): string => { let filename = state.rc?.webpack?.output?.filename ?? '[name].js'; if (typeof filename === 'function') { filename = filename(state); if (typeof filename !== 'string') { throw new Error('rc.webpack.filename function should return a string.'); } } return filename;}; const selectPath = (state: BuildConfig) => path.join(state.cwd, state.rc?.webpack?.output?.path ?? 'dist/'); const selectOutput = (state: BuildConfig): webpack.Configuration['output'] => ({ path: selectPath(state), pathinfo: isEnvDevelopment(state), filename: selectFilename(state), // TODO: remove this when upgrading to webpack 5 futureEmitAssets: true, chunkFilename: isEnvProduction(state) ? '[name].[contenthash:8].chunk.js' : isEnvDevelopment(state) ? '[name].chunk.js' : undefined, // 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. // We inferred the "public path" (such as / or /my-project) from homepage. publicPath: selectPublicUrlOrPath(state), // Prevents conflicts when multiple Webpack runtimes (from different apps) // are used on the same page. jsonpFunction: `webpackJsonp${camelcase(state.name, { pascalCase: true, })}`, // this defaults to 'window', but by setting it to 'this' then // module chunks which are built will work in web workers as well. globalObject: 'this',}); const selectMinimizer = (state: BuildConfig) => [ // This is only used in production mode new TerserPlugin({ terserOptions: { parse: { // We want terser to parse ecma 8 code. However, we don't want it // to apply any minification steps that turns valid ecma 5 code // into invalid ecma 5 code. This is why the 'compress' and 'output' // sections only apply transformations that are ecma 5 safe // https://github.com/facebook/create-react-app/pull/4234 ecma: 8, }, compress: { ecma: 5, warnings: false, // 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, // Disabled because of an issue with Terser breaking valid code: // https://github.com/facebook/create-react-app/issues/5250 // Pending further investigation: // https://github.com/terser-js/terser/issues/120 inline: 2, }, mangle: { safari10: true, }, // Added for profiling in devtools keep_classnames: isEnvProductionProfile(), keep_fnames: isEnvProductionProfile(), output: { ecma: 5, 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, }, }, sourceMap: shouldUseSourceMap(), }), // This is only used in production mode new OptimizeCSSAssetsPlugin({ cssProcessorOptions: { parser: safePostCssParser, map: shouldUseSourceMap() ? { // `inline: false` forces the sourcemap to be output into a // separate file inline: false, // `annotation: true` appends the sourceMappingURL to the end of // the css file, helping the browser find the sourcemap annotation: true, } : false, }, cssProcessorPluginOptions: { preset: ['default', { minifyFontValues: { removeQuotes: false } }], }, }),]; Function `addHotReload` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.const addHotReload = ( entry: webpack.Configuration['entry'],): webpack.Configuration['entry'] => { const client = require.resolve('react-dev-utils/webpackHotDevClient'); if (typeof entry === 'string') { return [client, entry]; } if (Array.isArray(entry)) { return [client, ...entry]; } // @TODO(mAAdhaTTah) what to do if function provided? if (typeof entry === 'function') { return entry; } if (typeof entry === 'object') { for (const key in entry) { let value = entry[key]; if (Array.isArray(value)) { value = [client, ...value]; } if (typeof value === 'string') { value = [client, value]; } entry[key] = value; } } return entry;}; Function `selectWebpackConfig` has 72 lines of code (exceeds 25 allowed). Consider refactoring.export const selectWebpackConfig = ( state: BuildConfig,): webpack.Configuration => { let entry = selectWebpackEntry(state); if (state.cmd === 'start') { entry = addHotReload(entry); } const config: webpack.Configuration = { entry, output: selectOutput(state), bail: isEnvProduction(state), mode: state.env, devtool: isEnvProduction(state) ? 'source-map' : 'cheap-module-source-map', resolve: { mainFields: ['module', 'main'], // 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.mjs', 'mjs', 'web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', ] .map(ext => `.${ext}`) .filter(ext => state.extension === 'ts' || !ext.includes('ts')), 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', // Allows for better profiling with ReactDevTools ...(isEnvProductionProfile() && { 'react-dom$': 'react-dom/profiling', 'scheduler/tracing': 'scheduler/tracing-profiling', }), ...{ // Add additional aliases here. }, }, plugins: [ // @TODO(mAAdhaTTah) revisit if we want to add these plugins to the build // Adds support for installing with Plug'n'Play, leading to faster installs and adding // guards against forgotten dependencies and such. // PnpWebpackPlugin, // 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]) ], }, // resolveLoader: { // plugins: [ // // Also related to Plug'n'Play, but this time it tells Webpack to load its loaders // // from the current package. // PnpWebpackPlugin.moduleLoader(module), // ], // }, module: { strictExportPresence: true, rules: [...selectDefaultRules(state), ...selectEnvRules(state)], }, plugins: [ ...selectDefaultPlugins(state), ...selectEnvPlugins(state), ...selectCmdPlugins(state), ], optimization: { minimize: isEnvProduction(state), minimizer: selectMinimizer(state), // 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 // @TODO(mAAdhaTTah) figure out why this results in no app bootstrapping when running start // splitChunks: { // chunks: 'all', // name: false // }, // Keep the runtime chunk separated to enable long term caching // https://twitter.com/wSokra/status/969679223278505985 // https://github.com/facebook/create-react-app/issues/5358 runtimeChunk: { name: entrypoint => `runtime-${entrypoint.name}`, }, }, // 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: { module: 'empty', dgram: 'empty', dns: 'mock', fs: 'empty', http2: 'empty', net: 'empty', tls: 'empty', child_process: 'empty', }, }; return ( state.rc?.webpack?.modifier?.(config, { env: state.env, cmd: state.cmd, }) ?? config );}; export const selectServerConfig = ( state: BuildConfig,): WebpackDevServer.Configuration => ({ // WebpackDevServer 2.4.3 introduced a security fix that prevents remote // websites from potentially accessing local content through DNS rebinding: // https://github.com/webpack/webpack-dev-server/issues/887 // https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a // However, it made several existing use cases such as development in cloud // environment or subdomains in development significantly more complicated: // https://github.com/facebook/create-react-app/issues/2271 // https://github.com/facebook/create-react-app/issues/2233 // While we're investigating better solutions, for now we will take a // compromise. Since our WDS configuration only serves files in the `public` // folder we won't consider accessing them a vulnerability. However, if you // use the `proxy` feature, it gets more dangerous because it can expose // remote code execution vulnerabilities in backends like Django and Rails. // So we will disable the host check normally, but enable it if you have // specified the `proxy` setting. Finally, we let you override it if you // really know what you're doing with a special environment variable. // @TODO(mAAdhaTTah) make this configurable disableHostCheck: false, // Enable gzip compression of generated files. compress: true, // Silence WebpackDevServer's own logs since they're generally not useful. // It will still show compile warnings and errors with this setting. clientLogLevel: 'silent', // By default WebpackDevServer serves physical files from current directory // in addition to all the virtual build products that it serves from memory. // This is confusing because those files won’t automatically be available in // production build folder unless we copy them. However, copying the whole // project directory is dangerous because we may expose sensitive files. // Instead, we establish a convention that only files in `public` directory // get served. Our build script will copy `public` into the `build` folder. // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%: // <link rel="icon" href="%PUBLIC_URL%/favicon.ico"> // In JavaScript code, you can access it with `process.env.PUBLIC_URL`. // Note that we only recommend to use `public` folder as an escape hatch // for files like `favicon.ico`, `manifest.json`, and libraries that are // for some reason broken when imported through Webpack. If you just want to // use an image, put it in `src` and `import` it from JavaScript instead. contentBase: path.join(state.cwd, 'public'), // By default files from `contentBase` will not trigger a page reload. watchContentBase: true, // Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint // for the WebpackDevServer client so it can learn when the files were // updated. The WebpackDevServer client is included as an entry point // in the Webpack development configuration. Note that only changes // to CSS are currently hot reloaded. JS changes will refresh the browser. hot: true, // Use 'ws' instead of 'sockjs-node' on server since we're using native // websockets in `webpackHotDevClient`. transportMode: 'ws', // Prevent a WS client from getting injected as we're already including // `webpackHotDevClient`. injectClient: false, // Enable custom sockjs pathname for websocket connection to hot reloading server. // Enable custom sockjs hostname, pathname and port for websocket connection // to hot reloading server. // @TODO(mAAdhaTTah) make these 3 configurable // sockHost, // sockPath, // sockPort, // It is important to tell WebpackDevServer to use the same "publicPath" path as // we specified in the Webpack config. When homepage is '.', default to serving // from the root. // remove last slash so user can land on `/test` instead of `/test/` // publicPath: selectPublicPath(), // WebpackDevServer is noisy by default so we emit custom message instead // by listening to the compiler events with `compiler.hooks[...].tap` calls above. quiet: true, // Reportedly, this avoids CPU overload on some systems. // https://github.com/facebook/create-react-app/issues/293 // src/node_modules is not ignored to support absolute imports // https://github.com/facebook/create-react-app/issues/1065 watchOptions: { ignored: ignoredFiles(selectAppPath(state)), }, // https: selectHttpsConfig(state), // host: selectHost(state), overlay: false, historyApiFallback: { // Paths with dots should still use the history fallback. // See https://github.com/facebook/create-react-app/issues/387. disableDotRule: true, index: selectPublicUrlOrPath(state), }, // public: selectAllowHosts(state), // `proxy` is run between `before` and `after` `webpack-dev-server` hooks // proxy: selectProxy(state), before(app, server) { // Keep `evalSourceMapMiddleware` and `errorOverlayMiddleware` // middlewares before `redirectServedPath` otherwise will not have any effect // This lets us fetch source contents from webpack for the error overlay app.use(evalSourceMapMiddleware(server)); // This lets us open files from the runtime error overlay. app.use(errorOverlayMiddleware()); }, after(app) { // Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match // app.use(redirectServedPath(selectPublicUrlOrPath(state))); // This service worker file is effectively a 'no-op' that will reset any // previous service worker registered for the same host:port combination. // We do this in development to avoid hitting the production cache if // it used the same host and port. // https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432 app.use(noopServiceWorkerMiddleware()); },});