Skip to content

An importShim.getWorkerScriptURL function should be added to simplify usage #535

@lzxb

Description

@lzxb

Motivation & Pain Point

Currently, using Web Workers with es-module-shims to leverage Import Maps is technically possible but introduces significant boilerplate and complexity. Developers are required to manually:

  1. Construct a Blob to bootstrap the worker environment.
  2. Use importScripts to load es-module-shims itself within the worker.
  3. Extract, serialize, and inject the current Import Map from the main thread into the worker.
  4. Finally, call importShim to load the target module.

This process is repetitive, error-prone (e.g., handling paths or keeping shim versions in sync), and creates friction for adopting ESM workers.

Proposal: Add importShim.getWorkerScriptURL

I propose adding a helper function importShim.getWorkerScriptURL(moduleUrl) that automates this bootstrapping process.

Proposed Usage

// The library handles the Blob creation, shim injection, and map propagation automatically.
const workerUrl = importShim.getWorkerScriptURL('./my-worker.js');
const worker = new Worker(workerUrl);

Feasibility Analysis

The proposed API is highly feasible because es-module-shims already holds the necessary context:

  • Import Map Awareness: It knows the currently active import map configuration.
  • Self-Reference: It can determine its own script URL to ensure the worker loads the matching shim version.
  • Resolution Logic: It already handles the core logic for module resolution.

Encapsulating this "bootstrap logic" into a core API would standardize the pattern and prevent community fragmentation with ad-hoc implementations.

Comparison

Current "Manual" Implementation (Complex & Verbose):
To properly use a worker with import maps today, developers must write something like this:

// 1. Get the current import map
const importMap = JSON.stringify(importShim.getImportMap()); // Assuming we can get this, or query DOM
// 2. Locate the shim script itself
const shimSrc = document.querySelector('script[src*="es-module-shims"]').src;

// 3. Create the bootstrap blob
const blob = new Blob([`
  importScripts('${shimSrc}');
  importShim.addImportMap(${importMap});
  importShim('${moduleUrl}');
`], { type: 'application/javascript' });

const worker = new Worker(URL.createObjectURL(blob));

Proposed API (Clean & Declarative):
With the new API, the complexity is hidden, improving the Developer Experience (DX) significantly.

Implementation Idea

The internal implementation could roughly look like this:

importShim.getWorkerScriptURL = function(moduleUrl) {
  // Resolve absolute path for the module
  const resolvedUrl = new URL(moduleUrl, location.href).href;
  // Get current shim URL (simplified)
  const shimUrl = document.querySelector('script[src*="es-module-shims"]').src;
  // Get current import map
  const importMap = JSON.stringify(this.getImportMap() || {});
  
  const blobContent = `
    importScripts('${shimUrl}');
    importShim.addImportMap(${importMap});
    importShim('${resolvedUrl}');
  `;
  
  return URL.createObjectURL(new Blob([blobContent], { type: 'application/javascript' }));
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions