Hosted mode
A JOPS app starts in one of two modes, chosen by the attributes of the jops-core <script> tag.
| Standalone mode | Hosted mode | |
|---|---|---|
| Script tag | data-app (default ./src/App.js) |
data-host, no data-app |
| Who starts the app | JOPS, as soon as the library loads | the host page, by calling mount() |
| Renders into | <body>, or the data-root element |
the element passed to mount() |
| Ending the app | a page load | unmount(), or leaving the app’s page |
| Used by | regular SPAs, hybrid mobile, Electron | Next.js (JopsApp), WordPress ([jops]), any other page |
Standalone mode
Section titled “Standalone mode”The app owns the page. JOPS imports the module named in data-app and creates its default export:
<script type="importmap"> { "imports": { "jops-core": "https://cdn.jsdelivr.net/npm/jops-core@latest/lib/jops-core.min.js" } }</script><script type="module" src="https://cdn.jsdelivr.net/npm/jops-core@latest/lib/jops-core.min.js" data-app="./src/App.js"></script>By default the app renders into <body>. To keep the rest of the page and render into one element, add data-root with the element’s id:
<div id="app"></div><script type="module" src="https://cdn.jsdelivr.net/npm/jops-core@latest/lib/jops-core.min.js" data-app="./src/App.js" data-root="app"></script>Hosted mode
Section titled “Hosted mode”In hosted mode, the page is in charge. Load the library with data-host and no data-app: nothing starts automatically, and window.JOPS exposes mount() and unmount(). Then start the app yourself:
<script type="importmap"> { "imports": { "jops-core": "/lib/jops-core.min.js" } }</script><script type="module" src="/lib/jops-core.min.js" data-host></script>
<div id="app" style="position: relative"></div><script type="module"> const start = () => window.JOPS.mount({ app: "/my-app/App.js", root: document.getElementById("app") }); window.JOPS ? start() : window.addEventListener("jops:ready", start, { once: true });</script>jops:readyfires once jops-core has fully loaded, so a listener may callmount()directly. Ifwindow.JOPSalready exists, the library is ready.- One instance. The import map and the script
srcmust be the same URL, so the page loads a single jops-core instance. - One app per page. There is one host root and one Router.
position: relativeon the container keeps Router animations inside it.
mount() and unmount()
Section titled “mount() and unmount()”mount({ app, root }) imports app, creates its default export, and makes the root view render into root (an HTMLElement) instead of <body>. It returns a promise of the App instance.
unmount() ends the app completely: it destroys the Router and every view, empties root, clears the Store and the EventBus, and restores the browser history methods that JOPS wrapped. It is safe to call more than once, and mount() can start an app again afterwards.
Modules on the same page can also import them directly; window.JOPS.mount and window.JOPS.unmount are the same functions:
import { mount, unmount } from "jops-core";
await mount({ app: "/my-app/App.js", root: document.getElementById("app") });unmount();When the app ends
Section titled “When the app ends”- A full page load ends the app anyway.
- A host that removes the app’s element without a page load, or navigates with
history.pushState(), callsunmount(). - When browser history moves to another path, the Router ends the app by itself. Coming back starts it again at the route in the hash.
Anything that must outlive the app belongs on the server.
What changes in hosted mode
Section titled “What changes in hosted mode”setStyle()has no effect: the host page provides the CSS. Load your styles with the host’s own mechanism, and scope them under the app’s root class so they don’t restyle the host page.- The Android back button integration is off.
Paths you give to JOPS (app in mount(), data-app, src=, layout=, loadLayout(), setStyle()) are resolved against the HTML page, not the file they are written in, and the right form depends on where the library comes from.
Library on the same origin (/lib/jops-core.min.js in both the import map and src): write root-absolute paths. They work on every page of the site.
<Users jops src="/my-app/Users.js" layout="/my-app/layout/users.html"></Users>This is the convention for Next.js (files in public/) and WordPress (the app folder in the WordPress root).
With the library from jsDelivr, JOPS resolves paths relative to the hosting page: ./my-app/App.js on example.com/admin/users means example.com/admin/my-app/App.js, and root-absolute /my-app/... paths are turned page-relative too. This breaks when the same app is embedded on pages at different depths.