an attempt to make a lightweight, easily self-hostable, scoped bluesky appview
at main 2.7 kB view raw
1//https://gist.github.com/sikanhe/f9ac68dd4c78c914c29cc98e7b875466 2import { readFileSync } from "node:fs" 3import * as babel from "npm:@babel/core" 4//import BabelPluginReactCompiler from "npm:babel-plugin-react-compiler" 5import BabelPluginReactCompiler from "npm:babel-plugin-react-compiler" 6import * as esbuild from "npm:esbuild@0.20.2"; 7import QuickLRU from "npm:quick-lru" 8 9export function ReactCompilerEsbuildPlugin({ 10 filter, 11 sourceMaps, 12 runtimeModulePath, 13}: { filter: RegExp; sourceMaps: boolean; runtimeModulePath: string }): esbuild.Plugin { 14 return { 15 name: "esbuild-react-compiler-plugin", 16 setup(build) { 17 // Cache previous outputs for incremental rebuilds 18 const buildCache = new QuickLRU<string, string>({ maxSize: 1000 }) 19 20 let timings: number[] = [] 21 22 build.onEnd(() => { 23 if (timings.length < 1) return 24 25 const totalTime = timings.reduce((sum, x) => sum + x, 0).toFixed(0) 26 console.log(`[⚛️ React Compiler] ${timings.length} files changed`) 27 console.log(`[⚛️ React Compiler] Used ${totalTime} ms`) 28 29 timings = [] 30 }) 31 32 build.onLoad({ filter, namespace: "" }, (args) => { 33 const contents = readFileSync(args.path, "utf8") 34 35 const t0 = performance.now() 36 37 if (buildCache.has(contents)) { 38 return { 39 contents: buildCache.get(contents), 40 loader: "js", 41 } 42 } 43 44 const output = build.esbuild.transformSync(contents, { 45 loader: "tsx", 46 jsx: "automatic", 47 define: build.initialOptions.define, 48 target: build.initialOptions.target, 49 }) 50 51 const transformResult = babel.transformSync(output.code, { 52 plugins: [ 53 // Warning: using string config here (ie 'babel-plugin-react-compiler') instead of the directly 54 // imported object is much slower than directly passing the plugin object because 55 // Babel has to resolve the plugin file from node_modules 56 [ 57 BabelPluginReactCompiler, 58 { 59 runtimeModule: runtimeModulePath, 60 }, 61 ], 62 ], 63 filename: args.path, 64 caller: { 65 name: "esbuild-react-compiler-plugin", 66 supportsStaticESM: true, 67 }, 68 // TODO: figure out sourcemap setting and chaining 69 sourceMaps, 70 }) 71 72 timings.push(performance.now() - t0) 73 74 if (transformResult?.code) { 75 buildCache.set(contents, transformResult?.code) 76 } 77 78 return { 79 contents: transformResult?.code ?? undefined, 80 loader: "js", 81 } 82 }) 83 }, 84 } 85}