How it works

Compiled when your server loads, bundled for each request, run by your app: what each step does.

A screen goes through three steps: compiled when your server loads its files, bundled for each request, and run by your app.

1. Compiled with your server

Your server runs with a loader, @backtickjs/node-plugin on Node or @backtickjs/bun-plugin on Bun. As it loads each .tsx file, it compiles each cs`…` to plain JavaScript, with the compile step your framework names in package.json:

{
"backtick": {
"plugins": ["@backtickjs/react/plugin"]
}
}

A compiled script is a module: a function of its splices, which reads each splice where the script wrote it. A script compiles once, however many requests use it. To build your server ahead of time instead, @backtickjs/tspatch-plugin does the same with tspc.

2. Bundled for each request

bundler.build runs the server components you hand it, then writes what they returned as one JavaScript file:

server/Home.bundle.js
"use strict";
const { ScrollView: $i0 } = require("react-native");
const { Text: $i1 } = require("react-native");
const { useState: $i2 } = require("react");
const { Pressable: $i3 } = require("react-native");
const $module0 = require("react/jsx-runtime");
const $modules = {
"25wlsdb7ez0q4:20:9": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
exports.default = ($splice0, $splice1, $splice2, $splice3, $splice4) => ($ScrollView => /*#__PURE__*/ (0, jsx_runtime_1.jsxs)($ScrollView, {
children: [($Text => /*#__PURE__*/ (0, jsx_runtime_1.jsxs)($Text, {
children: ["Good morning, ", $splice2().name]
}))($splice1()), ($ReorderButton => /*#__PURE__*/ (0, jsx_runtime_1.jsx)($ReorderButton, {
order: $splice4()
}))($splice3())]
}))($splice0());
},
"25wlsdb7ez0q4:7:22": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
exports.default = ($splice0, $splice1, $splice2) => props => {
const [added, setAdded] = $splice0()(false);
return ($Pressable => /*#__PURE__*/ (0, jsx_runtime_1.jsx)($Pressable, {
onPress: () => setAdded(true),
children: ($Text => /*#__PURE__*/ (0, jsx_runtime_1.jsx)($Text, {
children: added ? "Added ✓" : "Reorder " + props.order.name
}))($splice2())
}))($splice1());
};
},
};
const $exports = {
"react/jsx-runtime": $module0,
};
const $require = (id) => {
if (!(id in $exports)) {
const module = { exports: {} };
$exports[id] = module.exports;
$modules[id](module, module.exports, $require);
$exports[id] = module.exports;
}
return $exports[id];
};
const $cs0 = $require("25wlsdb7ez0q4:20:9").default;
const $cs1 = $require("25wlsdb7ez0q4:7:22").default;
const $thunk0 = () => ($i0);
const $thunk1 = () => ($i1);
const $thunk2 = () => ({ id: "u-7", name: "Sam" });
const $thunk3 = () => ($i2);
const $thunk4 = () => ($i3);
const $function5 = $cs1($thunk3, $thunk4, $thunk1);
const $thunk6 = () => ($function5);
const $thunk7 = () => ({ id: "o-1042", name: "Flat white" });
module.exports = ($cs0($thunk0, $thunk1, $thunk2, $thunk6, $thunk7));

From the top:

  • The packages the app provides, required by name: react-native, react, react/jsx-runtime. Each is checked against the versions you passed as packageVersions.
  • The module table: each script's compiled module, once, however many times it's used.
  • The bundle's constants: a function script that reads nothing of where it's used is made once, $function<n>, and each splice is a function the script calls when it reads it, $thunk<n>. The same code anywhere in the bundle is the same constant, so a value used at every level of a screen is written once.
  • The root: the screen, as the call of its script.

Only what a request drew is in its bundle, and data is written as data, never as code. generate writes it as CommonJS, "cjs", for React Native, or as an ES module, "es", for a web page, with an optional source map into your server files.

3. Run by your app

The app fetches the bundle like any request, and runs it with evaluate from @backtickjs/react-native-client, handing it the packages it ships. What the bundle exports is the screen, a React element the app draws. See Thinking in Backtick for the server route and the app code.

Because the phone runs code your server wrote, a deploy of your server is a release of the screen: the next time someone opens it, they get the new one.