For AI agents: the complete documentation index is available at /next/llms.txt, the full documentation bundle is available at /next/llms-full.txt, and this page is available as Markdown at /next/guide/build/index.md.
Lynx
  • English
  • 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:

    npm create @lynx-js/lynx@latest -- --template rsbuild-react-ts

    In the generated project directory, install dependencies and start the dev server:

    npm install
    npm run dev

    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:

    rsbuild.config.ts
    import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin';
    import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
    import { defineConfig } from '@rsbuild/core';
    
    export default defineConfig({
      source: {
        entry: {
          main: './src/index.tsx',
        },
      },
      plugins: [pluginQRCode(), pluginReactLynx()],
    });

    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. pluginLynx prefers dependencies' lynx export condition; see resolve.extensions for 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:

    Still using Rspeedy?

    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:

    PartWeb appLynx Bundle
    ScriptsJavaScript files loaded at runtimeEncoded into the bundle by default; main-thread code creates the first screen, while background-thread code runs application logic
    StylesCSS files loaded at runtimeCSS parsed into structured data and encoded into the bundle
    AssetsSeparate images, fonts and other files, with small assets optionally inlinedAlso supports separate files and inlining small assets
    EntryThe browser loads HTML, then the scripts, styles and assets it referencesThe host loads the bundle directly, including page configuration and other metadata

    Output files

    Standard Lynx Bundle output

    Build output goes into dist/ by default:

    dist/
    ├── [name].lynx.bundle  # application bundle
    ├── lazy-bundle/       # bundles loaded on demand
    ├── static/            # static assets and split scripts
    └── .lynx/[name]/      # intermediates for debugging

    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 in lazy-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.

    Engine Version

    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:

    rsbuild.config.ts
    import { defineConfig } from '@rsbuild/core';
    import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
    
    export default defineConfig({
      plugins: [
        pluginReactLynx({
          engineVersion: '3.2',
        }),
      ],
    });

    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:

    // Detect if `lynx.newlyAddedMethod` can be called
    if (lynx.newlyAddedMethod) {
      lynx.newlyAddedMethod();
    }

    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 engineVersion are 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

    Except as otherwise noted, this work is licensed under a Creative Commons Attribution 4.0 International License, and code samples are licensed under the Apache License 2.0.