one
Version:
One is a new React Framework that makes Vite serve both native and web.
463 lines (421 loc) • 20.1 kB
JavaScript
"use strict";
var import_vitest = require("vitest");
var import_clientTreeShakePlugin = require("./clientTreeShakePlugin.native.js");
(0, import_vitest.describe)("clientTreeShakePlugin", function () {
(0, import_vitest.describe)("transformTreeShakeClient", function () {
(0, import_vitest.it)("should remove loader export and its imports", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { Text } from 'react-native'
import { useLoader } from 'one'
export function loader() {
return serverOnlyModule()
}
export default function Page() {
const data = useLoader(loader)
return <Text>{data}</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
(0, import_vitest.expect)(result.code).toContain("react-native");
(0, import_vitest.expect)(result.code).toContain("one");
});
(0, import_vitest.it)("should remove loader export with dynamic import", async function () {
var code = `
import { Text } from 'react-native'
import { useLoader } from 'one'
export async function loader() {
const { serverFn } = await import('server-only-pkg')
return serverFn()
}
export default function Page() {
const data = useLoader(loader)
return <Text>{data}</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
});
(0, import_vitest.it)("should remove loader with const arrow function export", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { Text } from 'react-native'
import { useLoader } from 'one'
export const loader = async () => {
return serverOnlyModule()
}
export default function Page() {
const data = useLoader(loader)
return <Text>{data}</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
});
(0, import_vitest.it)("should handle multiple imports where only some are used in loader", async function () {
var code = `
import { serverFn } from 'server-only-pkg'
import { sharedUtil } from 'shared-pkg'
import { Text } from 'react-native'
import { useLoader } from 'one'
export function loader() {
return serverFn()
}
export default function Page() {
const data = useLoader(loader)
return <Text>{sharedUtil(data)}</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
(0, import_vitest.expect)(result.code).toContain("shared-pkg");
});
(0, import_vitest.it)("should remove generateStaticParams and its imports", async function () {
var code = `
import { getRoutes } from 'server-only-pkg'
import { Text } from 'react-native'
export function generateStaticParams() {
return getRoutes()
}
export default function Page() {
return <Text>Hello</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/[slug].tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
});
(0, import_vitest.it)("should not transform files without loader or generateStaticParams", async function () {
var code = `
import { Text } from 'react-native'
export default function Page() {
return <Text>Hello</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeUndefined();
});
(0, import_vitest.it)("should embed routeId in loader stub when root is provided", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { useLoader } from 'one'
export async function loader() {
return serverOnlyModule()
}
export default function Layout() {
const data = useLoader(loader)
return data
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/project/app/_layout.tsx", "/project");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('export function loader() {return "./_layout.tsx"}');
(0, import_vitest.expect)(result.code).not.toContain("__vxrn__loader__");
});
(0, import_vitest.it)("should strip a custom router root from the loader stub routeId", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { useLoader } from 'one'
export const loader = async () => {
return serverOnlyModule()
}
export default function Page() {
const data = useLoader(loader)
return data
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/project/app-sootsim/(marketing)/changelog/index+ssg.tsx", "/project", "app-sootsim");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('export function loader() {return "./(marketing)/changelog/index+ssg.tsx"}');
});
(0, import_vitest.it)("should embed routeId with render mode suffix in loader stub", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { useLoader } from 'one'
export async function loader() {
return serverOnlyModule()
}
export default function Layout() {
const data = useLoader(loader)
return data
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/project/app/user+ssr.tsx", "/project");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('export function loader() {return "./user+ssr.tsx"}');
});
(0, import_vitest.it)("should fall back to __vxrn__loader__ stub when no root provided", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { useLoader } from 'one'
export async function loader() {
return serverOnlyModule()
}
export default function Page() {
const data = useLoader(loader)
return data
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain("__vxrn__loader__");
});
(0, import_vitest.it)("should not transform route file when loader is imported (no inline declaration)", async function () {
var code = `
import { loader } from './loaders/my-loader'
import { useLoader } from 'one'
export { loader }
export default function Layout() {
const data = useLoader(loader)
return data
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/project/app/_layout.tsx", "/project");
(0, import_vitest.expect)(result).toBeUndefined();
});
(0, import_vitest.it)("should tree-shake server imports from source file where loader is defined", async function () {
var sourceCode = `
import { db } from 'server-only-db'
export async function loader() {
return db.query('SELECT * FROM users')
}
export function helperUsedByClient() {
return 'hello'
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(sourceCode, "/project/app/loaders/my-loader.ts", "/project");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-db");
(0, import_vitest.expect)(result.code).toContain("helperUsedByClient");
(0, import_vitest.expect)(result.code).toContain('export function loader() {return "./loaders/my-loader.ts"}');
});
(0, import_vitest.it)("should not transform re-export from source syntax", async function () {
var code = `
export { loader } from './loaders/shared-loader'
import { useLoader } from 'one'
export default function Page() {
return 'hello'
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/project/app/page.tsx", "/project");
(0, import_vitest.expect)(result).toBeUndefined();
});
(0, import_vitest.it)("should preserve type-only imports during tree shaking", async function () {
var code = `
import type { SomeType } from 'types-pkg'
import { serverFn } from 'server-only-pkg'
import { Text } from 'react-native'
import { useLoader } from 'one'
export function loader(): SomeType {
return serverFn()
}
export default function Page() {
const data = useLoader(loader)
return <Text>{data}</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain("types-pkg");
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
});
(0, import_vitest.it)("should preserve type imports even when used only in loader", async function () {
var code = `
import type { APIGuildMember } from '@discordjs/core'
import { getClient } from 'discord-client'
import { Text } from 'react-native'
import { useLoader } from 'one'
export function loader(): APIGuildMember {
return getClient()
}
export default function Page() {
const data = useLoader(loader)
return <Text>{JSON.stringify(data)}</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain("@discordjs/core");
(0, import_vitest.expect)(result.code).not.toContain("discord-client");
});
(0, import_vitest.it)("should preserve side-effect imports during tree shaking", async function () {
var code = `
import './style.css'
import { serverOnlyModule } from 'server-only-pkg'
import { Text } from 'react-native'
export function loader() {
return serverOnlyModule()
}
export default function Page() {
return <Text>Hello</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain("import './style.css'");
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
});
(0, import_vitest.it)("should remove transitive local bindings exclusively used by loader", async function () {
var code = `
import { db } from 'server-only-db'
import { Text } from 'react-native'
const secretKey = 'my-secret'
function querySecret() {
return db.query(secretKey)
}
export async function loader() {
return querySecret()
}
export default function Page() {
return <Text>Hello</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-db");
(0, import_vitest.expect)(result.code).not.toContain("secretKey");
(0, import_vitest.expect)(result.code).not.toContain("querySecret");
(0, import_vitest.expect)(result.code).toContain("export default function Page");
});
(0, import_vitest.it)("should preserve shared local bindings used by both loader and client", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { Text } from 'react-native'
const sharedConfig = { siteName: 'One' }
function getTitle() {
return sharedConfig.siteName
}
export function loader() {
serverOnlyModule()
return getTitle()
}
export default function Page() {
return <Text>{getTitle()}</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("server-only-pkg");
(0, import_vitest.expect)(result.code).toContain("sharedConfig");
(0, import_vitest.expect)(result.code).toContain("getTitle");
});
(0, import_vitest.it)("should throw build error on syntax error in production", async function () {
var origEnv = process.env.NODE_ENV;
try {
process.env.NODE_ENV = "production";
var code = `
import { serverOnly } from 'server-only-pkg'
export function loader() {
bad syntax {
}
`;
await (0, import_vitest.expect)((0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx")).rejects.toThrow(/Failed to parse/);
} finally {
process.env.NODE_ENV = origEnv;
}
});
(0, import_vitest.it)("should log warning and return undefined on syntax error in development", async function () {
var origEnv = process.env.NODE_ENV;
try {
process.env.NODE_ENV = "development";
var code = `
import { serverOnly } from 'server-only-pkg'
export function loader() {
bad syntax {
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeUndefined();
} finally {
process.env.NODE_ENV = origEnv;
}
});
(0, import_vitest.it)("should generate a valid sourcemap", async function () {
var code = `
import { serverOnlyModule } from 'server-only-pkg'
import { Text } from 'react-native'
export function loader() {
return serverOnlyModule()
}
export default function Page() {
return <Text>Hello</Text>
}
`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.map).toBeDefined();
(0, import_vitest.expect)(result.map.mappings).toBeDefined();
});
(0, import_vitest.it)("preserves shared import referenced in destructuring default parameter", async function () {
var code = `import {shared} from "./shared"; export function loader(){return shared}; export default function Page({x = shared}) {return x}`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('import {shared} from "./shared"');
(0, import_vitest.expect)(result.code).toContain("Page({x = shared})");
(0, import_vitest.expect)(result.code).toContain("export function loader()");
});
(0, import_vitest.it)("preserves shared import referenced in top-level executable statement", async function () {
var code = `import {shared} from "./shared"; export function loader(){return shared}; if (globalThis.ready) shared();`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('import {shared} from "./shared"');
(0, import_vitest.expect)(result.code).toContain("if (globalThis.ready) shared();");
(0, import_vitest.expect)(result.code).toContain("export function loader()");
});
(0, import_vitest.it)("preserves shared import referenced in top-level retained initializer", async function () {
var code = `import {shared} from "./shared"; const retained = shared(); export function loader(){return shared}; export default function Page(){return null}`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('import {shared} from "./shared"');
(0, import_vitest.expect)(result.code).toContain("const retained = shared();");
(0, import_vitest.expect)(result.code).toContain("export function loader()");
});
(0, import_vitest.it)("removes top-level declaration and import used exclusively by loader", async function () {
var code = `import {secret} from "./secret"; const localSecret = secret(); export function loader(){return localSecret}; export default function Page(){return null}`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("./secret");
(0, import_vitest.expect)(result.code).not.toContain("localSecret");
(0, import_vitest.expect)(result.code).toContain("export function loader()");
});
(0, import_vitest.it)("preserves shared import referenced in top-level destructuring default binding", async function () {
var code = `import {shared} from "./shared"; const {x = shared} = {}; export function loader(){return [x,shared]}; export default function Page(){return x}`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('import {shared} from "./shared"');
(0, import_vitest.expect)(result.code).toContain("const {x = shared} = {}");
(0, import_vitest.expect)(result.code).toContain("return x");
});
(0, import_vitest.it)("removes server-only import referenced in top-level destructuring default binding when used only by loader", async function () {
var code = `import {secret} from "./server"; const {x = secret} = {}; export function loader(){return x}; export default function Page(){return null}`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("./server");
(0, import_vitest.expect)(result.code).not.toContain("secret");
(0, import_vitest.expect)(result.code).not.toContain("{x = secret}");
(0, import_vitest.expect)(result.code).toContain("Page(){return null}");
});
(0, import_vitest.it)("removes server-only enum and class declarations used only by loader", async function () {
var code = `import {server} from "./server"; enum E { X = server() }; export function loader() {return E.X}; export default function Page(){return null}`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).not.toContain("./server");
(0, import_vitest.expect)(result.code).not.toContain("enum E");
(0, import_vitest.expect)(result.code).toContain("Page(){return null}");
});
(0, import_vitest.it)("preserves shared enum used by both loader and client Page", async function () {
var code = `import {shared} from "./shared"; enum E { X = shared() }; export function loader() {return E.X}; export default function Page(){return E.X}`;
var result = await (0, import_clientTreeShakePlugin.transformTreeShakeClient)(code, "/app/index.tsx");
(0, import_vitest.expect)(result).toBeDefined();
(0, import_vitest.expect)(result.code).toContain('import {shared} from "./shared"');
(0, import_vitest.expect)(result.code).toContain("enum E");
(0, import_vitest.expect)(result.code).toContain("Page(){return E.X}");
});
});
});
//# sourceMappingURL=clientTreeShakePlugin.test.native.js.map