From Source to Bundle
Lynx builds use Rsbuild with pluginLynx. Use Rsbuild's TypeScript, CSS, static asset and plugin capabilities, while pluginLynx compiles code for both threads and encodes the bundles your host loads.
Get started with Rsbuild
Create a project with the ReactLynx Rsbuild template:
In the generated project directory, install dependencies and start the dev server:
Scan the QR code with Lynx Explorer to run the app on a device. The dev server updates the app when you save your code.
The template's build configuration lives in rsbuild.config.ts. pluginReactLynx applies pluginLynx automatically, and pluginQRCode provides the QR code:
When development is complete, use rsbuild build to generate production files and rsbuild preview to preview them locally.
Configure your app
rsbuild.config.ts accepts the full Rsbuild configuration. Configure the capabilities your project needs:
- TypeScript: build-time declarations and types for application data, elements and native modules.
- CSS: CSS Modules, global styles, pre-processors and PostCSS. For Tailwind, see the Lynx preset setup.
-
Static assets: images,
fonts, the
public/directory, URL prefixes and inlining. -
Module resolution: path aliases
and dependency resolution.
pluginLynxprefers dependencies'lynxexport condition; seeresolve.extensionsfor file extensions. -
Plugins: add Rsbuild plugins or extend
the underlying build through
tools.rspack.
The rsbuild.config.ts reference describes Lynx-specific options and changed defaults. For example, to customize the bundle filename, explicitly add pluginLynx({ output: { filename: { bundle: 'app.lynx.bundle' } } }) to plugins; it will not be applied twice.
Optimize and debug
The build also provides ways to control loading, investigate performance and diagnose problems:
- Code splitting: load some code on demand to reduce what the first screen needs.
- External Bundle: build common dependencies into a bundle shared by several apps.
- Build profiling: use tools such as Rsdoctor to understand build time and dependencies.
- Runtime profiling and bundle size analysis: investigate runtime and loading costs.
- Production error mapping and UI source maps: use build-generated debugging information to connect errors and rendered nodes to source code.
Rspeedy is still maintained and uses the same build engine as pluginLynx. Existing projects can keep using it; Rsbuild is recommended for new projects. See the Rspeedy migration guide for the differences and migration steps.
Understand the output
A Lynx Bundle is the deliverable
for a Lynx app: a binary file ending in .lynx.bundle. The host passes its URL
or contents to the Lynx Engine, which loads it and renders
the page. A Lynx Bundle has much in common with a web app:
Output files
Standard Lynx Bundle output
Build output goes into dist/ by default:
Scripts are encoded into the bundle by default; code splitting can also produce files in static/js/. Set the bundle filename with output.filename.bundle, other filenames with output.filename, and output directories with output.distPath. See the APIs for source maps and license comments for those options.
Web output
The same source can also target the web: the web environment produces a .web.bundle, loaded by <lynx-view url="...">. The [platform] placeholder in the default filename is the environment name, so the two environments produce main.lynx.bundle and main.web.bundle respectively.
From intermediate files to binary
The build first produces the main-thread script main-thread.js, the background-thread script background.js and styles. The tasm.json file organizes these contents and page configuration for @lynx-js/tasm to encode into the .lynx.bundle binary.
These intermediate files live in .lynx/[name]/ and are kept in development builds by default; use DEBUG=lynx to retain them in production builds. Inspect tasm.json to see what the bundle encodes; debug-metadata.json supports Production Error Mapping.
An app can have multiple bundles
Besides the main bundle, an app can load other bundles on demand or share them:
- Lazy bundles: load components through dynamic
import(), with output inlazy-bundle/, to reduce what the first screen needs. See Code Splitting. - External Bundle: build common dependencies into a separate bundle shared by several apps. See External Bundle.
Compatibility
This article explains how to ensure version compatibility between Bundle and Lynx Engine, and how to handle challenges that come with Lynx Engine version evolution.
Build from Source
A simple way to ensure compatibility is to always build the Bundle with the Host application from source.
- Bundle can fully utilize all features of the current Lynx Engine version
- Compatibility can be fully verified during development, what you see is what you get
Multi-version Compatibility
However, in a complex project, the relationship between Bundle and Lynx Engine is not one-to-one:
-
A Bundle might run in applications with different Lynx Engine versions
-
An application can run multiple Bundles maintained by different teams
In this case, you need to set the engineVersion to ensure compatibility.
When the Bundle's engineVersion is greater than the Lynx Engine version, it will not be able to run.
For example: a Bundle with engineVersion 3.3 can run on Lynx Engine 3.3 and later versions, but cannot run on 3.2.
When a Bundle needs to run on multiple Lynx Engine versions, its engineVersion must not exceed the oldest Lynx Engine version it targets.
When running multiple Bundles on a single Lynx Engine version, each Bundle can set different engineVersions, but none can be greater than the Lynx Engine version.
Version Incompatibility Handling
If you try to run a Bundle on a lower version of the Lynx Engine, a Fatal level error with code 10204 will occur, and the rendering process will stop. This mechanism prevents potential runtime issues caused by version incompatibility.
Configuring Engine Version
The engineVersion is a string containing two version numbers, and you can specify it in your configuration file:
Upgrading Lynx Engine
As Lynx Engine evolves, new features are added and some features may be deprecated. Their compatibility is also managed by engineVersion.
New Features
Some new features will not affect existing Bundles, but if engineVersion is lower than the version where they were introduced, runtime detection is needed, for example:
While some new features cannot run on lower versions of the Lynx Engine at all, so they will only be enabled when engineVersion is greater than or equal to the corresponding version.
Deprecated Features
Some features may be deprecated during iteration, and their behavior may change when a higher engineVersion is set.
- If only the Lynx Engine version is upgraded without upgrading the Bundle's
engineVersion, there will be no compatibility issues - If both Lynx Engine and Bundle's
engineVersionare upgraded, you need to read the CHANGELOG to ensure there are no unexpected behavior changes
Feature and API compatibility
Check each feature, element, API or CSS property's reference for platform support. The example below shows cross-platform compatibility for CSS gap:
LCD tables only load in the browser