'use strict'; const fs = require('fs'); const path = require('path'); const webpack = require('webpack'); const resolve = require('resolve'); const PnpWebpackPlugin = require('pnp-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); const paths = require('./paths'); const getClientEnvironment = require('./env'); const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt'); const typescriptFormatter = require('react-dev-utils/typescriptFormatter'); const getPackageJson = require('./getPackageJson'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); // 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'; // Some apps do not need the benefits of saving a web request, so not inlining the chunk // makes for a smoother build process. const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== '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); // Check if TypeScript is setup const useTypeScript = fs.existsSync(paths.appTsConfig); // style files regexes const cssRegex = /\.css$/; const cssModuleRegex = /\.module\.css$/; const sassRegex = /\.(scss|sass)$/; const sassModuleRegex = /\.module\.(scss|sass)$/; const { version, name, license, repository, author, } = getPackageJson('version', 'name', 'license', 'repository', 'author'); const banner = ` ${name} v${version} (Non-minified build) ${repository.url} Copyright (c) ${author.replace(/ *\<[^)]*\> */g, " ")} This source code is licensed under a dual license system ${license}, as found in the LICENSE file in the root directory of this source tree. `; // common function to get style loaders const getStyleLoaders = (cssOptions, preProcessor) => { const loaders = [ { loader: MiniCssExtractPlugin.loader, options: Object.assign( {}, shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined ), }, { 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, }), ], sourceMap: shouldUseSourceMap, }, }, ]; if (preProcessor) { loaders.push({ loader: require.resolve(preProcessor), options: { sourceMap: shouldUseSourceMap, }, }); } return loaders; }; // 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: false, // In production, we only want to load the app code. entry: [paths.appLibIndexJs], 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: 'simple-keyboard.js', chunkFilename: 'index.[chunkhash:8].chunk.js', // We inferred the "public path" (such as / or /my-project) from homepage. publicPath: publicPath, library: "SimpleKeyboard", libraryTarget: 'umd', umdNamedDefine: true, // Point sourcemap entries to original disk location (format as URL on Windows) devtoolModuleFilenameTemplate: info => path .relative(paths.appSrcLib, info.absoluteResourcePath) .replace(/\\/g, '/'), }, optimization: { minimizer: [ // we specify a custom UglifyJsPlugin here to get source maps in production new UglifyJsPlugin({ cache: false, parallel: false, uglifyOptions: { output: { comments: true, beautify: true, braces: true, indent_level: 2 }, mangle: false, compress: false }, sourceMap: false }), new webpack.BannerPlugin({ banner: banner, entryOnly: 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/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: paths.moduleFileExtensions .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/ 'react-native': 'react-native-web', }, plugins: [ // 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.appSrcLib, [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: [ // 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)$/, enforce: 'pre', use: [ { options: { formatter: require.resolve('react-dev-utils/eslintFormatter'), eslintPath: require.resolve('eslint'), }, loader: require.resolve('eslint-loader'), }, ], include: paths.appSrcLib, }, { // "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, TypeScript and some ESnext features. { test: /\.(js|mjs|jsx|ts|tsx)$/, include: paths.appSrcLib, loader: require.resolve('babel-loader'), options: { customize: require.resolve( 'babel-preset-react-app/webpack-overrides' ), plugins: [ [ require.resolve('babel-plugin-named-asset-import'), { loaderMap: { svg: { ReactComponent: '@svgr/webpack?-prettier,-svgo![path]', }, }, }, ], ], cacheDirectory: true, // Save disk space when time isn't as important cacheCompression: true, compact: true, }, }, // Process any JS outside of the app with Babel. // Unlike the application JS, we only compile the standard ES features. { test: /\.(js|mjs)$/, exclude: /@babel(?:\/|\\{1,2})runtime/, loader: require.resolve('babel-loader'), options: { babelrc: false, configFile: false, compact: false, presets: [ [ require.resolve('babel-preset-react-app/dependencies'), { helpers: true }, ], ], cacheDirectory: true, // Save disk space when time isn't as important cacheCompression: 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. // `MiniCSSExtractPlugin` extracts styles into CSS // files. If you use code splitting, async bundles will have their own separate CSS chunk file. // By default we support CSS Modules with the extension .module.css { test: cssRegex, exclude: cssModuleRegex, loader: getStyleLoaders({ importLoaders: 1, sourceMap: 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, loader: getStyleLoaders({ importLoaders: 1, sourceMap: shouldUseSourceMap, modules: true, getLocalIdent: getCSSModuleLocalIdent, }), }, // Opt-in support for SASS. The logic here is somewhat similar // as in the CSS routine, except that "sass-loader" runs first // to compile SASS files into CSS. // By default we support SASS Modules with the // extensions .module.scss or .module.sass { test: sassRegex, exclude: sassModuleRegex, loader: getStyleLoaders( { importLoaders: 2, sourceMap: shouldUseSourceMap, }, '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, loader: getStyleLoaders( { importLoaders: 2, sourceMap: shouldUseSourceMap, modules: true, getLocalIdent: getCSSModuleLocalIdent, }, 'sass-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|mjs|jsx|ts|tsx)$/, /\.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. ], }, ], }, plugins: [ // Generates an `index.html` file with the