mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-10-27 23:27:09 +09:00
## Summary - bundle Zod into the published CLI because `bundleVersion` derives from Zod schema internals - bundle `@emotion/hash`, which produces the contract identifier - prevent compatible dependency updates at install time from changing an already-published CLI's contract - add regression coverage for the CLI bundling boundary ## Root cause `webstudio@0.294.0` externalized `zod` and declared `^4.4.3`. The Builder was built with the lockfile version, while a fresh `npx webstudio@latest` installation resolved Zod 4.5.4. Because the project bundle contract is calculated at runtime from Zod definitions, the Builder expected `bundle-1mym82p` while the freshly installed CLI sent `bundle-8e39e9` despite both being the same Webstudio release. ## Packaged CLI reproduction Tested the CLI built from the parent commit and this branch in the same isolated `webstudio@0.294.0` installation with Zod 4.5.4. Both builds executed the real local `webstudio sync` command against the same capture server. - Before: `{"label":"before","zod":"4.5.4","bundleVersion":"bundle-8e39e9"}` - After: `{"label":"after","zod":"4.5.4","bundleVersion":"bundle-1mym82p"}` - Live Builder: `{"bundleVersion":"bundle-1mym82p"}` The fixed local CLI now sends the exact contract required by the live Builder even though the install environment still contains Zod 4.5.4. ## Verification - isolated before/after packaged CLI test through the real `sync` request path - `pnpm --filter webstudio exec vitest run src/cli-bundle-externals.test.ts` - `pnpm --filter webstudio typecheck` - `pnpm --filter webstudio build` - verified emitted CLI files contain no external imports from `zod` or `@emotion/hash` - `pnpm exec oxfmt --check packages/cli/vite.config.ts packages/cli/src/cli-bundle-externals.test.ts` - `git diff --check`
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
import {
|
|
defaultClientConditions,
|
|
defaultServerConditions,
|
|
defineConfig,
|
|
} from "vite";
|
|
import { createRequire } from "node:module";
|
|
import pkg from "./package.json";
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const nodeDecodeNamedCharacterReference =
|
|
require.resolve("decode-named-character-reference");
|
|
|
|
const externalDependencies = new Set(
|
|
Object.keys(pkg.dependencies).filter((name) => {
|
|
return name.startsWith("@webstudio-is/") === false;
|
|
})
|
|
);
|
|
|
|
// The project bundle contract is derived from Zod's schema definitions and
|
|
// hashed at runtime. Keep both implementations in the published artifact so a
|
|
// transitive dependency update cannot change bundleVersion after publication.
|
|
const bundledDependencies = new Set(["@emotion/hash", "acorn", "zod"]);
|
|
|
|
const getPackageName = (id: string) => {
|
|
if (id.startsWith("@")) {
|
|
return id.split("/").slice(0, 2).join("/");
|
|
}
|
|
return id.split("/")[0];
|
|
};
|
|
|
|
export const isExternal = (id: string) => {
|
|
const packageName = getPackageName(id);
|
|
return (
|
|
id.startsWith("node:") ||
|
|
(externalDependencies.has(packageName) &&
|
|
bundledDependencies.has(packageName) === false)
|
|
);
|
|
};
|
|
|
|
export default defineConfig({
|
|
resolve: {
|
|
alias: {
|
|
"decode-named-character-reference": nodeDecodeNamedCharacterReference,
|
|
},
|
|
conditions: ["webstudio", ...defaultClientConditions],
|
|
},
|
|
ssr: {
|
|
resolve: {
|
|
conditions: ["webstudio", ...defaultServerConditions],
|
|
},
|
|
},
|
|
build: {
|
|
target: "node22",
|
|
minify: false,
|
|
commonjsOptions: {
|
|
esmExternals: true,
|
|
},
|
|
lib: {
|
|
entry: ["src/cli.ts", "src/preview-server/preview-process-supervisor.ts"],
|
|
formats: ["es"],
|
|
},
|
|
rollupOptions: {
|
|
external: isExternal,
|
|
output: {
|
|
dir: "lib",
|
|
},
|
|
},
|
|
},
|
|
});
|