Changeset View
Changeset View
Standalone View
Standalone View
src/cashtab/config/webpack.config.js
- This file was added.
"use strict"; | |||||
const darkTheme = require("@ant-design/dark-theme"); | |||||
const fs = require("fs"); | |||||
const isWsl = require("is-wsl"); | |||||
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 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 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"); | |||||
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 workboxPlugin = require('workbox-webpack-plugin'); | |||||
const postcssNormalize = require("postcss-normalize"); | |||||
const appPackageJson = require(paths.appPackageJson); | |||||
// 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"; | |||||
const imageInlineSizeLimit = parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || "10000"); | |||||
// 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)$/; | |||||
// This is the production and development configuration. | |||||
// It is focused on developer experience, fast rebuilds, and a minimal bundle. | |||||
module.exports = function(webpackEnv) { | |||||
const isEnvDevelopment = webpackEnv === "development"; | |||||
const isEnvProduction = webpackEnv === "production"; | |||||
// 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. | |||||
// In development, we always serve from the root. This makes config easier. | |||||
const publicPath = isEnvProduction ? paths.servedPath : isEnvDevelopment && "/"; | |||||
// 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 === "./"; | |||||
// `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 = isEnvProduction ? publicPath.slice(0, -1) : isEnvDevelopment && ""; | |||||
// Get environment variables to inject into our app. | |||||
const env = getClientEnvironment(publicUrl); | |||||
// common function to get style loaders | |||||
const getStyleLoaders = (cssOptions, preProcessor) => { | |||||
const loaders = [ | |||||
isEnvDevelopment && require.resolve("style-loader"), | |||||
isEnvProduction && { | |||||
loader: MiniCssExtractPlugin.loader, | |||||
options: shouldUseRelativeAssetPaths ? { publicPath: "../../" } : {} | |||||
}, | |||||
{ | |||||
loader: require.resolve("css-loader"), | |||||
options: cssOptions | |||||
}, | |||||
{ | |||||
loader: require.resolve("less-loader"), | |||||
options: { | |||||
modifyVars: { | |||||
"@layout-sider-background": "#131720", | |||||
"@layout-trigger-background": "#20242D", | |||||
"@light": "#7F7F7F", | |||||
"@dark": "#000", | |||||
"@heading-color": "fade(@light, 85)", | |||||
"@text-color": "fade(@light, 65)", | |||||
"@text-color-secondary": "fade(@light, 45)", | |||||
"@disabled-color": "fade(@light, 25)", | |||||
"@primary-5": "#40a9ff", | |||||
"@primary-color": "#20242D", | |||||
"@outline-color": "@primary-color", | |||||
"@icon-color": "fade(@light, 65)", | |||||
"@icon-color-hover": "fade(@light, 85)", | |||||
"@primary-6": "#096dd9", | |||||
"@border-color-base": "@border-color-split", | |||||
"@btn-default-color": "@heading-color", | |||||
"@btn-default-bg": "#444457", | |||||
"@btn-default-border": "#444457", | |||||
"@btn-ghost-color": "fade(@light, 45)", | |||||
"@btn-ghost-border": "fade(@light, 45)", | |||||
"@input-color": "@text-color", | |||||
"@input-bg": "#3b3b4d", | |||||
"@input-disabled-bg": "#4c4c61", | |||||
"@input-placeholder-color": "@text-color-secondary", | |||||
"@input-hover-border-color": "fade(@light, 10)", | |||||
"@checkbox-check-color": "#3b3b4d", | |||||
"@checkbox-color": "@primary-color", | |||||
"@select-border-color": "#3b3b4d", | |||||
"@item-active-bg": "#272733", | |||||
"@border-color-split": "#17171f", | |||||
"@menu-dark-bg": "#131720", | |||||
"@body-background": "#FBFBFD", | |||||
"@component-background": "#FFFFFF", | |||||
"@layout-body-background": "#FBFBFD", | |||||
"@tooltip-bg": "#191922", | |||||
"@tooltip-arrow-color": "#191922", | |||||
"@popover-bg": "#2d2d3b", | |||||
"@success-color": "#00a854", | |||||
"@info-color": "@primary-color", | |||||
"@warning-color": "#ffbf00", | |||||
"@error-color": "#f04134", | |||||
"@menu-bg": "#20242D", | |||||
"@menu-item-active-bg": "fade(@light, 5)", | |||||
"@menu-highlight-color": "@light", | |||||
"@card-background": "@component-background", | |||||
"@card-hover-border": "#383847", | |||||
"@card-actions-background": "#FBFCFD", | |||||
"@tail-color": "fade(@light, 10)", | |||||
"@radio-button-bg": "transparent", | |||||
"@radio-button-checked-bg": "transparent", | |||||
"@radio-dot-color": "@primary-color", | |||||
"@table-row-hover-bg": "#383847", | |||||
"@item-hover-bg": "#383847", | |||||
"@alert-text-color": "fade(@dark, 65%)", | |||||
"@tabs-horizontal-padding": "12px 0", | |||||
// zIndex': 'notification > popover > tooltip | |||||
"@zindex-notification": "1063", | |||||
"@zindex-popover": "1061", | |||||
"@zindex-tooltip": "1060", | |||||
// width | |||||
"@anchor-border-width": "1px", | |||||
// margin | |||||
"@form-item-margin-bottom": "24px", | |||||
"@menu-item-vertical-margin": "0px", | |||||
"@menu-item-boundary-margin": "0px", | |||||
// size | |||||
"@font-size-base": "14px", | |||||
"@font-size-lg": "16px", | |||||
"@screen-xl": "1208px", | |||||
"@screen-lg": "1024px", | |||||
"@screen-md": "768px", | |||||
// 移动 | |||||
"@screen-sm": "767.9px", | |||||
// 超小屏 | |||||
"@screen-xs": "375px", | |||||
"@alert-message-color": "@popover-bg", | |||||
"@background-color-light": "@popover-bg", | |||||
"@layout-header-background": "@menu-dark-bg", | |||||
// 官网 | |||||
"@site-text-color": "@text-color", | |||||
"@site-border-color-split": "fade(@light, 5)", | |||||
"@site-heading-color": "@heading-color", | |||||
"@site-header-box-shadow": | |||||
"0 0.3px 0.9px rgba(0, 0, 0, 0.12), 0 1.6px 3.6px rgba(0, 0, 0, 0.12)", | |||||
"@home-text-color": "@text-color", | |||||
//自定义需要找设计师 | |||||
"@gray-8": "@text-color", | |||||
"@background-color-base": "#FBFBFD", | |||||
"@skeleton-color": "rgba(0,0,0,0.8)", | |||||
// pro | |||||
"@pro-header-box-shadow": "@site-header-box-shadow" | |||||
}, | |||||
javascriptEnabled: true | |||||
} | |||||
}, | |||||
{ | |||||
// 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 && shouldUseSourceMap | |||||
} | |||||
} | |||||
].filter(Boolean); | |||||
if (preProcessor) { | |||||
loaders.push( | |||||
{ | |||||
loader: require.resolve("resolve-url-loader"), | |||||
options: { | |||||
sourceMap: isEnvProduction && shouldUseSourceMap | |||||
} | |||||
}, | |||||
{ | |||||
loader: require.resolve(preProcessor), | |||||
options: { | |||||
sourceMap: true | |||||
} | |||||
} | |||||
); | |||||
} | |||||
return loaders; | |||||
}; | |||||
return { | |||||
mode: isEnvProduction ? "production" : isEnvDevelopment && "development", | |||||
// Stop compilation early in production | |||||
bail: isEnvProduction, | |||||
devtool: isEnvProduction | |||||
? shouldUseSourceMap | |||||
? "source-map" | |||||
: false | |||||
: isEnvDevelopment && "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. | |||||
entry: [ | |||||
// 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'), | |||||
isEnvDevelopment && 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. | |||||
].filter(Boolean), | |||||
output: { | |||||
// The build folder. | |||||
path: isEnvProduction ? paths.appBuild : undefined, | |||||
// Add /* filename */ comments to generated require()s in the output. | |||||
pathinfo: isEnvDevelopment, | |||||
// There will be one main bundle, and one file per asynchronous chunk. | |||||
// 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, | |||||
// There are also additional JS chunk files if you use code splitting. | |||||
chunkFilename: isEnvProduction | |||||
? "static/js/[name].[contenthash:8].chunk.js" | |||||
: isEnvDevelopment && "static/js/[name].chunk.js", | |||||
// We inferred the "public path" (such as / or /my-project) from homepage. | |||||
// We use "/" in development. | |||||
publicPath: publicPath, | |||||
// Point sourcemap entries to original disk location (format as URL on Windows) | |||||
devtoolModuleFilenameTemplate: isEnvProduction | |||||
? info => path.relative(paths.appSrc, info.absoluteResourcePath).replace(/\\/g, "/") | |||||
: isEnvDevelopment && (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}` | |||||
}, | |||||
optimization: { | |||||
minimize: false, | |||||
minimizer: [ | |||||
// 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 | |||||
}, | |||||
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 | |||||
} | |||||
}, | |||||
// 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 | |||||
} | |||||
}) | |||||
], | |||||
// 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 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}` | |||||
} | |||||
}, | |||||
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", paths.appNodeModules].concat(modules.additionalModulePaths || []), | |||||
// 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.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: [ | |||||
// 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 | |||||
}, | |||||
{ | |||||
// "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: imageInlineSizeLimit, | |||||
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.appSrc, | |||||
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?-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/ | |||||
// directory for faster rebuilds. | |||||
cacheDirectory: true, | |||||
// See #6846 for context on why cacheCompression is disabled | |||||
cacheCompression: false, | |||||
compact: isEnvProduction | |||||
} | |||||
}, | |||||
// 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, | |||||
// See #6846 for context on why cacheCompression is disabled | |||||
cacheCompression: false, | |||||
// 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 <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: getStyleLoaders({ | |||||
importLoaders: 1, | |||||
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 | |||||
}, | |||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules) | |||||
// using the extension .module.css | |||||
{ | |||||
test: cssModuleRegex, | |||||
use: getStyleLoaders({ | |||||
importLoaders: 1, | |||||
sourceMap: isEnvProduction && shouldUseSourceMap, | |||||
modules: true, | |||||
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: getStyleLoaders( | |||||
{ | |||||
importLoaders: 2, | |||||
sourceMap: isEnvProduction && 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, | |||||
use: getStyleLoaders( | |||||
{ | |||||
importLoaders: 2, | |||||
sourceMap: isEnvProduction && shouldUseSourceMap, | |||||
modules: true, | |||||
getLocalIdent: getCSSModuleLocalIdent | |||||
}, | |||||
"sass-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. | |||||
{ | |||||
loader: require.resolve("file-loader"), | |||||
// 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|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 <script> injected. | |||||
new HtmlWebpackPlugin( | |||||
Object.assign( | |||||
{}, | |||||
{ | |||||
inject: true, | |||||
template: paths.appHtml | |||||
}, | |||||
isEnvProduction | |||||
? { | |||||
minify: { | |||||
removeComments: true, | |||||
collapseWhitespace: true, | |||||
removeRedundantAttributes: true, | |||||
useShortDoctype: true, | |||||
removeEmptyAttributes: true, | |||||
removeStyleLinkTypeAttributes: true, | |||||
keepClosingSlash: true, | |||||
minifyJS: true, | |||||
minifyCSS: true, | |||||
minifyURLs: true | |||||
} | |||||
} | |||||
: undefined | |||||
) | |||||
), | |||||
// Inlines the webpack runtime script. This script is too small to warrant | |||||
// a network request. | |||||
// https://github.com/facebook/create-react-app/issues/5358 | |||||
isEnvProduction && | |||||
shouldInlineRuntimeChunk && | |||||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]), | |||||
// 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. | |||||
// In development, this will be an empty string. | |||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw), | |||||
// This gives some necessary context to module not found errors, such as | |||||
// the requesting resource. | |||||
new ModuleNotFoundPlugin(paths.appPath), | |||||
// 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 is set to production | |||||
// during a production build. | |||||
// Otherwise React will be compiled in the very slow development mode. | |||||
new webpack.DefinePlugin(env.stringified), | |||||
// This is necessary to emit hot updates (currently CSS only): | |||||
isEnvDevelopment && 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 | |||||
isEnvDevelopment && new CaseSensitivePathsPlugin(), | |||||
// 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 | |||||
isEnvDevelopment && new WatchMissingNodeModulesPlugin(paths.appNodeModules), | |||||
isEnvProduction && | |||||
new MiniCssExtractPlugin({ | |||||
// Options similar to the same options in webpackOptions.output | |||||
// both options are optional | |||||
filename: "static/css/[name].[contenthash:8].css", | |||||
chunkFilename: "static/css/[name].[contenthash:8].chunk.css" | |||||
}), | |||||
// 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: publicPath, | |||||
generate: (seed, files) => { | |||||
const manifestFiles = files.reduce(function(manifest, file) { | |||||
manifest[file.name] = file.path; | |||||
return manifest; | |||||
}, seed); | |||||
return { | |||||
files: manifestFiles | |||||
}; | |||||
} | |||||
}), | |||||
// 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$/), | |||||
// TypeScript type checking | |||||
useTypeScript && | |||||
new ForkTsCheckerWebpackPlugin({ | |||||
typescript: resolve.sync("typescript", { | |||||
basedir: paths.appNodeModules | |||||
}), | |||||
async: isEnvDevelopment, | |||||
useTypescriptIncrementalApi: true, | |||||
checkSyntacticErrors: true, | |||||
resolveModuleNameModule: process.versions.pnp ? `${__dirname}/pnpTs.js` : undefined, | |||||
resolveTypeReferenceDirectiveModule: process.versions.pnp | |||||
? `${__dirname}/pnpTs.js` | |||||
: undefined, | |||||
tsconfig: paths.appTsConfig, | |||||
reportFiles: [ | |||||
"**", | |||||
"!**/__tests__/**", | |||||
"!**/?(*.)(spec|test).*", | |||||
"!**/src/setupProxy.*", | |||||
"!**/src/setupTests.*" | |||||
], | |||||
silent: true, | |||||
// The formatter is invoked directly in WebpackDevServerUtils during development | |||||
formatter: isEnvProduction ? typescriptFormatter : undefined | |||||
}), | |||||
new workboxPlugin.InjectManifest({ | |||||
swSrc: './src/serviceWorker.js', | |||||
swDest: 'serviceWorker.js' | |||||
}) | |||||
].filter(Boolean), | |||||
// 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" | |||||
}, | |||||
// Turn off performance processing because we utilize | |||||
// our own hints via the FileSizeReporter | |||||
performance: false | |||||
}; | |||||
}; |