solid-start icon indicating copy to clipboard operation
solid-start copied to clipboard

[Bug?]: Client bundle including imports from "use server" functions

Open ian-pascoe opened this issue 1 year ago • 2 comments

Duplicates

  • [X] I have searched the existing issues

Latest version

  • [X] I have tested the latest version

Current behavior 😯

Vinxi and Vite are bundling dependencies that are only used in "use server"; functions. For example:

import { Resource } from 'sst';

export function getPublicResources() {
  "use server";
  return {
    apiUrl: Resource.APIRouter.url
  } satisfies PublicResources;
}

Vite throws this error during client bundle:

[8:36:13 PM]  ERROR  ../../node_modules/sst/dist/resource.js (1:9): "env" is not exported by "__vite-browser-external", imported by "../../node_modules/sst/dist/resource.js".
file: .../Code/revelationsai/node_modules/sst/dist/resource.js:1:9

1: import { env } from "node:process";
            ^
2: const raw = {
3:     // @ts-expect-error,

Here is my app.config.ts:

import { defineConfig } from '@solidjs/start/config';
import { searchForWorkspaceRoot } from 'vite';
import { cjsInterop } from 'vite-plugin-cjs-interop';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
  middleware: './src/middleware.ts',
  server: {
    preset: 'aws-lambda'
  },
  vite: {
    plugins: [
      tsconfigPaths(),
      cjsInterop({
        dependencies: ['@clerk/clerk-js']
      })
    ],
    server: {
      fs: {
        allow: [searchForWorkspaceRoot(process.cwd())]
      }
    }
  }
});

Workaround

I can get it to bundle successfully by moving the server function to a separate file and put "use server"; at the top.

Expected behavior 🤔

"use server"; dependencies should only be included in ssr and server bundles

Steps to reproduce 🕹

Steps:

  1. In app.tsx create a server function that imports a server-only module like node:async_hooks
  2. Try to build the app

Context 🔦

This is completely blocking my project. I cannot have all my server code sectioned off with my desired design.

Your environment 🌎

No response

ian-pascoe avatar Jun 05 '24 00:06 ian-pascoe

So I have narrowed it down to if I use "verbatimModuleSyntax": true that is causing the problem. As soon as I change it to false, my project builds with "use server" imports not being shipped to the client

ian-pascoe avatar Jun 05 '24 09:06 ian-pascoe

Reproduction: https://stackblitz.com/edit/github-fk8exj-eru4op?file=src%2Fapp.tsx

verbatimModuleSyntax as explained by esbuild tells esbuild to not drop unused import statements, which is probably causing the server-only imports to not be removed from the ~~client~~ build. ~~I don't think rollup respects verbatimModuleSyntax so this seems to just be a dev-only problem.~~ Happens in build too, nevermind

Brendonovich avatar Jun 08 '24 05:06 Brendonovich

tldr; use dynamic imports so that build tools can analyze and tree-shake correctly dropping this here to spread awareness

mdynnl avatar Nov 24 '24 18:11 mdynnl

@mdynnl on top of that, if a package/module has side-effects, the bundler can potentially fail to remove the unused import.

lxsmnsyc avatar Nov 25 '24 16:11 lxsmnsyc

We have changed the server-function tree-shaking heuristics with the new plugin. It should be way more aggressive and I'm pretty sure this doesn't happen anymore (we have a few tests as well, feel free to check them and perhaps PR a broken test if you think there's more work around treeshaking that we should do!)

atilafassina avatar Feb 12 '25 09:02 atilafassina