Bundle Generation
Elegance runs on a model of allowing server-side and client-side code to be written in one page.
Much like the idea of writing JS in HTML with JSX, and CSS in HTML with tailwind, we believe having your logic in 1 localized place helps developers reason about code better, and makes development less tangled and faster.
Boundaries
There's a few places you can't run server-side code, as they're considered seeding points for the page's bundle.
Within a component:
The view, onMount, onUnmount, and onNavigate methods are considered client only; but init can (by design) run server-side code, and is always guaranteed to be stripped from the bundle.
The atoms property is also considered client-side; so initializing an atom's using server-side code isn't allowed. Instead you should use the init method.
onPageLoad
The onPageLoad callback is a no-op on the server; because it's designed to run in the browser after hydration. Any transitively referenced variable within will be bundled.
on* Events
Values references within event handlers are required for the event handler (like onClick) to run, and thus need to be bundled. If you'd like to run server-side code within your event handler, consider server-actions.
Safety
We recognise DCE isn't perfect and that developers make mistakes. If you really want to be sure that something doesn't end up in the client bundle, you can use the //!no-bundle directive directly above the definition of that thing like so:
//!no-bundle const ENV_SECRET = "iLikeCats123";Then, if a page foolishly imports it, it will throw a compilation error instead of leaking your secrets.
╭────────────────────────────────────────────────────────╮ │ ✗ ERROR │ ╰────────────────────────────────────────────────────────╯ ⚠ Server Only Error The following declarations are marked server-only but were reached by the client bundle: • ENV_SECRET at <onPageLoad()> (/docs/advanced/bundle-generation:1110:15) | console.log(ENV_SECRET); | ^ The inclusion of server-only variables in client-side code is almost always unintentional. If these are references you did not intend to mark server-only, you can remove the //!no-bundle flag above their declarations. If that is not the case, remove the reference that cause their inclusion.Splitting
Elegance uses esbuild for the generation of bundles, and so splitting across shared imported modules is automatically enabled for both dev and prod builds.
If you have two pages, A & B:
/pages/lib.ts const counter = atom(0); export function increment() { counter.value++; console.log(counter.value) } /pages/a/page.tsx import { increment } from "../lib"; export default function page() { return <div> <button onClick={() => increment()}> Increment </button> </div> } /pages/b/page.tsx import { increment } from "../lib"; export default function page() { return <div> <button onClick={() => increment()}> Increment </button> </div> }Because of the ESM cache, when both modules import the shared chunk, counter remains the same, and the state is maintained not only on other pages, but upon returning back to the same page, the values remain.