Find out what won't compile
FSR turns your TypeScript into data a Rust host runs. Some code can't be expressed that way. You'll write some, read what the build says about it and see the two kinds of message it gives.
Before you start
Install from crates.io. You need no Node and no package manager.
cargo install snapfire_compiler
cargo install snapfire_fsr_cli
fsr --version
Every command and screenshot on this page was captured with fsr 0.x.
Break a loader#
A loader has to run in Rust, so the build is strict about it. Try normalizing a string.
;
normalize isn't a builtin a loader can use. You get the line and column, a non-zero exit and nothing written. The error comes from the build, before any request runs.
Break a component#
The build treats a component differently, because a component that can't be lowered can still run in the browser.
Take normalize back out of the loader and have it return a weight instead:
;
Then round the weight in the page:
;
The build succeeds and the page works. The build moved the smallest part of the markup around the call, the <p>, into an island module beside the page, page.island0.tsx. That island renders in the browser. The rest of the page still renders on the server. The report names the line that caused it, where the island is placed and the builtins you could use instead.
Errors and report lines#
A loader refusal is an error because there's no fallback: the loader has to run in Rust or it doesn't run. A component refusal is a report line because the component can still run in the browser. A component that needs the browser, such as one using a canvas, belongs there.
The second kind is easy to miss because nothing fails. Read the
clientrows on every build so you notice when part of a page stops being server-rendered.
Where a refusal lands#
One unlowerable call in a small leaf component marks that component client and nothing else. The page that places it stays lowered and renders on the server. Only the component renders in the browser, at the place the report names:
The cost is still real: the component's code ships to the browser and its markup arrives after the script runs.
How to fix it#
Move the work into the loader. The loader already runs in Rust and has a wider vocabulary than a render path does, so format the value there before it reaches the component.
The other fix is to put it in a module-level helper the build can read, which the report's last line suggests. A named function at module scope gets lowered once and called from the render path.
Next up: 130. Validate a form.