diff --git a/config/webpack.config.js b/config/webpack.config.js index 7f0e9b1..b30ebe5 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -11,12 +11,10 @@ const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin"); const InlineChunkHtmlPlugin = require("react-dev-utils/InlineChunkHtmlPlugin"); const TerserPlugin = require("terser-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); -const safePostCssParser = require("postcss-safe-parser"); -const ManifestPlugin = require("webpack-manifest-plugin"); +const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); +const { WebpackManifestPlugin } = require("webpack-manifest-plugin"); const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin"); const WorkboxWebpackPlugin = require("workbox-webpack-plugin"); -const WatchMissingNodeModulesPlugin = require("react-dev-utils/WatchMissingNodeModulesPlugin"); const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin"); const getCSSModuleLocalIdent = require("react-dev-utils/getCSSModuleLocalIdent"); const paths = require("./paths"); @@ -24,8 +22,7 @@ const modules = require("./modules"); const getClientEnvironment = require("./env"); const ModuleNotFoundPlugin = require("react-dev-utils/ModuleNotFoundPlugin"); const ForkTsCheckerWebpackPlugin = require("react-dev-utils/ForkTsCheckerWebpackPlugin"); -const typescriptFormatter = require("react-dev-utils/typescriptFormatter"); -const eslint = require("eslint"); +const ESLintPlugin = require("eslint-webpack-plugin"); const postcssNormalize = require("postcss-normalize"); @@ -52,7 +49,7 @@ const sassModuleRegex = /\.module\.(scss|sass)$/; // This is the production and development configuration. // It is focused on developer experience, fast rebuilds, and a minimal bundle. -module.exports = function(webpackEnv) { +module.exports = function (webpackEnv) { const isEnvDevelopment = webpackEnv === "development"; const isEnvProduction = webpackEnv === "production"; @@ -86,11 +83,11 @@ module.exports = function(webpackEnv) { isEnvDevelopment && require.resolve("style-loader"), isEnvProduction && { loader: MiniCssExtractPlugin.loader, - options: shouldUseRelativeAssetPaths ? { publicPath: "../../" } : {} + options: shouldUseRelativeAssetPaths ? { publicPath: "../../" } : {}, }, { loader: require.resolve("css-loader"), - options: cssOptions + options: cssOptions, }, { // Options for PostCSS as we reference these options twice @@ -105,32 +102,32 @@ module.exports = function(webpackEnv) { require("postcss-flexbugs-fixes"), require("postcss-preset-env")({ autoprefixer: { - flexbox: "no-2009" + flexbox: "no-2009", }, - stage: 3 + 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() + postcssNormalize(), ], - sourceMap: isEnvProduction && shouldUseSourceMap - } - } + sourceMap: isEnvProduction && shouldUseSourceMap, + }, + }, ].filter(Boolean); if (preProcessor) { loaders.push( { loader: require.resolve("resolve-url-loader"), options: { - sourceMap: isEnvProduction && shouldUseSourceMap - } + sourceMap: isEnvProduction && shouldUseSourceMap, + }, }, { loader: require.resolve(preProcessor), options: { - sourceMap: true - } + sourceMap: true, + }, } ); } @@ -162,7 +159,7 @@ module.exports = function(webpackEnv) { isEnvDevelopment && require.resolve("react-dev-utils/webpackHotDevClient"), // Finally, this is your app's code: - paths.appIndexJs + 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. @@ -176,9 +173,7 @@ module.exports = function(webpackEnv) { // In development, it does not produce real files. filename: isEnvProduction ? "static/js/[name].[contenthash:8].js" - : isEnvDevelopment && "static/js/bundle.js", - // TODO: remove this when upgrading to webpack 5 - futureEmitAssets: true, + : isEnvDevelopment && "static/js/[name].js", // There are also additional JS chunk files if you use code splitting. chunkFilename: isEnvProduction ? "static/js/[name].[contenthash:8].chunk.js" @@ -188,18 +183,19 @@ module.exports = function(webpackEnv) { publicPath: publicPath, // Point sourcemap entries to original disk location (format as URL on Windows) devtoolModuleFilenameTemplate: isEnvProduction - ? info => + ? (info) => path .relative(paths.appSrc, info.absoluteResourcePath) .replace(/\\/g, "/") : isEnvDevelopment && - (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, "/")), + ((info) => + path.resolve(info.absoluteResourcePath).replace(/\\/g, "/")), // Prevents conflicts when multiple Webpack runtimes (from different apps) // are used on the same page. - jsonpFunction: `webpackJsonp${appPackageJson.name}`, + chunkLoadingGlobal: `webpackJsonp${appPackageJson.name}`, // 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" + globalObject: "this", }, optimization: { minimize: isEnvProduction, @@ -213,7 +209,7 @@ module.exports = function(webpackEnv) { // 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 + ecma: 8, }, compress: { ecma: 5, @@ -227,10 +223,10 @@ module.exports = function(webpackEnv) { // https://github.com/facebook/create-react-app/issues/5250 // Pending further investigation: // https://github.com/terser-js/terser/issues/120 - inline: 2 + inline: 2, }, mangle: { - safari10: true + safari10: true, }, // Added for profiling in devtools keep_classnames: isEnvProductionProfile, @@ -240,49 +236,37 @@ module.exports = function(webpackEnv) { 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 - } + ascii_only: true, + }, }, // Use multi-process parallel running to improve the build speed // Default number of concurrent runs: os.cpus().length - 1 // Disabled on WSL (Windows Subsystem for Linux) due to an issue with Terser // https://github.com/webpack-contrib/terser-webpack-plugin/issues/21 parallel: !isWsl, - // Enable file caching - cache: 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 - } - }) + new CssMinimizerPlugin(), ], // 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 + 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}` - } + name: (entrypoint) => `runtime-${entrypoint.name}`, + }, }, + plugins: [ + new ESLintPlugin({ + cache: 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" @@ -298,8 +282,8 @@ module.exports = function(webpackEnv) { // `web` extension prefixes have been added for better support // for React Native Web. extensions: paths.moduleFileExtensions - .map(ext => `.${ext}`) - .filter(ext => useTypeScript || !ext.includes("ts")), + .map((ext) => `.${ext}`) + .filter((ext) => useTypeScript || !ext.includes("ts")), alias: { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ @@ -307,9 +291,9 @@ module.exports = function(webpackEnv) { // Allows for better profiling with ReactDevTools ...(isEnvProductionProfile && { "react-dom$": "react-dom/profiling", - "scheduler/tracing": "scheduler/tracing-profiling" + "scheduler/tracing": "scheduler/tracing-profiling", }), - ...(modules.webpackAliases || {}) + ...(modules.webpackAliases || {}), }, plugins: [ // Adds support for installing with Plug'n'Play, leading to faster installs and adding @@ -320,40 +304,32 @@ module.exports = function(webpackEnv) { // 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]) - ] + new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), + ], + // 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. + fallback: { + module: "empty", + dgram: "empty", + dns: "mock", + fs: "empty", + http2: "empty", + net: "empty", + tls: "empty", + child_process: "empty", + url: require.resolve("url/"), + }, }, 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) - ] + PnpWebpackPlugin.moduleLoader(module), + ], }, 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|mjs|jsx|ts|tsx)$/, - enforce: "pre", - use: [ - { - options: { - cache: true, - formatter: require.resolve("react-dev-utils/eslintFormatter"), - eslintPath: require.resolve("eslint"), - resolvePluginsRelativeTo: __dirname - }, - loader: require.resolve("eslint-loader") - } - ], - include: paths.appSrc - }, // We nest everything inside a oneOf, because worklets need special processing. { oneOf: [ @@ -361,7 +337,7 @@ module.exports = function(webpackEnv) { test: /\.worklet\.(js|ts)$/, use: [ { - loader: "worklet-loader" + loader: "worklet-loader", }, // Run worklets through babel // because of course webpack applies loaders right-to-left @@ -379,11 +355,11 @@ module.exports = function(webpackEnv) { loaderMap: { svg: { ReactComponent: - "@svgr/webpack?-svgo,+titleProp,+ref![path]" - } - } - } - ] + "@svgr/webpack?-svgo,+titleProp,+ref![path]", + }, + }, + }, + ], ], // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ @@ -391,10 +367,10 @@ module.exports = function(webpackEnv) { cacheDirectory: true, // See #6846 for context on why cacheCompression is disabled cacheCompression: false, - compact: isEnvProduction - } + compact: isEnvProduction, + }, }, - ] + ], }, { // "oneOf" will traverse all following loaders until one will @@ -409,8 +385,8 @@ module.exports = function(webpackEnv) { loader: require.resolve("url-loader"), options: { limit: imageInlineSizeLimit, - name: "static/media/[name].[hash:8].[ext]" - } + name: "static/media/[name].[hash:8].[ext]", + }, }, // Process application JS with Babel. // The preset includes JSX, Flow, TypeScript, and some ESnext features. @@ -430,11 +406,11 @@ module.exports = function(webpackEnv) { loaderMap: { svg: { ReactComponent: - "@svgr/webpack?-svgo,+titleProp,+ref![path]" - } - } - } - ] + "@svgr/webpack?-svgo,+titleProp,+ref![path]", + }, + }, + }, + ], ], // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ @@ -442,8 +418,8 @@ module.exports = function(webpackEnv) { cacheDirectory: true, // See #6846 for context on why cacheCompression is disabled cacheCompression: false, - compact: isEnvProduction - } + compact: isEnvProduction, + }, }, // Process any JS outside of the app with Babel. // Unlike the application JS, we only compile the standard ES features. @@ -458,8 +434,8 @@ module.exports = function(webpackEnv) { presets: [ [ require.resolve("babel-preset-react-app/dependencies"), - { helpers: true } - ] + { helpers: true }, + ], ], cacheDirectory: true, // See #6846 for context on why cacheCompression is disabled @@ -469,8 +445,8 @@ module.exports = function(webpackEnv) { // 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 - } + sourceMaps: false, + }, }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. @@ -484,13 +460,13 @@ module.exports = function(webpackEnv) { exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, - sourceMap: isEnvProduction && shouldUseSourceMap + sourceMap: isEnvProduction && 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 + sideEffects: true, }, // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css @@ -500,8 +476,8 @@ module.exports = function(webpackEnv) { importLoaders: 1, sourceMap: isEnvProduction && shouldUseSourceMap, modules: true, - getLocalIdent: getCSSModuleLocalIdent - }) + getLocalIdent: getCSSModuleLocalIdent, + }), }, // Opt-in support for SASS (using .scss or .sass extensions). // By default we support SASS Modules with the @@ -512,7 +488,7 @@ module.exports = function(webpackEnv) { use: getStyleLoaders( { importLoaders: 2, - sourceMap: isEnvProduction && shouldUseSourceMap + sourceMap: isEnvProduction && shouldUseSourceMap, }, "sass-loader" ), @@ -520,7 +496,7 @@ module.exports = function(webpackEnv) { // 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 + sideEffects: true, }, // Adds support for CSS Modules, but using SASS // using the extension .module.scss or .module.sass @@ -531,10 +507,10 @@ module.exports = function(webpackEnv) { importLoaders: 2, sourceMap: isEnvProduction && shouldUseSourceMap, modules: true, - getLocalIdent: getCSSModuleLocalIdent + getLocalIdent: getCSSModuleLocalIdent, }, "sass-loader" - ) + ), }, // "file" loader makes sure those assets get served by WebpackDevServer. // When you `import` an asset, you get its (virtual) filename. @@ -549,16 +525,16 @@ module.exports = function(webpackEnv) { // by webpacks internal loaders. exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/], options: { - name: "static/media/[name].[hash:8].[ext]" - } - } + 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. - ] - } - ] - } - ] + ], + }, + ], + }, + ], }, plugins: [ // Generates an `index.html` file with the