vite.config.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import path, { resolve } from "path"
  2. import fs from "fs"
  3. import { execSync } from "child_process"
  4. import { defineConfig, type PluginOption, type Plugin } from "vite"
  5. import react from "@vitejs/plugin-react"
  6. import tailwindcss from "@tailwindcss/vite"
  7. function getGitSha() {
  8. let gitSha: string | undefined = undefined
  9. try {
  10. gitSha = execSync("git rev-parse HEAD").toString().trim()
  11. } catch (_error) {
  12. // Do nothing.
  13. }
  14. return gitSha
  15. }
  16. const wasmPlugin = (): Plugin => ({
  17. name: "wasm",
  18. async load(id) {
  19. if (id.endsWith(".wasm")) {
  20. const wasmBinary = await import(id)
  21. return `
  22. const wasmModule = new WebAssembly.Module(${wasmBinary.default});
  23. export default wasmModule;
  24. `
  25. }
  26. },
  27. })
  28. const persistPortPlugin = (): Plugin => ({
  29. name: "write-port-to-file",
  30. configureServer(viteDevServer) {
  31. viteDevServer?.httpServer?.once("listening", () => {
  32. const address = viteDevServer?.httpServer?.address()
  33. const port = address && typeof address === "object" ? address.port : null
  34. if (port) {
  35. fs.writeFileSync(resolve(__dirname, "..", ".vite-port"), port.toString())
  36. console.log(`[Vite Plugin] Server started on port ${port}`)
  37. } else {
  38. console.warn("[Vite Plugin] Could not determine server port")
  39. }
  40. })
  41. },
  42. })
  43. // https://vitejs.dev/config/
  44. export default defineConfig(({ mode }) => {
  45. let outDir = "../src/webview-ui/build"
  46. const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "src", "package.json"), "utf8"))
  47. const gitSha = getGitSha()
  48. const define: Record<string, any> = {
  49. "process.platform": JSON.stringify(process.platform),
  50. "process.env.VSCODE_TEXTMATE_DEBUG": JSON.stringify(process.env.VSCODE_TEXTMATE_DEBUG),
  51. "process.env.PKG_NAME": JSON.stringify(pkg.name),
  52. "process.env.PKG_VERSION": JSON.stringify(pkg.version),
  53. "process.env.PKG_OUTPUT_CHANNEL": JSON.stringify("Roo-Code"),
  54. ...(gitSha ? { "process.env.PKG_SHA": JSON.stringify(gitSha) } : {}),
  55. }
  56. // TODO: We can use `@roo-code/build` to generate `define` once the
  57. // monorepo is deployed.
  58. if (mode === "nightly") {
  59. outDir = "../apps/vscode-nightly/build/webview-ui/build"
  60. const nightlyPkg = JSON.parse(
  61. fs.readFileSync(path.join(__dirname, "..", "apps", "vscode-nightly", "package.nightly.json"), "utf8"),
  62. )
  63. define["process.env.PKG_NAME"] = JSON.stringify(nightlyPkg.name)
  64. define["process.env.PKG_VERSION"] = JSON.stringify(nightlyPkg.version)
  65. define["process.env.PKG_OUTPUT_CHANNEL"] = JSON.stringify("Roo-Code-Nightly")
  66. }
  67. const plugins: PluginOption[] = [react(), tailwindcss(), persistPortPlugin(), wasmPlugin()]
  68. return {
  69. plugins,
  70. resolve: {
  71. alias: {
  72. "@": resolve(__dirname, "./src"),
  73. "@src": resolve(__dirname, "./src"),
  74. "@roo": resolve(__dirname, "../src/shared"),
  75. },
  76. },
  77. build: {
  78. outDir,
  79. emptyOutDir: true,
  80. reportCompressedSize: false,
  81. sourcemap: true,
  82. rollupOptions: {
  83. output: {
  84. entryFileNames: `assets/[name].js`,
  85. chunkFileNames: (chunkInfo) => {
  86. if (chunkInfo.name === "mermaid-bundle") {
  87. return `assets/mermaid-bundle.js`
  88. }
  89. // Default naming for other chunks, ensuring uniqueness from entry
  90. return `assets/chunk-[hash].js`
  91. },
  92. assetFileNames: (assetInfo) => {
  93. if (
  94. assetInfo.name &&
  95. (assetInfo.name.endsWith(".woff2") ||
  96. assetInfo.name.endsWith(".woff") ||
  97. assetInfo.name.endsWith(".ttf"))
  98. ) {
  99. return "assets/fonts/[name][extname]"
  100. }
  101. return "assets/[name][extname]"
  102. },
  103. manualChunks: (id, { getModuleInfo }) => {
  104. // Consolidate all mermaid code and its direct large dependencies (like dagre)
  105. // into a single chunk. The 'channel.js' error often points to dagre.
  106. if (
  107. id.includes("node_modules/mermaid") ||
  108. id.includes("node_modules/dagre") || // dagre is a common dep for graph layout
  109. id.includes("node_modules/cytoscape") // another potential graph lib
  110. // Add other known large mermaid dependencies if identified
  111. ) {
  112. return "mermaid-bundle"
  113. }
  114. // Check if the module is part of any explicitly defined mermaid-related dynamic import
  115. // This is a more advanced check if simple path matching isn't enough.
  116. const moduleInfo = getModuleInfo(id)
  117. if (moduleInfo?.importers.some((importer) => importer.includes("node_modules/mermaid"))) {
  118. return "mermaid-bundle"
  119. }
  120. if (
  121. moduleInfo?.dynamicImporters.some((importer) => importer.includes("node_modules/mermaid"))
  122. ) {
  123. return "mermaid-bundle"
  124. }
  125. },
  126. },
  127. },
  128. },
  129. server: {
  130. hmr: {
  131. host: "localhost",
  132. protocol: "ws",
  133. },
  134. cors: {
  135. origin: "*",
  136. methods: "*",
  137. allowedHeaders: "*",
  138. },
  139. },
  140. define,
  141. optimizeDeps: {
  142. include: [
  143. "mermaid",
  144. "dagre", // Explicitly include dagre for pre-bundling
  145. // Add other known large mermaid dependencies if identified
  146. ],
  147. exclude: ["@vscode/codicons", "vscode-oniguruma", "shiki"],
  148. },
  149. assetsInclude: ["**/*.wasm", "**/*.wav"],
  150. }
  151. })