Building & Deployment
Get your OneJS app running in standalone builds and WebGL.
Build Process
When you build your Unity project:
- JSRunnerBuildProcessor runs automatically during the build
- Locates each JSRunner's
app.js.txtbundle (TextAsset) - Assigns it to the JSRunner for runtime loading
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
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 buildsProduction 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 buildcompleted successfully - Verify
app.js.txtexists 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 --openCommon optimizations:
- Import only what you need from libraries
- Remove unused exports with tree shaking
- Split code if using multiple entry points