[loader] Pilot first-party dual ESM/CJS plugin builds #220

Closed
opened 2026-06-02 09:43:37 +00:00 by steve · 0 comments
Owner

Problem

The official plugin build and release path currently assumes CommonJS-style plugin artifacts. The ESM-first loader needs at least one first-party plugin to publish main.mjs with a CommonJS fallback where useful.

Goal

Pilot first-party dual ESM/CommonJS plugin builds and manifest metadata before migrating larger official plugins.

Scope

  • Update first-party plugin build templates to emit main.mjs and main.js where appropriate.
  • Require single-file ESM bundles for the early rollout.
  • Add lapis.runtime.entries.workspace metadata with format, fallbackPath, sharedDependencies, and reload requirements.
  • Add bundle external validation for generated public host modules.
  • Start with a small pilot plugin before migrating larger plugins such as Docs.

Non-goals

  • Do not migrate every first-party plugin in this issue.
  • Do not allow chunked ESM output until plugin asset serving supports it reliably.
  • Do not broaden the host-module public API surface for a single plugin convenience.

Acceptance Criteria

  • A pilot official plugin loads as ESM.
  • The same plugin can load via CommonJS fallback when ESM is disabled in tests.
  • Release metadata declares both formats and shared dependencies.

Implementation Notes

  • Prefer a small plugin for the pilot.
  • Keep bundled dependencies bundled unless they are explicitly public host modules.
  • Use generated shared externals instead of a hand-maintained external list.

Active Implementation Plan

  • Use @lapis-notes/telemetry / lapis-telemetry as the pilot because it is already an official registry-installable first-party plugin and is smaller than Docs.
  • Change the Telemetry Vite build to emit dist/main.mjs for the ESM artifact while keeping dist/main.js as the CommonJS fallback and preserving existing package exports.
  • Replace peer-dependency blanket externalization in the pilot build with the generated public renderer shared external list so private Svelte internals and UI subpaths are bundled unless explicitly public.
  • Add build-time validation that pilot plugin JS chunks only retain bare external imports from the generated shared externals and that the ESM output stays a single main.mjs file.
  • Add structured lapis.runtime.entries.workspace metadata to the Telemetry manifest with format, fallbackPath, sharedDependencies, and requiresReloadOnUpdate.
  • Update release tooling/tests and registry specs so official release artifacts can carry main.mjs beside required main.js.

Affected Packages and Files

  • packages/plugins/plugin-telemetry/vite.config.ts
  • packages/plugins/plugin-telemetry/package.json
  • packages/plugins/plugin-telemetry/manifest.json
  • packages/plugins/plugin-telemetry/src/telemetry-plugin.ts
  • packages/plugins/plugin-telemetry/spec.md
  • packages/api/src/lib/__tests__/plugin-runtime-entry.test.ts
  • spec/src/20-packages/plugins/telemetry/index.md
  • scripts/plugin-release.test.mjs
  • scripts/publish-official-plugin-assets.test.mjs
  • spec/src/30-cross-package-contracts/plugin-registry.md
  • spec/src/30-cross-package-contracts/plugin-runtime.md

Suggested Files or Specs To Inspect

  • spec/src/20-packages/plugins/index.md
  • spec/src/50-roadmap/full-registry-v1.md
  • packages/plugins/plugin-*/
  • scripts/

Validation Commands

  • pnpm plugin-host:check
  • pnpm --filter <pilot-package> check:all
  • pnpm check:all

Follow-up Tasks

Implementation Summary

Implemented the Telemetry dual ESM/CommonJS official plugin pilot, including main.mjs output, CommonJS fallback metadata, generated shared-external validation, release artifact coverage, and registry/runtime spec updates.

## Problem The official plugin build and release path currently assumes CommonJS-style plugin artifacts. The ESM-first loader needs at least one first-party plugin to publish `main.mjs` with a CommonJS fallback where useful. ## Goal Pilot first-party dual ESM/CommonJS plugin builds and manifest metadata before migrating larger official plugins. ## Scope - Update first-party plugin build templates to emit `main.mjs` and `main.js` where appropriate. - Require single-file ESM bundles for the early rollout. - Add `lapis.runtime.entries.workspace` metadata with format, fallbackPath, sharedDependencies, and reload requirements. - Add bundle external validation for generated public host modules. - Start with a small pilot plugin before migrating larger plugins such as Docs. ## Non-goals - Do not migrate every first-party plugin in this issue. - Do not allow chunked ESM output until plugin asset serving supports it reliably. - Do not broaden the host-module public API surface for a single plugin convenience. ## Acceptance Criteria - A pilot official plugin loads as ESM. - The same plugin can load via CommonJS fallback when ESM is disabled in tests. - Release metadata declares both formats and shared dependencies. ## Implementation Notes - Prefer a small plugin for the pilot. - Keep bundled dependencies bundled unless they are explicitly public host modules. - Use generated shared externals instead of a hand-maintained external list. ## Active Implementation Plan - Use `@lapis-notes/telemetry` / `lapis-telemetry` as the pilot because it is already an official registry-installable first-party plugin and is smaller than Docs. - Change the Telemetry Vite build to emit `dist/main.mjs` for the ESM artifact while keeping `dist/main.js` as the CommonJS fallback and preserving existing package exports. - Replace peer-dependency blanket externalization in the pilot build with the generated public renderer shared external list so private Svelte internals and UI subpaths are bundled unless explicitly public. - Add build-time validation that pilot plugin JS chunks only retain bare external imports from the generated shared externals and that the ESM output stays a single `main.mjs` file. - Add structured `lapis.runtime.entries.workspace` metadata to the Telemetry manifest with `format`, `fallbackPath`, `sharedDependencies`, and `requiresReloadOnUpdate`. - Update release tooling/tests and registry specs so official release artifacts can carry `main.mjs` beside required `main.js`. ## Affected Packages and Files - `packages/plugins/plugin-telemetry/vite.config.ts` - `packages/plugins/plugin-telemetry/package.json` - `packages/plugins/plugin-telemetry/manifest.json` - `packages/plugins/plugin-telemetry/src/telemetry-plugin.ts` - `packages/plugins/plugin-telemetry/spec.md` - `packages/api/src/lib/__tests__/plugin-runtime-entry.test.ts` - `spec/src/20-packages/plugins/telemetry/index.md` - `scripts/plugin-release.test.mjs` - `scripts/publish-official-plugin-assets.test.mjs` - `spec/src/30-cross-package-contracts/plugin-registry.md` - `spec/src/30-cross-package-contracts/plugin-runtime.md` ## Suggested Files or Specs To Inspect - `spec/src/20-packages/plugins/index.md` - `spec/src/50-roadmap/full-registry-v1.md` - `packages/plugins/plugin-*/` - `scripts/` ## Validation Commands - `pnpm plugin-host:check` - `pnpm --filter <pilot-package> check:all` - `pnpm check:all` ## Related Issues ## Follow-up Tasks ## Implementation Summary Implemented the Telemetry dual ESM/CommonJS official plugin pilot, including main.mjs output, CommonJS fallback metadata, generated shared-external validation, release artifact coverage, and registry/runtime spec updates. <!-- backlog:task_id=TASK-PLUGIN-LOADER-008 source_spec=spec/src/30-cross-package-contracts/plugin-runtime.md -->
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lapis-notes/lapis#220
No description provided.