Repository navigation
feat: self-contained WASM export bundles for offline use - #10879
Conversation
|
Deployment failed for project marimo-docs with the following error: View Documentation: https://vercel.com/docs/accounts/team-members-and-roles |
|
All contributors have signed the CLA ✍️ ✅ |
Bundle ReportChanges will increase total bundle size by 1.19kB (0.0%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: marimo-esmAssets Changed:
Files in
|
There was a problem hiding this comment.
1 issue found across 20 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="marimo/_export/offline.py">
<violation number="1" location="marimo/_export/offline.py:162">
P2: When offline export runs as root or in a container, Chromium fails because `--no-sandbox` never reaches Playwright. Forward the CLI sandbox choice into `_resolve_packages` and launch Chromium with the corresponding no-sandbox option.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| from playwright.async_api import async_playwright # type: ignore[import-not-found] | ||
|
|
||
| async with async_playwright() as playwright: | ||
| browser = await playwright.chromium.launch() |
There was a problem hiding this comment.
P2: When offline export runs as root or in a container, Chromium fails because --no-sandbox never reaches Playwright. Forward the CLI sandbox choice into _resolve_packages and launch Chromium with the corresponding no-sandbox option.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At marimo/_export/offline.py, line 162:
<comment>When offline export runs as root or in a container, Chromium fails because `--no-sandbox` never reaches Playwright. Forward the CLI sandbox choice into `_resolve_packages` and launch Chromium with the corresponding no-sandbox option.</comment>
<file context>
@@ -0,0 +1,309 @@
+ from playwright.async_api import async_playwright # type: ignore[import-not-found]
+
+ async with async_playwright() as playwright:
+ browser = await playwright.chromium.launch()
+ try:
+ page = await browser.new_page()
</file context>
There was a problem hiding this comment.
This finding looks invalid. playwright already launches chromium with --no-sandbox by default. marimo's --sandbox flag controls Python environment isolation and does not affect browser sandboxing.
mscolnick
left a comment
There was a problem hiding this comment.
this is a really great approach! great stuff
| export interface WasmRuntimeConfig { | ||
| pyodideIndexUrl?: string; | ||
| pyodideLockfileUrl?: string; | ||
| pypiIndexUrl?: string; |
There was a problem hiding this comment.
I wonder if this is how we should be sending marimo version too (not required in this PR). This is much cleaner than shoving in the worker name.
There was a problem hiding this comment.
Sure, we can do that in a follow up
Pass independent Pyodide, lockfile, and package-index URLs through the export template and both workers while preserving hosted defaults.
Resolve browser-compatible packages in Pyodide through Playwright, stage downloads, and preserve prior exports with content-addressed wheels and lockfiles.
Wire runtime bundling through both export paths, preserve local wheel handling, and document the setup and local HTTP hosting requirements.
Probe the actual headless browser before downloading assets and report its setup command when startup fails.
c18e330 to
fa64758
Compare
Follow up on #10879. With this, we now pass the marimo version through `WasmRuntimeConfig` instead of encoding it in the worker name. Both WASM workers use the bootstrap config as the version source and their names remain stable while preserving the custom-controller capability suffix.
Follow-up to #10879. `--offline` can now build the bundle from internal mirrors, for networks that can't reach jsDelivr or PyPI: ```bash marimo export html-wasm notebook.py -o dist --offline \ --pyodide-index-url https://mirror.example.com/pyodide/full/ \ --pypi-index-url https://mirror.example.com/pypi/simple/ ``` A mirrored Pyodide distribution brings its own `pyodide-lock.json`, and marimo's own packages then come from the package index. Everything still resolves from the lockfile first, so Pyodide-built pins like `pydantic-core` hold with any index. The resolver fetches through Python, so mirrors need no CORS headers, and the export stops early when a mirror serves a different Pyodide version. The bundle is now the dependency closure of what the notebook needs, so a download that fails mid-export stops it instead of shipping a bundle that won't boot. Closes #10985.
Adds
--offlineto bundle Pyodide and notebook dependencies alongside HTML-WASM exports:uv run --with playwright python -m playwright install chromium uv run --with playwright marimo export html-wasm notebook.py \ --offline --no-sandbox -o distExporting requires internet access and Playwright/Chromium. Pyodide resolves browser-compatible dependencies without executing notebook cells. The generated folder uses relative URLs and can be moved or served offline.
Runtime URL configuration remains separate from bundling, so granular source overrides can be exposed later. Existing exports retain their hosted defaults.
The export still requires a reachable HTTP server. It does not add browser offline caching, and notebook data/API calls & widget JavaScript assets need separate handling.
Closes #9811.