Skip to content
Closed
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b1d545b
refactor(transforms): run the browser server-exports strip before com…
kojiwakayama Aug 18, 2026
53714ad
fix(transforms): keep leading comments of statements the strip removes
kojiwakayama Aug 18, 2026
30c64ee
fix(transforms): keep comments that trail the last surviving statement
kojiwakayama Aug 18, 2026
0e476a8
fix(transforms): leave unrelated unused imports as authored
kojiwakayama Aug 18, 2026
7c1028a
docs(transforms): note the splitter caller in the ordering dependency
kojiwakayama Aug 18, 2026
8714b73
fix(transforms): delete hook-owned imports on every source dialect
kojiwakayama Aug 18, 2026
d6e744c
fix(transforms): never prune an exported import-equals
kojiwakayama Aug 18, 2026
b0f7653
test(transforms): pin the unrelated unused import in development
kojiwakayama Aug 19, 2026
e52fe75
fix(transforms): classify JSX references in the server-exports strip
kojiwakayama Aug 19, 2026
afc3eb7
fix(repo): remove the stray node_modules symlink committed by mistake
kojiwakayama Aug 19, 2026
9df87a2
fix(transforms): classify every reference-walker node type
kojiwakayama Aug 19, 2026
8db5dbc
test(transforms): pin every classification cell with a mutation-kille…
kojiwakayama Aug 19, 2026
89d59a5
fix(transforms): test every compiler predicate against the compiler
kojiwakayama Aug 19, 2026
30f34a8
test(transforms): let the compiler settle engine identifier-table drift
kojiwakayama Aug 19, 2026
c4e4fd7
Prevent escaped hook exports from reaching browser bundles
kojiwakayama Aug 20, 2026
51b31a5
Merge origin/main into strip-before-compile work
kojiwakayama Aug 20, 2026
c53015a
Refresh API reference after main merge
kojiwakayama Aug 20, 2026
e41b944
Drop unrelated API reference churn
kojiwakayama Aug 20, 2026
55cd797
fix(transforms): decide the strip gate from the grammar, not from spe…
kwakayama Aug 21, 2026
191234f
test(transforms): ask the artifact which names the module exports
kwakayama Aug 21, 2026
1f1d0c4
Merge origin/main into strip-before-compile work
kwakayama Aug 21, 2026
2262c26
fix(transforms): reject import-equals hook bindings before compile
kojiwakayama Aug 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ __test_project__/

# Dependencies
node_modules/
node_modules

# NPM config
# Local npm configs may contain credentials. Track only the root policy file.
Expand Down
23 changes: 23 additions & 0 deletions docs/guides/data-fetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ entirely, including their top-level side effects. Put client initialization in a
separate client-referenced module or a bare side-effect import that is not only
used by a server data hook.

Declare each data hook in the page module itself. Re-exporting one from another
file fails the browser build, with or without an alias:

```tsx
// Not supported. Both forms stop the build.
export { getServerData } from "../server/loaders.ts";
export { loadDashboard as getServerData } from "../server/loaders.ts";
```

A re-export binds no local declaration, so Veryfront has nothing to strip and
the loader module, its imports, and anything it closes over would reach the
browser. Declare the hook in the page and import the helpers it needs:

```tsx
// app/dashboard/page.tsx
import type { DataContext } from "veryfront";
import { loadDashboard } from "../server/loaders.ts";

export async function getServerData(ctx: DataContext) {
return { props: await loadDashboard(ctx) };
}
```

The `props` you return are passed to the page component. To read the same props
data from a layout or nested component without prop-drilling, use
`usePageContext().data` (see
Expand Down
2 changes: 1 addition & 1 deletion src/transforms/pipeline/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ const SSR_PIPELINE: TransformPlugin[] = [

const BROWSER_PIPELINE: TransformPlugin[] = [
parsePlugin,
browserServerExportsStripPlugin, // Drop server-only hooks + their now-unused imports
Comment thread
kojiwakayama marked this conversation as resolved.
compilePlugin,
cssStripPlugin, // Strip CSS imports before they hit import resolution
browserServerExportsStripPlugin, // Drop server-only hooks + their now-unused imports
browserNodeBuiltinImportsPlugin, // node:* named imports -> namespace + destructure
resolveImportsPlugin, // Unified import resolution
finalizePlugin,
Expand Down
1,268 changes: 1,083 additions & 185 deletions src/transforms/pipeline/stages/browser-server-exports-strip.test.ts

Large diffs are not rendered by default.

561 changes: 357 additions & 204 deletions src/transforms/pipeline/stages/browser-server-exports-strip.ts

Large diffs are not rendered by default.

31 changes: 1 addition & 30 deletions src/transforms/pipeline/stages/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,6 @@ const ReflectApply = Reflect.apply;
const ReflectGetOwnPropertyDescriptor = Reflect.getOwnPropertyDescriptor;
const SOURCE_MAP_SUFFIX =
/(^|\r?\n)[\t ]*\/\/[#@][\t ]*sourceMappingURL=[^"'`\s]+[\t ]*(?:\r?\n)?$/;
export const COMPILE_SOURCE_MAP_DIRECTIVE_METADATA = "compileSourceMapDirective";
export const COMPILE_SOURCE_MAP_INPUT_METADATA = "compileSourceMapInput";

function trailingSourceMapDirective(code: string): string | undefined {
const match = SOURCE_MAP_SUFFIX.exec(code);
return match?.[0].slice((match[1] ?? "").length).trimEnd();
}

function dropTrailingSourceMapDirective(code: string): string {
return code.replace(SOURCE_MAP_SUFFIX, "$1");
}

function appendBeforeSourceMap(code: string, addition: string): string {
const match = SOURCE_MAP_SUFFIX.exec(code);
if (match?.index === undefined) return code + addition;
Expand Down Expand Up @@ -108,27 +96,10 @@ export const compilePlugin: TransformPlugin = {
/\bconst\s+MDXLayout\b/.test(code) &&
!/export\s+\{[^}]*MDXLayout/.test(code)
) {
// Keep esbuild's directive last. Browser server-hook stripping removes
// a stale compile map after rewriting, and a framework export appended
// after the directive would otherwise hide that suffix.
// Keep esbuild's directive last.
code = appendBeforeSourceMap(code, "\nexport { MDXLayout };\n");
}

const sourceMapDirective = trailingSourceMapDirective(code);
if (ctx.target === "browser" && sourceMapDirective) {
// Keep the compiler map out of intermediate browser plugins. The
// server-export strip stage restores it only when the map-free compile
// output is unchanged and no hook is rewritten. This makes the real
// comment unambiguous even if a plugin copies its text into a string,
// appends code, or removes the hook itself.
ctx.metadata.set(COMPILE_SOURCE_MAP_DIRECTIVE_METADATA, sourceMapDirective);
code = dropTrailingSourceMapDirective(code);
ctx.metadata.set(COMPILE_SOURCE_MAP_INPUT_METADATA, code);
} else {
ctx.metadata.delete(COMPILE_SOURCE_MAP_DIRECTIVE_METADATA);
ctx.metadata.delete(COMPILE_SOURCE_MAP_INPUT_METADATA);
}

return code;
} catch (err) {
const errorMsg = err instanceof Error ? err.message : String(err);
Expand Down
Loading