Skip to content

0.18.0

Choose a tag to compare

@SisyphusZheng SisyphusZheng released this 17 May 02:47
· 933 commits to main since this release

Changelog: v0.18.0

Release date: 2026-05-17
Release type: minor (new capability, backward compatible)

Overview

v0.18.0 implements the Universal WC Engine Admission Layer, enabling LessJS to safely accept third-party Web Component packages through a validated compatibility model. Previously, LessJS could not distinguish between SSR-capable and client-only third-party packages, leading to potential runtime failures.

Complete SOP Steps

Step 1: CEM Parser ✅

Added packages/core/src/cem-parser.ts — parses standard custom-elements.json without executing package code:

  • Extracts tag names, module paths, exports, attributes, events, slots, CSS parts, and CSS custom properties
  • Preserves unknown CEM fields for future compatibility
  • Rejects invalid tag names and unresolved module paths
  • Detects duplicate tags before SSR registration
  • 19 tests passing

Step 2: Compatibility Classifier ✅

Added packages/core/src/compatibility.ts — 4-tier classification engine:

Tier Meaning Build behavior
ssr-capable Explicit Less manifest or adapter says SSR supported Import/register in SSR bundle
client-only Browser-only package or no SSR declaration Exclude from SSR bundle
rejected Invalid manifest, duplicate tag, unsafe path Fail before code generation
experimental-dom Opt-in DOM simulation candidate Render only when explicit flag enabled

Conservative defaults: CEM without Less extension → client-only (not SSR). 29 tests passing.

Step 3: SSR/client-only Planner ✅

Updated packages/adapter-vite/src/entry-descriptor.ts:

  • buildSsrAdmissionPlan() now accepts CompatibilityClassification[]
  • CEM classifications take precedence over island metadata
  • SsrAdmissionPlan.cemClassifications field added
  • 18 tests passing (9 new + 9 existing)

Step 4: Report Schema Extension ✅

  • packages/core/src/types.tsCemCompatibilityReport interface added to DsdBuildReport
  • packages/adapter-vite/src/cli/ssg-render.tsbuildCemCompatibilityReport() builder
  • packages/adapter-vite/src/build-context.tsPhase1Meta.cemClassifications field
  • Report schema version bumped to 1.1.0
  • cemCompatibility section in dsd-report.json

Step 5: Fixtures and Tests ✅

  • 4 new tests for CEM compatibility in ssg-report.test.ts
  • 6 new tests for CEM auto-detection in route-scanner.test.ts
  • Total: 630 tests passing

CEM Plugin Integration ✅

Completed the "last mile" integration that was missing from the original SOP:

  • packages/adapter-vite/src/route-scanner.tsscanCemManifests() + detectAndClassifyCemPackages()
    • Scans node_modules for custom-elements.json without executing package code
    • Handles scoped packages (@org/pkg), skips invalid JSON (non-fatal)
    • Calls parseCem() + classifyCemManifest() pipeline
  • packages/adapter-vite/src/index.tsbuildStart() now calls detectAndClassifyCemPackages()
    • Stores results in ctx.phase1.cemClassifications
    • Passes cemClassifications to buildEntryDescriptor()
    • Failure is non-fatal (best-effort, debug log only)
  • packages/core/deno.json — added ./compatibility subpath export

Package Version Update

Updated all 12 packages from 0.17.5 to 0.18.0:

  1. @lessjs/core
  2. @lessjs/adapter-lit
  3. @lessjs/adapter-react
  4. @lessjs/adapter-vanilla
  5. @lessjs/adapter-vite
  6. @lessjs/app
  7. @lessjs/content
  8. @lessjs/create
  9. @lessjs/i18n
  10. @lessjs/rpc
  11. @lessjs/signals
  12. @lessjs/ui

Note: Inter-package dependencies use ^0.17.0 (caret range), so 0.18.0 is automatically compatible.

Verification

  • All 5 SOP items implemented
  • CEM plugin integration complete
  • 630 tests passing
  • deno task fmt:check && deno task lint && deno task typecheck
  • Committed and pushed to origin/dev

Breaking Changes

