build: upgrade to webpack5 with polyfilled Buffer (#6568)

* fix: Revert "fix: Revert "build: upgrade to webpack 5 (#6459)" (#6566)"

This reverts commit 5e591455b38c9618c750a23bc2a63cdcc30dba57.

* build: polyfill Buffer

* docs: fix comment negation
This commit is contained in:
Zach Pomerantz 2023-05-15 14:07:05 -07:00 committed by GitHub
parent 719ee0f5b5
commit fe6df38997
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 4177 additions and 5882 deletions

@ -1,9 +1,11 @@
/* eslint-env node */
const { VanillaExtractPlugin } = require('@vanilla-extract/webpack-plugin')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
const { execSync } = require('child_process')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
const { DefinePlugin, IgnorePlugin } = require('webpack')
const path = require('path')
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin')
const { DefinePlugin, IgnorePlugin, ProvidePlugin } = require('webpack')
const commitHash = execSync('git rev-parse HEAD').toString().trim()
const isProduction = process.env.NODE_ENV === 'production'
@ -12,6 +14,11 @@ const isProduction = process.env.NODE_ENV === 'production'
// Omit them from production builds, as they slow down the feedback loop.
const shouldLintOrTypeCheck = !isProduction
function getCacheDirectory(cacheName) {
// Include the trailing slash to denote that this is a directory.
return `${path.join(__dirname, 'node_modules/.cache/', cacheName)}/`
}
module.exports = {
babel: {
plugins: [
@ -44,8 +51,13 @@ module.exports = {
pluginOptions(eslintConfig) {
return Object.assign(eslintConfig, {
cache: true,
cacheLocation: 'node_modules/.cache/eslint/',
cacheLocation: getCacheDirectory('eslint'),
ignorePath: '.gitignore',
// 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,
})
},
},
@ -55,11 +67,13 @@ module.exports = {
jest: {
configure(jestConfig) {
return Object.assign(jestConfig, {
transform: {
'\\.css\\.ts$': './vanilla.transform.cjs',
...jestConfig.transform,
},
cacheDirectory: 'node_modules/.cache/jest',
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.
transformIgnorePatterns: ['@uniswap/conedison/format', '@uniswap/conedison/provider'],
moduleNameMapper: {
'@uniswap/conedison/format': '@uniswap/conedison/dist/format',
@ -69,8 +83,19 @@ module.exports = {
},
},
webpack: {
plugins: [new VanillaExtractPlugin({ identifiers: 'short' })],
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' }),
],
configure: (webpackConfig) => {
// Configure webpack plugins:
webpackConfig.plugins = webpackConfig.plugins
.map((plugin) => {
// Extend process.env with dynamic values (eg commit hash).
@ -87,10 +112,16 @@ module.exports = {
plugin.options.ignoreOrder = true
}
// 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
}
return plugin
})
.filter((plugin) => {
// Case sensitive paths are enforced by TypeScript.
// Case sensitive paths are already enforced by TypeScript.
// See https://www.typescriptlang.org/tsconfig#forceConsistentCasingInFileNames.
if (plugin instanceof CaseSensitivePathsPlugin) return false
@ -100,20 +131,67 @@ module.exports = {
return true
})
// We're currently on Webpack 4.x which doesn't support the `exports` field in package.json.
// Instead, we need to manually map the import path to the correct exports path (eg dist or build folder).
// See https://github.com/webpack/webpack/issues/9509.
webpackConfig.resolve.alias['@uniswap/conedison'] = '@uniswap/conedison/dist'
// 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
})
// Configure webpack optimization:
webpackConfig.optimization.splitChunks = Object.assign(webpackConfig.optimization.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,
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'),
})
// 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/]
return webpackConfig
},
},

@ -67,7 +67,7 @@
]
},
"devDependencies": {
"@craco/craco": "6.4.3",
"@craco/craco": "^7.1.0",
"@ethersproject/experimental": "^5.4.0",
"@lingui/cli": "^3.9.0",
"@testing-library/jest-dom": "^5.16.4",
@ -104,6 +104,7 @@
"@vanilla-extract/jest-transform": "^1.1.1",
"@vanilla-extract/webpack-plugin": "^2.1.11",
"babel-plugin-istanbul": "^6.1.1",
"buffer": "^6.0.3",
"cypress": "10.3.1",
"cypress-hardhat": "^2.3.0",
"env-cmd": "^10.1.0",
@ -114,8 +115,11 @@
"jest-fetch-mock": "^3.0.3",
"jest-styled-components": "^7.0.8",
"ms.macro": "^2.0.0",
"path-browserify": "^1.0.1",
"prettier": "^2.7.1",
"react-scripts": "^4.0.3",
"process": "^0.11.10",
"react-scripts": "^5.0.1",
"resize-observer-polyfill": "^1.5.1",
"serve": "^11.3.2",
"source-map-explorer": "^2.5.3",
"ts-transform-graphql-tag": "^0.2.1",

@ -1,7 +1,7 @@
import { Token } from '@uniswap/sdk-core'
import { AddressMap } from '@uniswap/smart-order-router'
import { abi as MulticallABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json'
import { abi as NFTPositionManagerABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import MulticallJSON from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json'
import NFTPositionManagerJSON from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import { useWeb3React } from '@web3-react/core'
import { MULTICALL_ADDRESS, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES as V3NFT_ADDRESSES } from 'constants/addresses'
import { isSupportedChain, SupportedChainId } from 'constants/chains'
@ -43,11 +43,11 @@ function useContractMultichain<T extends BaseContract>(
}
export function useV3ManagerContracts(chainIds: SupportedChainId[]): ContractMap<NonfungiblePositionManager> {
return useContractMultichain<NonfungiblePositionManager>(V3NFT_ADDRESSES, NFTPositionManagerABI, chainIds)
return useContractMultichain<NonfungiblePositionManager>(V3NFT_ADDRESSES, NFTPositionManagerJSON.abi, chainIds)
}
export function useInterfaceMulticallContracts(chainIds: SupportedChainId[]): ContractMap<UniswapInterfaceMulticall> {
return useContractMultichain<UniswapInterfaceMulticall>(MULTICALL_ADDRESS, MulticallABI, chainIds)
return useContractMultichain<UniswapInterfaceMulticall>(MULTICALL_ADDRESS, MulticallJSON.abi, chainIds)
}
type PriceMap = { [key: CurrencyKey]: number | undefined }

@ -1,5 +1,5 @@
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { abi as IUniswapV3PoolStateABI } from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
import IUniswapV3PoolStateJSON from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
import { computePoolAddress, Pool, Position } from '@uniswap/v3-sdk'
import { V3_CORE_FACTORY_ADDRESSES } from 'constants/addresses'
import { SupportedChainId } from 'constants/chains'
@ -118,7 +118,7 @@ export default function useMultiChainPositions(account: string, chains = DEFAULT
// Combines PositionDetails with Pool data to build our return type
const fetchPositionInfo = useCallback(
async (positionDetails: PositionDetails[], chainId: SupportedChainId, multicall: UniswapInterfaceMulticall) => {
const poolInterface = new Interface(IUniswapV3PoolStateABI) as UniswapV3PoolInterface
const poolInterface = new Interface(IUniswapV3PoolStateJSON.abi) as UniswapV3PoolInterface
const tokens = await getTokens(
positionDetails.flatMap((details) => [details.token0, details.token1]),
chainId

@ -1,6 +1,6 @@
import { Interface } from '@ethersproject/abi'
import { BigintIsh, Currency, Token } from '@uniswap/sdk-core'
import { abi as IUniswapV3PoolStateABI } from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
import IUniswapV3PoolStateJSON from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
import { computePoolAddress } from '@uniswap/v3-sdk'
import { FeeAmount, Pool } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
@ -11,7 +11,7 @@ import { useMemo } from 'react'
import { V3_CORE_FACTORY_ADDRESSES } from '../constants/addresses'
import { IUniswapV3PoolStateInterface } from '../types/v3/IUniswapV3PoolState'
const POOL_STATE_INTERFACE = new Interface(IUniswapV3PoolStateABI) as IUniswapV3PoolStateInterface
const POOL_STATE_INTERFACE = new Interface(IUniswapV3PoolStateJSON.abi) as IUniswapV3PoolStateInterface
// Classes are expensive to instantiate, so this caches the recently instantiated pools.
// This avoids re-instantiating pools as the other pools in the same request are loaded.

@ -1,13 +1,13 @@
import { Interface } from '@ethersproject/abi'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import IUniswapV2PairJSON from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import { computePairAddress, Pair } from '@uniswap/v2-sdk'
import { useMultipleContractSingleData } from 'lib/hooks/multicall'
import { useMemo } from 'react'
import { V2_FACTORY_ADDRESSES } from '../constants/addresses'
const PAIR_INTERFACE = new Interface(IUniswapV2PairABI)
const PAIR_INTERFACE = new Interface(IUniswapV2PairJSON.abi)
export enum PairState {
LOADING,

@ -3,10 +3,21 @@ import 'polyfill-object.fromentries'
import { ResizeObserver } from '@juggle/resize-observer'
import flat from 'array.prototype.flat'
import flatMap from 'array.prototype.flatmap'
import { Buffer } from 'buffer'
flat.shim()
flatMap.shim()
declare global {
interface Window {
Buffer: typeof Buffer
}
}
if (!window.Buffer) {
window.Buffer = Buffer
}
if (!window.ResizeObserver) {
window.ResizeObserver = ResizeObserver
}
flat.shim()
flatMap.shim()

@ -1,7 +1,7 @@
import '@testing-library/jest-dom' // jest custom assertions
import 'polyfills'
import 'jest-styled-components' // adds style diffs to snapshot tests
import { ResizeObserver } from '@juggle/resize-observer'
import type { createPopper } from '@popperjs/core'
import { useWeb3React } from '@web3-react/core'
import failOnConsole from 'jest-fail-on-console'

@ -1,5 +1,5 @@
import type { TransactionResponse } from '@ethersproject/providers'
import { abi as MERKLE_DISTRIBUTOR_ABI } from '@uniswap/merkle-distributor/build/MerkleDistributor.json'
import MerkleDistributorJSON from '@uniswap/merkle-distributor/build/MerkleDistributor.json'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { MERKLE_DISTRIBUTOR_ADDRESS } from 'constants/addresses'
@ -15,7 +15,7 @@ import { useTransactionAdder } from '../transactions/hooks'
import { TransactionType } from '../transactions/types'
function useMerkleDistributorContract() {
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MerkleDistributorJSON.abi, true)
}
interface UserClaimData {

@ -6,8 +6,8 @@ import type { TransactionResponse } from '@ethersproject/providers'
import { toUtf8String, Utf8ErrorFuncs, Utf8ErrorReason } from '@ethersproject/strings'
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import { abi as GOVERNANCE_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
import { abi as UNI_ABI } from '@uniswap/governance/build/Uni.json'
import GovernorAlphaJSON from '@uniswap/governance/build/GovernorAlpha.json'
import UniJSON from '@uniswap/governance/build/Uni.json'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import GOVERNOR_BRAVO_ABI from 'abis/governor-bravo.json'
@ -39,11 +39,11 @@ import { TransactionType } from '../transactions/types'
import { VoteOption } from './types'
function useGovernanceV0Contract(): Contract | null {
return useContract(GOVERNANCE_ALPHA_V0_ADDRESSES, GOVERNANCE_ABI, false)
return useContract(GOVERNANCE_ALPHA_V0_ADDRESSES, GovernorAlphaJSON.abi, false)
}
function useGovernanceV1Contract(): Contract | null {
return useContract(GOVERNANCE_ALPHA_V1_ADDRESSES, GOVERNANCE_ABI, false)
return useContract(GOVERNANCE_ALPHA_V1_ADDRESSES, GovernorAlphaJSON.abi, false)
}
function useGovernanceBravoContract(): Contract | null {
@ -55,7 +55,7 @@ const useLatestGovernanceContract = useGovernanceBravoContract
function useUniContract() {
const { chainId } = useWeb3React()
const uniAddress = useMemo(() => (chainId ? UNI[chainId]?.address : undefined), [chainId])
return useContract(uniAddress, UNI_ABI, true)
return useContract(uniAddress, UniJSON.abi, true)
}
interface ProposalDetail {
@ -99,7 +99,7 @@ export enum ProposalState {
EXECUTED,
}
const GovernanceInterface = new Interface(GOVERNANCE_ABI)
const GovernanceInterface = new Interface(GovernorAlphaJSON.abi)
// get count of all proposals made in the latest governor contract
function useProposalCount(contract: Contract | null): number | undefined {

@ -1,5 +1,5 @@
import { Interface } from '@ethersproject/abi'
import { abi as STAKING_REWARDS_ABI } from '@uniswap/liquidity-staker/build/StakingRewards.json'
import StakingRewardsJSON from '@uniswap/liquidity-staker/build/StakingRewards.json'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core'
@ -11,7 +11,7 @@ import { useMemo } from 'react'
import { DAI, UNI, USDC_MAINNET, USDT, WBTC, WRAPPED_NATIVE_CURRENCY } from '../../constants/tokens'
const STAKING_REWARDS_INTERFACE = new Interface(STAKING_REWARDS_ABI)
const STAKING_REWARDS_INTERFACE = new Interface(StakingRewardsJSON.abi)
export const STAKING_GENESIS = 1600387200

@ -5,6 +5,7 @@
"alwaysStrict": true,
"baseUrl": "src",
"composite": true,
"declarationMap": false,
"downlevelIteration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
@ -21,6 +22,7 @@
"noUnusedLocals": false,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"strictNullChecks": true,
"target": "ESNext",

@ -1,12 +0,0 @@
/* eslint-env node */
/**
* @file Re-exports the vanilla-extract jest transform, so that jest can properly transform .css.ts files.
* `@vanilla-extract/jest-transform` incorrectly maps its default export, so that `import *` does not work; and expects
* the wrong shape for options, so it must be re-exported to be correctly used as a jest transform.
*/
const { default: transform } = require('@vanilla-extract/jest-transform')
module.exports = {
process: (source, filePath, options) =>
transform.process(source, filePath, { config: options, supportsStaticESM: false }),
}

9860
yarn.lock

File diff suppressed because it is too large Load Diff