Building and Deploying#
Warning
Project Neo is currently in Technical Preview. Features described in this section may change before general availability.
Bundles are deployed independently from the core Project Neo application. Two deployment models are available:
Deployment Models#
Model |
How it works |
Use case |
|---|---|---|
Platform deployment |
Bundle uploaded to the Squirro backend. The host loads it per-project from |
Production deployment to a Squirro SaaS or managed instance. |
Local bind-mount |
Bundle folder mounted into the Project Neo Docker container at |
Local development and testing. |
Use platform deployment for production. The bind-mount model is useful for local testing without uploading to the platform.
Step 1: Build the Bundle#
From your bundle directory:
neo-ui build
Output in dist/:
dist/
├── mf-manifest.json # Module Federation manifest
├── bundle-info.json # Deploy metadata (name, version, dashboards), stamped by neo-ui build
├── [hash].js # Bundle chunk(s), one per dashboard
└── [hash].css # Styles
Bundle Size#
What the host provides#
The host supplies several libraries to bundles at runtime via Module Federation. You do not pay for their size in your bundle:
react,react-dom.react-router-dom.zustand.@tanstack/react-query.i18next,react-i18next.
Any other dependency you add to package.json is bundled into the output.
Per-dashboard code splitting#
Code splitting happens automatically. The () => import('./dashboards/MyDashboard') entry for each dashboard in the manifest produces a separate output chunk. The host fetches that chunk only when the user navigates to the dashboard, not at application load.
For heavy dependencies used in only one dashboard (such as a charting library or a PDF renderer), the same technique applies inside the component itself:
import { lazy, Suspense } from 'react';
const HeavyChart = lazy(() => import('./HeavyChart'));
export default function Analytics({ projectId }: { projectId: string }) {
return (
<Suspense fallback={<p>Loading chart…</p>}>
<HeavyChart projectId={projectId} />
</Suspense>
);
}
That splits HeavyChart and its dependencies into a separate chunk that loads on demand.
Analyzing the bundle#
To inspect chunk sizes and the dependency breakdown, run the build with rsbuild’s built-in analyzer flag from inside the project directory:
BUNDLE_ANALYZE=true npx rsbuild build
The command writes a dist/report.html file and opens it in the browser. Use it to identify which dependency is responsible for an oversized chunk.
Size recommendations#
No hard limit is enforced by the build tooling, but keep each dashboard chunk under 200 KB parsed (not gzipped) as a practical target. Chunks larger than that add noticeable load time on slower connections when a user first navigates to the dashboard.
If a chunk exceeds that target, use dynamic imports to split the heaviest dependency, or check whether the dependency has a lighter alternative.
Step 2: Deploy#
Platform Deployment (Recommended)#
Use neo-ui deploy for a guided, one-command deploy:
neo-ui deploy
The command runs preflight checks (credentials, version compatibility, and bundle size), shows an interactive project picker, uploads the bundle, and sets frontend.ui-bundle on the selected project, all in one step.
Flags
Flag |
Description |
|---|---|
|
Skip the build step and deploy the existing |
|
Run preflight and list available projects without uploading. |
|
Skip the interactive picker and use a known project ID. Useful for CI. |
|
Override an incompatible compatibility verdict. |
|
Emit a machine-readable receipt on stdout. |
For a first deploy, run neo-ui deploy --dry-run to see the available projects and the compatibility verdict before committing, then run neo-ui deploy and select a project from the interactive picker. For subsequent deploys to a known project, skip the picker with neo-ui deploy --project <project-id>.
For a CI pipeline, deploy to a known project and capture the machine-readable receipt:
neo-ui deploy --project $PROJECT_ID --json | jq .
Note
If neo-ui deploy is unavailable, use the squirro_asset tool as a fallback. That tool is part of the Squirro Toolbox. For installation instructions, see the squirro_asset CLI Reference page.
Run the following command, where <folder> is a directory named after the bundle that contains a dist/ subdirectory:
squirro_asset ui_bundle upload \
--cluster https://your-instance.example.com/ \
--token <your-refresh-token> \
--folder <folder>/
The --token value is passed as a command-line argument, which means it appears in your shell history and in process listings. After running the command, clear the relevant history entry or use your shell’s history-ignore facility for sensitive commands.
Then set the frontend.ui-bundle project configuration to the bundle name. That setting is available under Setup Space → Settings → Project Configuration:
frontend.ui-bundle = <bundle-name>
How Loading Works#
When a user navigates to a project, the host:
Fetches the project configuration and reads the
frontend.ui-bundlevalue.Loads
mf-manifest.jsonfrom/v0/workspaces/<domain>/ui_bundles/<bundle-name>/dist/mf-manifest.json.Registers the Module Federation remote and loads the bundle manifest.
Adds the bundle dashboards to the sidebar navigation and creates dynamic routes.
The bundle is loaded once per session and cached across project revisits within the same browser session.
Local Bind-Mount#
To test a production build locally without uploading to the platform, mount the dist/ folder into the Project Neo Docker container:
# docker-compose.local.yml
volumes:
- /path/to/your/bundle/dist:/app/extensions:ro
The host detects the /extensions/mf-manifest.json path and loads the bundle globally for all projects. No frontend.ui-bundle project configuration is needed in this mode.
Note
The bind-mount model is for local development and testing only. Use platform deployment for production.
Step 3: Verify#
After deploying, open the Project Neo application in the browser and hard-refresh (Cmd+Shift+R on macOS, Ctrl+Shift+R on Windows and Linux). Your bundle dashboards should appear in the sidebar.
To verify the manifest is reachable after a platform deployment:
https://your-instance.example.com/v0/workspaces/<domain>/ui_bundles/<bundle-name>/dist/mf-manifest.json
To verify the manifest is reachable after a local bind-mount:
http://localhost:5555/extensions/mf-manifest.json
Both URLs should return JSON. If either returns HTML or a 404, the bundle did not reach the correct path.
Updating a Bundle#
Make changes in
src/.Run
neo-ui build.Run
neo-ui deployagain to upload the new build, overwriting the previous one.Users see the update on their next page load. No server restart is needed.
Chunk filenames include content hashes, so new and old chunks never conflict. Only mf-manifest.json is overwritten in place.
Version Compatibility#
Each bundle build records the platformVersion it was compiled against, which is the @squirro/nextgen-core version in your project. neo-ui deploy checks this against the running host version and gates the deploy on the result:
Verdict |
Meaning |
Deploy behavior |
|---|---|---|
|
Exact version match. |
Proceeds. |
|
Same |
Warns and proceeds. |
|
Different |
Blocked. Fix before deploying. |
|
Instance predates version reporting. |
Warns and proceeds. |
If the deploy is blocked as incompatible, upgrade the bundle to match the host, then deploy again:
neo-ui upgrade
neo-ui deploy
To override the gate and deploy anyway, use --force:
neo-ui deploy --force
To check the verdict in advance without uploading, run neo-ui deploy --dry-run.
Multiple Bundles#
The host supports one bundle per project. If your use case requires multiple bundles for a single project, visit the Squirro Support website and submit a technical support request.