mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-10 07:11:25 +03:00
147 lines
5.3 KiB
TypeScript
147 lines
5.3 KiB
TypeScript
import { defineConfig } from "electron-vite"
|
|
import type { Plugin } from "vite"
|
|
import { BetaNotes } from "./script/beta-notes"
|
|
import { pickerPlugin } from "./script/picker"
|
|
import { nodePtyPackage } from "./script/utils"
|
|
|
|
function resolveChannel() {
|
|
const raw = process.env.OPENCODE_CHANNEL
|
|
|
|
if (raw === "local" || raw === "dev" || raw === "beta" || raw === "prod") return raw
|
|
|
|
if (raw === "latest") return "prod"
|
|
|
|
return "dev"
|
|
}
|
|
|
|
const appPlugin = (await import("@opencode/app/vite")).default
|
|
|
|
// Every module the entry reaches through static imports lands in one chunk. Automatic splitting
|
|
// otherwise fragments the initial graph into ~50 files shared with lazy routes, and each file costs
|
|
// the renderer a main-thread request round trip through the main process before first paint.
|
|
// Rolldown hands every chunk-name call a fresh context, so the graph is walked once per output.
|
|
const initialGraph = new Set<string>()
|
|
|
|
const initialChunk: Plugin = {
|
|
name: "opencode-desktop:initial-chunk",
|
|
renderStart() {
|
|
const entries = [...this.getModuleIds()].filter((id) => this.getModuleInfo(id)?.isEntry)
|
|
initialGraph.clear()
|
|
entries.forEach((id) => initialGraph.add(id))
|
|
|
|
// A Set's iterator also visits members added while iterating, so this reaches every static import.
|
|
for (const id of initialGraph) this.getModuleInfo(id)?.importedIds.forEach((imported) => initialGraph.add(imported))
|
|
},
|
|
}
|
|
|
|
export default defineConfig(async ({ command }) => {
|
|
const channel = resolveChannel()
|
|
const nodePtyPkg = nodePtyPackage()
|
|
|
|
// Beta builds carry their commit and recent history for the updater's "What's new in beta"; the dev server carries
|
|
// them without asking GitHub, so the page can be tried; other channels none.
|
|
const betaNotes =
|
|
channel === "beta"
|
|
? await BetaNotes.enrich(BetaNotes.embed(), { token: process.env.GITHUB_TOKEN })
|
|
: command === "serve"
|
|
? BetaNotes.embed()
|
|
: undefined
|
|
|
|
return {
|
|
main: {
|
|
resolve: {
|
|
dedupe: ["effect"],
|
|
},
|
|
define: {
|
|
// Local renderer/server mode still uses the dev application identity and updater policy.
|
|
"import.meta.env.OPENCODE_CHANNEL": JSON.stringify(channel === "local" ? "dev" : channel),
|
|
},
|
|
build: {
|
|
minify: command === "build",
|
|
rolldownOptions: {
|
|
input: { index: "src/main/index.ts" },
|
|
output: {
|
|
format: "es",
|
|
// DesktopPaths resolves resources from the main output directory,
|
|
// including when the lazy desktop entry shares it with other chunks.
|
|
chunkFileNames: "[name]-[hash].js",
|
|
},
|
|
},
|
|
externalizeDeps: {
|
|
// Bundle the Effect family together.
|
|
exclude: ["effect", "@effect/platform-node", "@effect/platform-node-shared", "drizzle-orm"],
|
|
include: [nodePtyPkg],
|
|
},
|
|
},
|
|
plugins: [
|
|
{
|
|
name: "opencode:node-pty-narrower",
|
|
enforce: "pre",
|
|
resolveId(s) {
|
|
if (s === "@lydell/node-pty") return nodePtyPkg
|
|
|
|
return undefined
|
|
},
|
|
},
|
|
{
|
|
// Rolldown emits its own scoped createRequire runtime for CommonJS dependencies.
|
|
// electron-vite's post-bundle regex shim injects a top-level `const require` that collides
|
|
// with bundled ESM modules declaring their own `require` (such as @effect/platform-node).
|
|
name: "opencode:disable-esm-shim",
|
|
configResolved(config) {
|
|
const shim = config.plugins.find((plugin) => plugin.name === "vite:esm-shim")
|
|
|
|
if (shim) delete shim.renderChunk
|
|
},
|
|
},
|
|
],
|
|
},
|
|
preload: {
|
|
build: {
|
|
minify: command === "build",
|
|
rolldownOptions: {
|
|
input: { index: "src/preload/index.ts" },
|
|
output: {
|
|
format: "cjs",
|
|
// The package is "type": "module". Under --no-sandbox Electron loads the preload
|
|
// through Node's module loader, which treats a .js file as ESM and fails on
|
|
// require("electron"). The sandboxed path ignores the extension.
|
|
entryFileNames: "[name].cjs",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
renderer: {
|
|
experimental: {
|
|
bundledDev: true,
|
|
},
|
|
define: {
|
|
"import.meta.env.OPENCODE_VERSION": JSON.stringify(process.env.OPENCODE_VERSION),
|
|
"import.meta.env.VITE_OPENCODE_CHANNEL": JSON.stringify(channel),
|
|
"import.meta.env.OPENCODE_COMMIT": betaNotes ? JSON.stringify(betaNotes.sha) : "undefined",
|
|
"import.meta.env.OPENCODE_BETA_NOTES": betaNotes ? JSON.stringify(JSON.stringify(betaNotes)) : "undefined",
|
|
"import.meta.env.OPENCODE_TEST_ONBOARDING": JSON.stringify(
|
|
command === "serve" && process.env.OPENCODE_TEST_ONBOARDING === "1",
|
|
),
|
|
},
|
|
plugins: [pickerPlugin(), appPlugin, initialChunk],
|
|
publicDir: "../../../app/public",
|
|
root: "src/renderer",
|
|
build: {
|
|
minify: command === "build",
|
|
sourcemap: true,
|
|
rolldownOptions: {
|
|
input: {
|
|
main: "src/renderer/index.html",
|
|
},
|
|
output: {
|
|
codeSplitting: {
|
|
groups: [{ name: (id) => (initialGraph.has(id) ? "app" : null), priority: 10 }],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
})
|