Building & Deployment

Get your OneJS app running in standalone builds and WebGL.

Build Process

When you build your Unity project:

  1. JSRunnerBuildProcessor runs automatically during the build
  2. Locates each JSRunner's app.js.txt bundle (TextAsset)
  3. Assigns it to the JSRunner for runtime loading
Styles: CSS Modules and Tailwind styles are embedded in your JavaScript bundle, so they work automatically. Regular USS files loaded via loadStyleSheet() need to be copied to StreamingAssets manually.

Standalone Builds

Works automatically. The JavaScript bundle is stored as a TextAsset in your project and loaded at runtime. No StreamingAssets path configuration needed.

WebGL Builds

WebGL works with some differences:

  • JavaScript runs in the browser's V8/SpiderMonkey engine (JIT compiled)
  • Uses browser's native requestAnimationFrame
  • Async file loading via fetch
Build normally and deploy to a web server.

How JSRunner Loads Code

In Editor mode, JSRunner loads from the filesystem (enabling hot reload).

In builds, JSRunner automatically uses the app.js.txt TextAsset that was generated during npm run build. The build processor assigns this asset before the build completes.

The bundle location follows the Scene Folder convention:

Assets/Scenes/YourScene/
└── MainUI_abc123/
    └── app.js.txt      # TextAsset used in builds

Production Build Checklist

1. Minify Your Code

// esbuild.config.js
await esbuild.build({
    minify: true,
    treeShaking: true,
    drop: ["console", "debugger"],
})

2. Remove Dev Dependencies

Only include what you need in the bundle.

3. Test the Build

Run your built JavaScript through the JSRunner before making a Unity build.

4. Check Console

Watch for errors during initialization.

Troubleshooting

"Script error" or "Bundle not found" in Build

  • Ensure npm run build completed successfully
  • Verify app.js.txt exists in the instance folder
  • Check Unity Console for build processor messages

"Script error" in WebGL

  • Open browser DevTools for full error message
  • Check for CORS issues if loading external resources
  • Verify all imports are bundled

Performance Issues

  • Profile in browser DevTools (WebGL)
  • Reduce DOM updates (batch state changes)
  • Use React.memo for expensive components

Platform-Specific Code

const isWebGL = typeof window !== "undefined"

function App() {
    useEffect(() => {
        if (isWebGL) {
            console.log("Running in browser")
        } else {
            console.log("Running in Unity")
        }
    }, [])
}

Loading External Assets

In builds, load assets from StreamingAssets:

const basePath = CS.UnityEngine.Application.streamingAssetsPath

async function loadConfig() {
    const response = await fetch(`${basePath}/config.json`)
    return response.json()
}

Hot Reload in Builds

Hot reload only works in the Editor. For production:

  • Changes require rebuilding JavaScript
  • Restart the app to see changes

Size Optimization

Analyze your bundle:

npx esbuild-visualizer --open

Common optimizations:

  • Import only what you need from libraries
  • Remove unused exports with tree shaking
  • Split code if using multiple entry points