[Bug?]: (v1.1.0) Unable to inline server functions in components
Duplicates
- [x] I have searched the existing issues
Latest version
- [x] I have tested the latest version
Current behavior 😯
Previously we were able to inline server functions directly in components. Since v1.1.0 this is no longer possible and throws a very verbose error (including the full component three times).
Expected behavior 🤔
I'm wondering if this change is deliberate or a bug. If it is deliberate, maybe the error message can be improved.
Steps to reproduce 🕹
import { action, useAction } from "@solidjs/router";
import { isServer } from "solid-js/web";
export default function Home() {
const myAction = useAction(
action(async () => {
"use server";
console.log(isServer);
}),
);
return (
<main>
<button onClick={myAction}>Action</button>
</main>
);
}
pnpm build
📦 Compiling ssr router...
vinxi building router ssr in http mode
vite v6.1.0 building SSR bundle for production...
✓ 1 modules transformed.
x Build failed in 63ms
ERROR [tanstack-start-directive-vite-plugin] 1 | import { action, useAction } from "@solidjs/router"; 4:06:43 AM
2 | import { isServer } from "solid-js/web";
> 3 | export default function Home() {
| ^^
> 4 | const myAction = useAction(action(async () => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 5 | "use server";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 6 |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 7 | console.log(isServer);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 8 | }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 9 | return <main>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 10 | <button onClick={myAction}>Action</button>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 11 | </main>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 12 | }
| ^ Server Functions cannot be nested in other blocks or functions
file: /home/peter/Projects/test/solid-start-inline-fn/src/routes/index.tsx?pick=default&pick=$css
2 | import { isServer } from "solid-js/web";
> 3 | export default function Home() {
| ^^
> 4 | const myAction = useAction(action(async () => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 5 | "use server";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 6 |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 7 | console.log(isServer);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 8 | }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 9 | return <main>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 10 | <button onClick={myAction}>Action</button>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 11 | </main>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 12 | }
| ^ Server Functions cannot be nested in other blocks or functions
file: src/routes/index.tsx?pick=default&pick=$css
at codeFrameError (node_modules/.pnpm/@[email protected]/node_modules/@tanstack/directive-functions-plugin/dist/esm/compilers.js:326:10)
at DirectiveLiteral (node_modules/.pnpm/@[email protected]/node_modules/@tanstack/directive-functions-plugin/dist/esm/compilers.js:177:19)
at NodePath._call (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:49:20)
at NodePath.call (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:39:18)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:88:31)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitSingle (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:66:19)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:113:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitMultiple (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:62:17)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:111:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitSingle (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:66:19)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:113:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitMultiple (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:62:17)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:111:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitMultiple (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:62:17)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:111:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitSingle (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:66:19)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:113:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitMultiple (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:62:17)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:111:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitMultiple (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:62:17)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:111:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
at TraversalContext.visitQueue (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:90:16)
at TraversalContext.visitSingle (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:66:19)
at TraversalContext.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:113:19)
at traverseNode (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/traverse-node.js:22:17)
at NodePath.visit (node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:94:52)
ERROR [tanstack-start-directive-vite-plugin] 1 | import { action, useAction } from "@solidjs/router"; 4:06:43 AM
2 | import { isServer } from "solid-js/web";
> 3 | export default function Home() {
| ^^
> 4 | const myAction = useAction(action(async () => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 5 | "use server";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 6 |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 7 | console.log(isServer);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 8 | }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 9 | return <main>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 10 | <button onClick={myAction}>Action</button>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 11 | </main>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 12 | }
| ^ Server Functions cannot be nested in other blocks or functions
file: /home/peter/Projects/test/solid-start-inline-fn/src/routes/index.tsx?pick=default&pick=$css
ERROR Exited with code: 1 4:06:43 AM
at CommandChild.pipedStdoutBuffer (node_modules/.pnpm/[email protected]/node_modules/dax-sh/esm/mod.js:9392:19)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
ERROR Exited with code: 1 4:06:43 AM
ELIFECYCLE Command failed with exit code 1.
Context 🔦
No response
Your environment 🌎
Hi, @peterhirn yes, that's an unpredicted regression. It's on me and I'm really sorry about that.
The new server-function plugin has much more aggressive treeshaking, this prevents code from leaking to the frontend. Unfortunately, as a consequence of that, it does not perform closure extraction.
As a workaround, you can refactor your code like such:
import { action, useAction } from "@solidjs/router";
import { isServer } from "solid-js/web";
const yourServerAction = action(async () => {
"use server";
console.log(isServer);
}),
export default function Home() {
const myAction = useAction(yourServerAction);
return (
<main>
<button onClick={myAction}>Action</button>
</main>
);
}
And that would work again, plus, even in the old plugin - that would make your code safer, imho, by making it easier for the code-removal preventing it to land in the client-side bundle.
I'm still working on a better DX, either to migrate or to add code-extraction to the plugin.
Hello, I wanted to confirm this is the same issue
This code causes the same error original post showed:
import { createAsync } from "@solidjs/router";
export default function Home() {
const test = createAsync(async () => {
"use server";
console.log("Test!");
return;
});
return <main class=""></main>;
}
While this code works fine:
import { createAsync } from "@solidjs/router";
import { isServer } from "solid-js/web";
export default function Home() {
const test = createAsync(async () => {
if (!isServer) return;
console.log("Test!");
return;
});
return <main class=""></main>;
}
It seems related/the same but I just thought I'd put this here in case anyone needs more info