Skip to content

Latest commit

 

History

History
executable file
·
322 lines (268 loc) · 11.3 KB

File metadata and controls

executable file
·
322 lines (268 loc) · 11.3 KB

Worker

🍩

+

🏞️


Worker 🍩

The Service Worker for Land 🏞️

Web applications that lose authentication state on network drops force users to re-authenticate. Tokens stored in plaintext are accessible to any script running on the page.

"Offline-capable. Auth tokens encrypted. Auto-refreshed."

License: CC0-1.0 NPM Version

Welcome to Worker, the Service Worker for the Land Code Editor that enhances web application performance and reliability through advanced caching, offline support, and a unique strategy for handling dynamic CSS imports from JavaScript modules.

Worker is engineered to:

  1. Implement Asset Caching: Provide multiple caching strategies including network-first for navigation and cache-first for static assets.
  2. Enable Offline Support: Allow the application shell and cached assets to function without network connectivity.
  3. Handle Dynamic CSS Loading: Intercept JavaScript CSS imports and respond with JavaScript modules that trigger standard <link> tag loading.
  4. Support Automatic Updates: Detect new Service Worker versions and prompt clients to reload for seamless updates.

Key Features 🔐

  • Asset Caching: Implements multiple caching strategies:
    • Core Cache (CACHE_CORE): Stores essential application shell files and critical scripts (like /Application/, Register.js, Load.js). Uses a network-first strategy for navigation requests to ensure users get the latest page structure if online, falling back to the cache when offline. Pre-caches essential assets on install.
    • Asset Cache (CACHE_ASSET): Stores static application assets (/Static/Application/*), including JavaScript, images, and the actual CSS files. Uses a cache-first strategy for fast loading. Also stores the dynamically generated JavaScript modules used for CSS loading.
  • Offline Support: Leverages the caches to allow the application shell and cached assets to function offline.
  • Dynamic CSS Loading: Intercepts JavaScript import statements for specific CSS files and responds with a JavaScript module that triggers the loading of the actual CSS via a standard <link> tag.
  • Automatic Updates: Detects when a new version of the Service Worker is activated and prompts the client (via Register.js) to reload the page, ensuring the user gets the latest application version seamlessly.
  • Client Control Management: The Register.js script ensures the Service Worker gains control of the page, potentially reloading the page once after the initial registration if necessary.

System Architecture Diagram 🏗️

This diagram illustrates Worker's service worker caching and CSS loading strategy.

graph LR
classDef worker fill:#f9f,stroke:#333,stroke-width:2px;
classDef client fill:#9cf,stroke:#333,stroke-width:2px;
classDef cache fill:#cfc,stroke:#333,stroke-width:1px;

subgraph "Client (Browser)"
Client["Client Application"]:::client
end

subgraph "Service Worker"
SW["Service Worker"]:::worker
CoreCache["CACHE_CORE"]:::cache
AssetCache["CACHE_ASSET"]:::cache
end

Client -- Fetch /Application/ --> SW
SW -- Network-first --> CoreCache
CoreCache -- Return cached or network --> SW

Client -- Import *.css --> SW
SW -- JS module response --> Client
Client -- Create link tag --> Client
Client -- Fetch CSS --> SW
SW -- Cache-first --> AssetCache
AssetCache -- Return CSS --> SW
SW -- CSS applied --> Client
Loading

Usage: Dynamic CSS Loading via JS Module Response 🚀

This worker implements a specific strategy to handle dynamic CSS imports from JavaScript modules (e.g., import './some-styles.css';) located under the /Static/Application/ path.

The Workflow:

  1. Initial JS Import: A JavaScript module attempts to import a CSS file under /Static/Application/ (e.g., /Static/Application/CodeEditorLand/component.css).
  2. Service Worker Intercept #1: The worker's fetch listener intercepts this request. Because the URL matches /Static/Application/*.css and doesn't contain the special ?Skip=Intercept parameter, it proceeds with the CSS handling logic.
  3. Service Worker Responds with JS: The worker immediately responds to the fetch request with a dynamically generated JavaScript module:
    window._LOAD_CSS_WORKER("/Static/Application/CodeEditorLand/component.css");
    export default {};
    This JavaScript response is cached in CACHE_ASSET using the original CSS request URL as the key.
  4. Browser Executes JS: The browser receives and executes this JavaScript module. The export default {}; satisfies the expectation of the original import statement.
  5. Client Function Call: The executed JavaScript calls the globally available window._LOAD_CSS_WORKER function (defined in Load.js).
  6. Client Modifies URL & Creates <link>: The _LOAD_CSS_WORKER function appends the ?Skip=Intercept query parameter to the received CSS URL. It then creates a standard <link rel="stylesheet"> tag and appends it to <head>.
  7. Browser Fetches CSS: The browser sees the new <link> tag and initiates a second fetch request for the CSS file, this time with the ?Skip=Intercept parameter.
  8. Service Worker Intercept #2: The worker intercepts this second request.
  9. Service Worker Serves CSS: The worker detects the ?Skip=Intercept parameter, bypasses the JS generation logic, and fetches the actual CSS content using a cache-first strategy against CACHE_ASSET. It responds with the real CSS content (Content-Type: text/css).
  10. Browser Applies Styles: The browser receives the actual CSS and applies the styles.

This two-step fetch process, distinguished by the Skip=Intercept parameter, allows the initial JavaScript import to resolve quickly while triggering the standard browser mechanism for loading the actual CSS without causing infinite interception loops.


Deep Dive & Component Breakdown 🔬

To understand how Worker's service worker implements the dynamic CSS loading strategy, see the following source files:

  • Worker.ts - Main service worker with caching strategies
  • Register.ts - Service worker registration and update handling
  • Load.ts - Client-side CSS loader function (window._LOAD_CSS_WORKER)

HTML Integration Example

<!DOCTYPE html>
<html lang="en">
	<head>
		<!--
      IMPORTANT: Load the CSS Loader script EARLY.
      Defines window._LOAD_CSS_WORKER before main app script runs.
    -->
		<script src="/Worker/CSS/Load.js" type="module"></script>

		<!--
      Set the path to the Service Worker file.
      Must come before Register.js.
    -->
		<script>
			window._WORKER = "/Worker.js";
		</script>

		<!--
      Register the Service Worker.
      Handles registration, listens for updates, manages page control.
      Registers with scope '/Application'.
    -->
		<script src="/Worker/Register.js" type="module"></script>
	</head>

	<body>
		<!--
      Load main application script LAST.
      Any dynamic import '/Static/Application/some-component.css'
      will trigger Service Worker interception.
    -->
		<script src="/scripts/main-app.js" type="module"></script>
	</body>
</html>

See Also


License ⚖️

This project is released into the public domain under the Creative Commons CC0 Universal license. You are free to use, modify, distribute, and build upon this work for any purpose, without any restrictions. For the full legal text, see the LICENSE file.


Changelog 📜

Stay updated with our progress! See CHANGELOG.md for a history of changes specific to Worker.


Funding & Acknowledgements 🙏🏻

Worker is a core element of the Land ecosystem. This project is funded through NGI0 Commons Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet program. Learn more at the NLnet project page.

The project is operated by PlayForm, based in Sofia, Bulgaria.

PlayForm acts as the open-source steward for Code Editor Land under the NGI0 Commons Fund grant.

Land PlayForm NLnet NGI0 Commons Fund
Land PlayForm NLnet NGI0 Commons Fund

Project Maintainers: Source Open (Source/Open@Editor.Land) | GitHub Repository | Report an Issue | Security Policy