None. This is a minor release that adds:

  • New CEM parsing capability
  • New compatibility classification tiers
  • New report schema extensions
  • No API changes
  • No behavior changes (conservative defaults preserve existing behavior)

Migration Guide

For users: No action needed. v0.18.0 is a drop-in replacement for v0.17.5.

For third-party Web Component authors:

  • If your package has a custom-elements.json, it will now be auto-detected
  • By default, your components are treated as client-only (not SSR)
  • To enable SSR: add a LessJS manifest with ssr: true or use a supported adapter

For contributors:

  • When adding new compatibility tiers, update packages/core/src/compatibility.ts
  • When modifying CEM parsing, update packages/core/src/cem-parser.ts
  • Run deno task test to verify compatibility classification

Next Steps

With v0.18.0 complete, the project can now proceed to:

  • v0.18.1: less validate-manifest CLI built on top of the classifier
  • See docs/sop/v0.18.1-validate-manifest-cli.md (to be created)

Diff Summary

git diff --stat v0.17.5..v0.18.0

packages/core/src/cem-parser.ts (new)
packages/core/src/compatibility.ts (new)
packages/core/src/types.ts (CEM types added)
packages/adapter-vite/src/entry-descriptor.ts (cemClassifications support)
packages/adapter-vite/src/entry-renderer.ts (cemClassifications support)
packages/adapter-vite/src/route-scanner.ts (CEM auto-detection)
packages/adapter-vite/src/build-context.ts (Phase1Meta.cemClassifications)
packages/adapter-vite/src/cli/ssg-render.ts (cemCompatibility report)
packages/adapter-vite/__tests__/ssr-admission.test.ts (18 tests)
packages/adapter-vite/__tests__/route-scanner.test.ts (CEM tests)
packages/adapter-vite/__tests__/ssg-report.test.ts (CEM report tests)
packages/core/deno.json (version bump + ./compatibility export)
packages/adapter-lit/deno.json (version bump)
packages/adapter-react/deno.json (version bump)
packages/adapter-vanilla/deno.json (version bump)
packages/adapter-vite/deno.json (version bump)
packages/app/deno.json (version bump)
packages/content/deno.json (version bump)
packages/create/deno.json (version bump)
packages/i18n/deno.json (version bump)
packages/rpc/deno.json (version bump)
packages/signals/deno.json (version bump)
packages/ui/deno.json (version bump)

Stats:

  • 25+ files changed
  • 2 new core modules (cem-parser, compatibility)
  • 630 tests passing
  • 12 version bumps

Consumer-Level Explanation (Simple Analogies)

What was the problem?

Imagine you're building a house, and you can use materials from:

  • Local suppliers (your own components) — you know exactly how they work
  • Third-party suppliers (npm packages) — you don't know if they work in SSR or only in browser

Previously, LessJS treated all third-party Web Components as potentially SSR-safe, which could cause runtime failures if a component tried to access browser APIs during server-side rendering.

What did we do in v0.18.0?

  1. Added a "material inspector" (CEM Parser)

    • Reads the "spec sheet" (custom-elements.json) for each third-party package
    • Understands what the component is and what it needs
  2. Added a "classification system" (Compatibility Classifier)

    • SSR-capable: safe for server rendering
    • Client-only: must run in browser only
    • Rejected: broken or unsafe
    • Experimental: needs opt-in
  3. Added "automatic detection" (CEM Plugin Integration)

    • Scans your node_modules for Web Component packages
    • Classifies them automatically
    • No configuration needed
  4. Added "reporting" (Report Schema Extension)

    • Every decision is logged in dsd-report.json
    • You can see exactly why each component was classified

Why should you care?

  • If you're a user: Your builds are now safer. Third-party components that don't support SSR are automatically excluded from the SSR bundle, preventing runtime failures.

  • If you're a library author: Add a custom-elements.json to your package. By default, it's treated as client-only (safe). Add LessJS metadata to enable SSR if your component supports it.

Analogy Summary

Before v0.18.0: "I hope all these third-party materials work on the server."

After v0.18.0: "Here's exactly which materials are safe for server, which need browser, and why. No more guessing."