personal fork of bluesky app
bsky.kelinci.net
4.5 kB
128 lines
1import path from 'node:path';
2
3import { defineConfig } from '@rsbuild/core';
4import { pluginReact } from '@rsbuild/plugin-react';
5import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';
6import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin';
7
8import oauthMetadata from './public/oauth-client-metadata.json' with { type: 'json' };
9import { ServiceWorkerPrecachePlugin } from './scripts/sw-precache-plugin';
10
11const root = process.cwd();
12const serverHost = '127.0.0.1';
13const serverPort = 19006;
14
15export default defineConfig(({ envMode }) => {
16 const oauthScope = process.env.PUBLIC_OAUTH_SCOPE || oauthMetadata.scope;
17 const oauthRedirectPath = new URL(oauthMetadata.redirect_uris[0]!).pathname;
18 const oauthRedirectUri =
19 envMode === 'production'
20 ? process.env.PUBLIC_OAUTH_REDIRECT_URI || oauthMetadata.redirect_uris[0]!
21 : `http://${serverHost}:${serverPort}${oauthRedirectPath}`;
22 const oauthClientId =
23 envMode === 'production'
24 ? process.env.PUBLIC_OAUTH_CLIENT_ID || oauthMetadata.client_id
25 : `http://localhost?redirect_uri=${encodeURIComponent(oauthRedirectUri)}` +
26 `&scope=${encodeURIComponent(oauthScope)}`;
27
28 return {
29 plugins: [
30 // React Compiler runs natively in rspack's builtin swc-loader (no Babel pass). `panicThreshold:
31 // 'none'` downlevels the components the compiler declines to optimize from hard build errors to
32 // skipped optimizations — the bail-out severity is honoured as of rspack 2.1.0
33 // (web-infra-dev/rspack#14517).
34 pluginReact({ reactCompiler: { panicThreshold: 'none' } }),
35 ],
36 source: {
37 define: {
38 'import.meta.env.PUBLIC_GIT_COMMIT_HASH': JSON.stringify(process.env.GIT_COMMIT_HASH ?? ''),
39 'import.meta.env.PUBLIC_OAUTH_CLIENT_ID': JSON.stringify(oauthClientId),
40 'import.meta.env.PUBLIC_OAUTH_REDIRECT_URI': JSON.stringify(oauthRedirectUri),
41 'import.meta.env.PUBLIC_OAUTH_SCOPE': JSON.stringify(oauthScope),
42 },
43 entry: {
44 index: path.resolve(root, 'index.tsx'),
45 },
46 },
47 html: {
48 favicon: path.resolve(root, 'assets/favicon.png'),
49 template: path.resolve(root, 'web/index.html'),
50 title: 'Bluesky',
51 },
52 resolve: {
53 alias: {
54 '#': path.resolve(root, 'src'),
55 },
56 aliasStrategy: 'prefer-alias',
57 extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx', '.json'],
58 },
59 server: {
60 host: serverHost,
61 historyApiFallback: true,
62 port: serverPort,
63 // forward link-resolution xrpc calls to the locally-running worker (`pnpm dev:worker`), keeping
64 // them same-origin from the browser's perspective.
65 proxy: {
66 '/xrpc': 'http://127.0.0.1:8787',
67 },
68 },
69 output: {
70 cleanDistPath: true,
71 distPath: { root: 'web-build' },
72 sourceMap: { js: 'source-map' },
73 minify: {
74 jsOptions: {
75 minimizerOptions: {
76 compress: {
77 passes: 3,
78 },
79 },
80 },
81 },
82 },
83 performance: {
84 // strip console.* from production bundles (replaces babel-plugin-transform-remove-console)
85 removeConsole: envMode === 'production',
86 },
87 tools: {
88 rspack(config) {
89 config.plugins ??= [];
90 config.plugins.push(new VanillaExtractPlugin());
91
92 // prioritize deduplication in async CSS chunks: hoist any extracted-CSS module shared by
93 // 2+ chunks into its own shared chunk rather than copying it into every route chunk.
94 config.optimization ??= {};
95 if (config.optimization.splitChunks !== false) {
96 config.optimization.splitChunks ??= {};
97 config.optimization.splitChunks.cacheGroups ??= {};
98 config.optimization.splitChunks.cacheGroups.sharedStyles = {
99 chunks: 'all',
100 minChunks: 2,
101 minSize: 0,
102 priority: 20,
103 reuseExistingChunk: true,
104 type: 'css/mini-extract',
105 };
106 }
107
108 // precaching only makes sense against a hashed production build; in dev it would fight
109 // the dev server and HMR, so the service worker is emitted for production builds only.
110 if (envMode === 'production') {
111 config.plugins.push(new ServiceWorkerPrecachePlugin(path.resolve(root, 'src/lib/sw-template.js')));
112 }
113
114 // opt-in bundle analysis: `RSDOCTOR=true pnpm build`
115 if (process.env.RSDOCTOR) {
116 config.plugins.push(
117 new RsdoctorRspackPlugin({
118 disableClientServer: !process.stdout.isTTY,
119 // the loader probe recurses to a stack overflow on vanilla-extract's virtual
120 // `extracted.js` modules; we only want bundle/chunk analysis anyway.
121 features: { bundle: true, loader: false, plugins: true, resolver: false, treeShaking: false },
122 }),
123 );
124 }
125 },
126 },
127 };
128});