2023-04-10 10:05:22 -07:00
|
|
|
/* eslint-env node */
|
2022-08-10 16:38:23 -07:00
|
|
|
const { VanillaExtractPlugin } = require('@vanilla-extract/webpack-plugin')
|
2023-05-15 14:07:05 -07:00
|
|
|
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
|
2023-04-13 12:43:47 -07:00
|
|
|
const { execSync } = require('child_process')
|
2022-08-10 16:38:23 -07:00
|
|
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
2023-05-15 14:07:05 -07:00
|
|
|
const path = require('path')
|
|
|
|
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin')
|
|
|
|
const { DefinePlugin, IgnorePlugin, ProvidePlugin } = require('webpack')
|
2022-09-22 15:29:29 -04:00
|
|
|
|
2023-04-13 12:43:47 -07:00
|
|
|
const commitHash = execSync('git rev-parse HEAD').toString().trim()
|
2023-04-17 09:28:00 -07:00
|
|
|
const isProduction = process.env.NODE_ENV === 'production'
|
|
|
|
|
|
|
|
// Linting and type checking are only necessary as part of development and testing.
|
|
|
|
// Omit them from production builds, as they slow down the feedback loop.
|
|
|
|
const shouldLintOrTypeCheck = !isProduction
|
2022-08-10 16:38:23 -07:00
|
|
|
|
2023-05-15 14:07:05 -07:00
|
|
|
function getCacheDirectory(cacheName) {
|
|
|
|
// Include the trailing slash to denote that this is a directory.
|
|
|
|
return `${path.join(__dirname, 'node_modules/.cache/', cacheName)}/`
|
|
|
|
}
|
|
|
|
|
2022-08-10 16:38:23 -07:00
|
|
|
module.exports = {
|
|
|
|
babel: {
|
2023-04-20 15:34:09 -07:00
|
|
|
plugins: [
|
|
|
|
'@vanilla-extract/babel-plugin',
|
|
|
|
...(process.env.REACT_APP_ADD_COVERAGE_INSTRUMENTATION
|
|
|
|
? [
|
|
|
|
[
|
|
|
|
'istanbul',
|
|
|
|
{
|
|
|
|
all: true,
|
|
|
|
include: ['src/**/*.tsx', 'src/**/*.ts'],
|
|
|
|
exclude: [
|
|
|
|
'src/**/*.css',
|
|
|
|
'src/**/*.css.ts',
|
|
|
|
'src/**/*.test.ts',
|
|
|
|
'src/**/*.test.tsx',
|
|
|
|
'src/**/*.spec.ts',
|
|
|
|
'src/**/*.spec.tsx',
|
|
|
|
'src/**/graphql/**/*',
|
|
|
|
'src/**/*.d.ts',
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
]
|
|
|
|
: []),
|
|
|
|
],
|
2023-01-09 15:54:48 -06:00
|
|
|
},
|
2023-04-17 09:28:00 -07:00
|
|
|
eslint: {
|
|
|
|
enable: shouldLintOrTypeCheck,
|
|
|
|
pluginOptions(eslintConfig) {
|
|
|
|
return Object.assign(eslintConfig, {
|
|
|
|
cache: true,
|
2023-05-15 14:07:05 -07:00
|
|
|
cacheLocation: getCacheDirectory('eslint'),
|
2023-04-20 13:44:57 -07:00
|
|
|
ignorePath: '.gitignore',
|
2023-05-15 14:07:05 -07:00
|
|
|
// Use our own eslint/plugins/config, as overrides interfere with caching.
|
|
|
|
// This ensures that `yarn start` and `yarn lint` share one cache.
|
|
|
|
eslintPath: require.resolve('eslint'),
|
|
|
|
resolvePluginsRelativeTo: null,
|
|
|
|
baseConfig: null,
|
2023-04-17 09:28:00 -07:00
|
|
|
})
|
|
|
|
},
|
|
|
|
},
|
|
|
|
typescript: {
|
|
|
|
enableTypeChecking: shouldLintOrTypeCheck,
|
|
|
|
},
|
2023-01-09 15:54:48 -06:00
|
|
|
jest: {
|
|
|
|
configure(jestConfig) {
|
2023-04-17 09:28:00 -07:00
|
|
|
return Object.assign(jestConfig, {
|
2023-05-15 14:07:05 -07:00
|
|
|
cacheDirectory: getCacheDirectory('jest'),
|
|
|
|
transform: Object.assign(jestConfig.transform, {
|
|
|
|
// Transform vanilla-extract using its own transformer.
|
|
|
|
// See https://sandroroth.com/blog/vanilla-extract-cra#jest-transform.
|
|
|
|
'\\.css\\.ts$': '@vanilla-extract/jest-transform',
|
|
|
|
}),
|
|
|
|
// Use @uniswap/conedison's build directly, as jest does not support its exports.
|
2023-01-25 17:12:23 -05:00
|
|
|
transformIgnorePatterns: ['@uniswap/conedison/format', '@uniswap/conedison/provider'],
|
2023-01-09 15:54:48 -06:00
|
|
|
moduleNameMapper: {
|
|
|
|
'@uniswap/conedison/format': '@uniswap/conedison/dist/format',
|
2023-01-25 17:12:23 -05:00
|
|
|
'@uniswap/conedison/provider': '@uniswap/conedison/dist/provider',
|
2023-01-09 15:54:48 -06:00
|
|
|
},
|
|
|
|
})
|
|
|
|
},
|
2022-08-10 16:38:23 -07:00
|
|
|
},
|
|
|
|
webpack: {
|
2023-05-15 14:07:05 -07:00
|
|
|
plugins: [
|
|
|
|
// Webpack 5 does not polyfill node globals, so we do so for those necessary:
|
|
|
|
new ProvidePlugin({
|
|
|
|
// - react-markdown requires process.cwd
|
|
|
|
process: 'process/browser',
|
|
|
|
}),
|
|
|
|
// vanilla-extract has poor performance on M1 machines with 'debug' identifiers, so we use 'short' instead.
|
|
|
|
// See https://vanilla-extract.style/documentation/integrations/webpack/#identifiers for docs.
|
|
|
|
// See https://github.com/vanilla-extract-css/vanilla-extract/issues/771#issuecomment-1249524366.
|
|
|
|
new VanillaExtractPlugin({ identifiers: 'short' }),
|
|
|
|
],
|
2022-08-10 16:38:23 -07:00
|
|
|
configure: (webpackConfig) => {
|
2023-05-15 14:07:05 -07:00
|
|
|
// Configure webpack plugins:
|
2023-04-20 14:12:43 -07:00
|
|
|
webpackConfig.plugins = webpackConfig.plugins
|
|
|
|
.map((plugin) => {
|
|
|
|
// Extend process.env with dynamic values (eg commit hash).
|
|
|
|
// This will make dynamic values available to JavaScript only, not to interpolated HTML (ie index.html).
|
|
|
|
if (plugin instanceof DefinePlugin) {
|
|
|
|
Object.assign(plugin.definitions['process.env'], {
|
|
|
|
REACT_APP_GIT_COMMIT_HASH: JSON.stringify(commitHash),
|
|
|
|
})
|
|
|
|
}
|
2022-11-17 19:59:40 +01:00
|
|
|
|
2023-04-20 14:12:43 -07:00
|
|
|
// CSS ordering is mitigated through scoping / naming conventions, so we can ignore order warnings.
|
|
|
|
// See https://webpack.js.org/plugins/mini-css-extract-plugin/#remove-order-warnings.
|
|
|
|
if (plugin instanceof MiniCssExtractPlugin) {
|
|
|
|
plugin.options.ignoreOrder = true
|
|
|
|
}
|
2023-04-13 12:43:47 -07:00
|
|
|
|
2023-05-15 14:07:05 -07:00
|
|
|
// Disable TypeScript's config overwrite, as it interferes with incremental build caching.
|
|
|
|
// This ensures that `yarn start` and `yarn typecheck` share one cache.
|
|
|
|
if (plugin.constructor.name == 'ForkTsCheckerWebpackPlugin') {
|
|
|
|
delete plugin.options.typescript.configOverwrite
|
|
|
|
}
|
|
|
|
|
2023-04-20 14:12:43 -07:00
|
|
|
return plugin
|
|
|
|
})
|
|
|
|
.filter((plugin) => {
|
2023-05-15 14:07:05 -07:00
|
|
|
// Case sensitive paths are already enforced by TypeScript.
|
2023-04-20 14:12:43 -07:00
|
|
|
// See https://www.typescriptlang.org/tsconfig#forceConsistentCasingInFileNames.
|
|
|
|
if (plugin instanceof CaseSensitivePathsPlugin) return false
|
|
|
|
|
|
|
|
// IgnorePlugin is used to tree-shake moment locales, but we do not use moment in this project.
|
|
|
|
if (plugin instanceof IgnorePlugin) return false
|
|
|
|
|
|
|
|
return true
|
|
|
|
})
|
2023-04-13 12:43:47 -07:00
|
|
|
|
2023-05-15 14:07:05 -07:00
|
|
|
// Configure webpack resolution:
|
|
|
|
webpackConfig.resolve = Object.assign(webpackConfig.resolve, {
|
|
|
|
plugins: webpackConfig.resolve.plugins.map((plugin) => {
|
|
|
|
// Allow vanilla-extract in production builds.
|
|
|
|
// This is necessary because create-react-app guards against external imports.
|
|
|
|
// See https://sandroroth.com/blog/vanilla-extract-cra#production-build.
|
|
|
|
if (plugin instanceof ModuleScopePlugin) {
|
|
|
|
plugin.allowedPaths.push(path.join(__dirname, 'node_modules/@vanilla-extract/webpack-plugin'))
|
|
|
|
}
|
|
|
|
|
|
|
|
return plugin
|
|
|
|
}),
|
|
|
|
// Webpack 5 does not resolve node modules, so we do so for those necessary:
|
|
|
|
fallback: {
|
|
|
|
// - react-markdown requires path
|
|
|
|
path: require.resolve('path-browserify'),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Configure webpack transpilation (create-react-app specifies transpilation rules in a oneOf):
|
|
|
|
webpackConfig.module.rules[1].oneOf = webpackConfig.module.rules[1].oneOf.map((rule) => {
|
|
|
|
// The fallback rule (eg for dependencies).
|
|
|
|
if (rule.loader && rule.loader.match(/babel-loader/) && !rule.include) {
|
|
|
|
// Allow not-fully-specified modules so that legacy packages are still able to build.
|
|
|
|
rule.resolve = { fullySpecified: false }
|
|
|
|
|
|
|
|
// The class properties transform is required for @uniswap/analytics to build.
|
|
|
|
rule.options.plugins.push('@babel/plugin-proposal-class-properties')
|
|
|
|
}
|
|
|
|
return rule
|
|
|
|
})
|
2022-11-17 19:59:40 +01:00
|
|
|
|
2023-05-02 08:46:32 -07:00
|
|
|
// Configure webpack optimization:
|
2023-05-15 14:07:05 -07:00
|
|
|
webpackConfig.optimization = Object.assign(
|
|
|
|
webpackConfig.optimization,
|
|
|
|
isProduction
|
|
|
|
? {
|
|
|
|
splitChunks: {
|
|
|
|
// Cap the chunk size to 5MB.
|
|
|
|
// react-scripts suggests a chunk size under 1MB after gzip, but we can only measure maxSize before gzip.
|
|
|
|
// react-scripts also caps cacheable chunks at 5MB, which gzips to below 1MB, so we cap chunk size there.
|
|
|
|
// See https://github.com/facebook/create-react-app/blob/d960b9e/packages/react-scripts/config/webpack.config.js#L713-L716.
|
|
|
|
maxSize: 5 * 1024 * 1024,
|
|
|
|
// Optimize over all chunks, instead of async chunks (the default), so that initial chunks are also optimized.
|
|
|
|
chunks: 'all',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
: {}
|
|
|
|
)
|
|
|
|
|
|
|
|
// Configure webpack caching:
|
|
|
|
webpackConfig.cache = Object.assign(webpackConfig.cache, {
|
|
|
|
cacheDirectory: getCacheDirectory('webpack'),
|
2023-05-02 08:46:32 -07:00
|
|
|
})
|
|
|
|
|
2023-05-15 14:07:05 -07:00
|
|
|
// Ignore failed source mappings to avoid spamming the console.
|
|
|
|
// Source mappings for a package will fail if the package does not provide them, but the build will still succeed,
|
|
|
|
// so it is unnecessary (and bothersome) to log it. This should be turned off when debugging missing sourcemaps.
|
|
|
|
// See https://webpack.js.org/loaders/source-map-loader#ignoring-warnings.
|
|
|
|
webpackConfig.ignoreWarnings = [/Failed to parse source map/]
|
|
|
|
|
2022-08-10 16:38:23 -07:00
|
|
|
return webpackConfig
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|