Bar Files

On this page

Bar Files

Lens adds one block of about a kilobyte before the closing </body>, plus the data of the request. The styles, the script, Alpine.js, the markup and the icons are separate files that the browser fetches once and keeps.

<!-- BxLens -->
<link rel="stylesheet" id="bxlens-css" href="/~bxlens/index.bxm/assets/lens.css?v=3f9a1c07d2be">
<div id="bxlens" x-cloak data-base="/~bxlens/index.bxm/assets/" data-html="..." data-icons="..." data-alpine="..."></div>
<script type="application/json" id="bxlens-data">{ ... the data of this request ... }</script>
<script defer id="bxlens-js" src="/~bxlens/index.bxm/assets/lens.js?v=a41b9c2e7710"></script>
<!-- /BxLens -->
FileWhat it is
lens.cssThe styles, all scoped under #bxlens.
lens.jsThe bar component. It loads the next three files.
lens.htmlThe markup of the bar.
bar-icons.svgThe icon sprite (Phosphor, MIT).
alpine.min.jsAlpine.js. Loaded only when the page has no Alpine of its own.

Caching

The ?v= value is the first 12 characters of the SHA-256 of the file, computed when Lens starts. A request that carries the current hash gets:

Cache-Control: public, max-age=31536000, immutable
ETag: "<hash>"

A new Lens build has new hashes, so the browser fetches the new files by itself. A request without the hash, or with an old one, gets Cache-Control: no-cache and the ETag, so it revalidates (a 304 when nothing changed). With dev.reloadAssets the files are read and hashed again on every page and are never cached, so you can edit them and refresh.

The files hold no data of any request and no secret. They are the same for everyone, so a CDN or a proxy may cache them.

Who can fetch them

The bar files are served to anyone who can reach the URL, whatever console.access says, because the page of a caller who may see the bar has to load them. The check that decides who gets the bar (bar.access, access.allowedHosts, access.requireHeader) applies to the page, which is where the data of the request is. Console pages and the console's own files (console.js, console.css, the login page) keep the console.access rules and answer 404 to a caller who is not allowed.

The route needs the console path to reach BoxLang. On MiniServer that is the pass predicate in The console URL. The URL is under /~bxlens/, which Lens never tracks.

Alpine

lens.js checks for window.Alpine. If the page has one (started, or still loading: Lens waits for the page to finish loading before it decides), Lens registers its component with it and uses it. Otherwise it loads alpine.min.js from the same place. The page never gets two copies. Lens cannot know from the server whether the page has its own Alpine, which is why the decision is made in the browser.

Content-Security-Policy

If your pages send a Content-Security-Policy, the bar needs:

DirectiveValueWhy
script-src'self' and 'unsafe-eval'lens.js and alpine.min.js come from your own server. Alpine evaluates the expressions in the markup. The data block is type="application/json", which is data and needs no unsafe-inline.
style-src'self'lens.css comes from your own server.
connect-src'self'lens.js fetches the markup and the icons from your own server.

Lens sets a CSP only on its own console pages, where it is strict (default-src 'none' and the same-origin sources it needs). Nothing is loaded from another origin, ever.