Something went wrong. Try again.
Bluesky app fork with some witchin' additions 💫 forked from jollywhoppers.com/witchsky.app
Something went wrong. Try again.
witchsky.app webpack.config.js
6.9 kB · 179 lines
JavaScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180const path = require('path')
const createExpoWebpackConfigAsync = require('@expo/webpack-config')const webpack = require('webpack')const {withAlias} = require('@expo/webpack-config/addons')const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer')const {sentryWebpackPlugin} = require('@sentry/webpack-plugin')const {version} = require('./package.json')
const GENERATE_STATS = process.env.EXPO_PUBLIC_GENERATE_STATS === '1'const OPEN_ANALYZER = process.env.EXPO_PUBLIC_OPEN_ANALYZER === '1'
const reactNativeWebWebviewConfiguration = { test: /postMock.html$/, use: { loader: 'file-loader', options: { name: '[name].[ext]', }, },}
// Walk a rule tree and wrap source-map-loader's filterSourceMappingUrl to// drop sourcemap references matching the given path pattern. Mutates in place.function patchSourceMapFilter(rules, pathPattern) { if (!rules) return for (const rule of rules) { if (!rule || typeof rule !== 'object') continue if (rule.oneOf) patchSourceMapFilter(rule.oneOf, pathPattern) if (rule.rules) patchSourceMapFilter(rule.rules, pathPattern) const uses = Array.isArray(rule.use) ? rule.use : rule.use ? [rule.use] : [] for (const use of uses) { if (!use?.loader?.includes('source-map-loader')) continue const prev = use.options?.filterSourceMappingUrl use.options = { ...use.options, filterSourceMappingUrl(url, resourcePath) { if (pathPattern.test(resourcePath)) return 'remove' return prev ? prev(url, resourcePath) : true }, } } }}
module.exports = async function (env, argv) { env.babel = { dangerouslyAddModulePathsToTranspile: [ // this covers every package that starts with these strings (e.g. @atproto/lex-client) '@bsky.app/expo', '@atproto/lex', ], } let config = await createExpoWebpackConfigAsync(env, argv) /* * Expo only registers its own internal config as a cache build dependency, * so changes to this file (e.g. aliases) don't invalidate the persistent * filesystem cache and stale module resolutions get reused. Register this * file so edits here always bust the cache. */ if (config.cache?.buildDependencies) { config.cache.buildDependencies.config = [ ...(config.cache.buildDependencies.config || []), __filename, ] } config = withAlias(config, { 'react-native$': 'react-native-web', 'react-native-webview': 'react-native-web-webview', 'react-native-gesture-handler': false, // RNGH should not be used on web, so let's cause a build error if it sneaks in '@sentry-internal/replay': false, // not used, ~300kb of dead weight /* * @sentry/react-native's tracing integration probes for expo-router via a * try/catch require(). We don't use expo-router, so the module can't * resolve and webpack warns on every build. Stubbing it to an empty * module makes the probe return null (`mod?.store ?? null`) silently. */ 'expo-router/build/global-state/router-store': false, /* * react-native-svg's fetchData util imports the ~55KB `buffer` polyfill, * but is only needed by SvgUri/SvgXml remote loading, which we don't use. * Stubbing it out makes fetchText undefined, so it throws if ever called. * The alias key must be an absolute path because the package imports it * via a relative path internally. */ [path.join( __dirname, 'node_modules/react-native-svg/lib/module/utils/fetchData', )]: false, /* * reanimated's webUtils.web.js mixes ESM exports with bare CommonJS * require() calls in try/catch, which webpack leaves untranspiled - they * throw at runtime and createReactDOMStyle & co. silently stay undefined, * making _updatePropsJS crash on every animated style update. The shim * imports the same react-native-web internals statically. See the shim * file for details. */ [path.join( __dirname, 'node_modules/react-native-reanimated/lib/module/ReanimatedModule/js-reanimated/webUtils', )]: path.join(__dirname, 'web/reanimatedWebUtilsShim.js'), })
/* * expo-font's serverContext.web.js imports `node:async_hooks` for SSR-only * font collection, but webpack can't resolve `node:` URIs for web targets. * Every call site is guarded by `typeof window === 'undefined'`, so in the * browser bundle the module is dead code - strip the scheme prefix and stub * the builtin out with an empty module. */ config.plugins.push( new webpack.NormalModuleReplacementPlugin( /^node:async_hooks$/, resource => { resource.request = 'async_hooks' }, ), ) config.resolve.fallback = {...config.resolve.fallback, async_hooks: false}
// react-native-uuid ships sourceMappingURL comments but no .map files. patchSourceMapFilter(config.module.rules, /react-native-uuid/) config.module.rules = [ ...(config.module.rules || []), reactNativeWebWebviewConfiguration, ] if (env.mode === 'development') { config.plugins.push(new ReactRefreshWebpackPlugin()) config.devServer = config.devServer || {} config.devServer.historyApiFallback = { ...(config.devServer.historyApiFallback || {}), // Handles like `xan.lol` contain dots, which the default history // fallback treats as asset requests instead of app routes. disableDotRule: true, } // Reap zombie HMR WebSocket connections that linger after refresh. // Without this, dead sockets exhaust the browser's per-origin connection // pool and the dev server stops responding. config.devServer.onListening = devServer => { devServer.server.on('connection', socket => { socket.setTimeout(10000) socket.on('timeout', () => socket.destroy()) }) } } else { // Support static CDN for chunks config.output.publicPath = 'auto' }
if (GENERATE_STATS || OPEN_ANALYZER) { config.plugins.push( new BundleAnalyzerPlugin({ openAnalyzer: OPEN_ANALYZER, generateStatsFile: true, statsFilename: '../stats.json', analyzerMode: OPEN_ANALYZER ? 'server' : 'json', defaultSizes: 'parsed', // reasons balloon stats.json past Node's max string length, breaking bundle-size-diff in CI statsOptions: OPEN_ANALYZER ? null : {reasons: false}, }), ) } if (process.env.SENTRY_AUTH_TOKEN) { config.plugins.push( sentryWebpackPlugin({ org: 'blueskyweb', project: 'app', authToken: process.env.SENTRY_AUTH_TOKEN, release: { // fallback needed for Render.com deployments name: process.env.SENTRY_RELEASE || version, dist: process.env.SENTRY_DIST, }, }), ) } return config}