Spec Registry
Help your agents use open-source better. Learn more.
Find usage specs for your project’s dependencies
- Author
- tessl
- Last updated
- Spec files
npm-svelte
Describes: npm/svelte
- Description
- A cybernetically enhanced web application framework that compiles to highly optimized JavaScript with reactive state management and component-based architecture.
- Author
- tessl
- Last updated
legacy.md docs/
1# Legacy Compatibility23Svelte 5 provides compatibility utilities for migrating from Svelte 4 patterns and working with legacy components. These utilities help bridge the gap between the old reactivity system and the new runes-based approach.45## Capabilities67### createClassComponent89Creates a Svelte 4-style class component from a modern Svelte 5 component for backwards compatibility.1011```typescript { .api }12/**13* Create a legacy class component from a modern Svelte 5 component14* @param component - Modern Svelte 5 component15* @returns Legacy class component with Svelte 4 API16*/17function createClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>>(18component: Component<Props, Exports>19): LegacyComponentConstructor<Props, Exports>;20```2122**Usage Examples:**2324```typescript25import { createClassComponent } from "svelte/legacy";26import ModernComponent from "./ModernComponent.svelte";2728// Create legacy wrapper29const LegacyComponent = createClassComponent(ModernComponent);3031// Use with Svelte 4 patterns32const instance = new LegacyComponent({33target: document.getElementById("app"),34props: {35name: "World",36count: 037}38});3940// Legacy API methods41instance.$set({ count: 5 });42instance.$on("event", (event) => {43console.log("Event received:", event.detail);44});4546// Legacy lifecycle47instance.$destroy();4849// Access props and component references50console.log(instance.$$.props);51console.log(instance.$$.component);52```5354### asClassComponent5556Marks a Svelte 5 component to be compiled with legacy class component API for backwards compatibility.5758```typescript { .api }59/**60* Mark a component to be compiled with legacy class component API61* @param component - Component constructor to mark as legacy62* @returns The same component with legacy compilation marker63*/64function asClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>>(65component: Component<Props, Exports>66): Component<Props, Exports>;67```6869**Usage Examples:**7071```typescript72// ModernComponent.svelte - in <script> tag73import { asClassComponent } from "svelte/legacy";7475// Mark this component for legacy compilation76export default asClassComponent(77// Component definition here78);7980// Or in parent component81import { asClassComponent } from "svelte/legacy";82import Component from "./Component.svelte";8384const LegacyWrappedComponent = asClassComponent(Component);8586// Now can be used with legacy patterns87const instance = new LegacyWrappedComponent({88target: document.body,89props: { message: "Hello" }90});91```9293### Legacy Component Patterns9495Working with components that expect the old Svelte 4 component API.9697**Migration Example:**9899```typescript100// Before (Svelte 4)101import Component from "./Component.svelte";102103const app = new Component({104target: document.getElementById("app"),105props: {106name: "world"107}108});109110app.$set({ name: "svelte" });111app.$on("close", () => {112app.$destroy();113});114115// After (Svelte 5 with legacy compatibility)116import { createClassComponent } from "svelte/legacy";117import Component from "./Component.svelte"; // Modern Svelte 5 component118119const LegacyComponent = createClassComponent(Component);120121const app = new LegacyComponent({122target: document.getElementById("app"),123props: {124name: "world"125}126});127128app.$set({ name: "svelte" });129app.$on("close", () => {130app.$destroy();131});132```133134### Interoperability Patterns135136**Using Legacy Components in Modern Context:**137138```typescript139// Modern parent component using legacy child140import { createClassComponent } from "svelte/legacy";141import LegacyChild from "./LegacyChild.svelte";142143const LegacyChildClass = createClassComponent(LegacyChild);144145let childInstance = $state(null);146let containerElement;147148$effect(() => {149if (containerElement) {150childInstance = new LegacyChildClass({151target: containerElement,152props: {153data: someReactiveData154}155});156157return () => {158childInstance?.$destroy();159};160}161});162163// Update props reactively164$effect(() => {165if (childInstance) {166childInstance.$set({ data: someReactiveData });167}168});169```170171**Legacy Event Handling:**172173```typescript174import { createClassComponent } from "svelte/legacy";175import EventEmittingComponent from "./EventEmittingComponent.svelte";176177const LegacyEventComponent = createClassComponent(EventEmittingComponent);178179const instance = new LegacyEventComponent({180target: document.body181});182183// Handle legacy events184instance.$on("customEvent", (event) => {185console.log("Custom event:", event.detail);186});187188instance.$on("click", (event) => {189console.log("Click event:", event);190});191192// Programmatic event dispatch (if supported by component)193instance.$set({ triggerEvent: true });194```195196### Third-Party Library Integration197198**Integrating with libraries that expect Svelte 4 components:**199200```typescript201import { createClassComponent } from "svelte/legacy";202import MyComponent from "./MyComponent.svelte";203import ThirdPartyLibrary from "some-svelte4-library";204205// Wrap modern component for legacy library206const WrappedComponent = createClassComponent(MyComponent);207208// Use with third-party library that expects Svelte 4 API209const libraryInstance = new ThirdPartyLibrary({210component: WrappedComponent,211target: document.getElementById("container"),212props: {213title: "Hello World"214}215});216217// Library can now use legacy API methods218libraryInstance.component.$set({ title: "Updated Title" });219libraryInstance.component.$on("change", handleChange);220```221222### Component Factory Pattern223224**Creating reusable legacy component factories:**225226```typescript227import { createClassComponent } from "svelte/legacy";228229// Factory function for creating legacy versions230function createLegacyFactory(modernComponent) {231const LegacyClass = createClassComponent(modernComponent);232233return function createInstance(target, props = {}) {234return new LegacyClass({235target,236props,237// Default legacy options238intro: true,239anchor: null240});241};242}243244// Usage245import Modal from "./Modal.svelte";246import Tooltip from "./Tooltip.svelte";247248const createLegacyModal = createLegacyFactory(Modal);249const createLegacyTooltip = createLegacyFactory(Tooltip);250251// Create instances with legacy API252const modal = createLegacyModal(document.body, {253title: "Confirmation",254message: "Are you sure?"255});256257const tooltip = createLegacyTooltip(document.getElementById("help"), {258text: "Click for help",259position: "top"260});261```262263## Types264265```typescript { .api }266interface LegacyComponentConstructor<Props extends Record<string, any>, Exports extends Record<string, any>> {267new (options: {268target: Element | Document | ShadowRoot;269anchor?: Element;270props?: Props;271context?: Map<any, any>;272hydrate?: boolean;273intro?: boolean;274$$inline?: boolean;275}): LegacyComponentInstance<Props, Exports>;276}277278interface LegacyComponentInstance<Props extends Record<string, any>, Exports extends Record<string, any>> {279/** Update component props */280$set(props: Partial<Props>): void;281282/** Subscribe to component events */283$on(event: string, callback: (event: CustomEvent) => void): () => void;284285/** Destroy component instance */286$destroy(): void;287288/** Access to internal component state */289$$: {290props: Props;291component: Exports;292ctx: any;293};294}295296interface Component<297Props extends Record<string, any> = {},298Exports extends Record<string, any> = {},299Bindings extends keyof Props | '' = string300> {301(internals: ComponentInternals, props: Props): Exports;302}303```304305## Migration Strategies306307### Gradual Migration308309```typescript310// Phase 1: Wrap legacy components311import { createClassComponent } from "svelte/legacy";312import OldComponent from "./OldComponent.svelte";313314const WrappedOldComponent = createClassComponent(OldComponent);315316// Phase 2: Update usage patterns gradually317// Instead of: new OldComponent({...})318// Use: new WrappedOldComponent({...})319320// Phase 3: Migrate component internals to runes321// Update OldComponent.svelte to use $state, $derived, etc.322323// Phase 4: Remove legacy wrapper when ready324// import OldComponent from "./OldComponent.svelte";325// const instance = mount(OldComponent, {...});326```327328### Testing Legacy Components329330```typescript331import { createClassComponent } from "svelte/legacy";332import { render } from "@testing-library/svelte";333import Component from "./Component.svelte";334335// Test modern component336test("modern component", () => {337const { getByText } = render(Component, { props: { name: "test" } });338expect(getByText("Hello test")).toBeInTheDocument();339});340341// Test legacy wrapped component342test("legacy wrapped component", () => {343const LegacyComponent = createClassComponent(Component);344const container = document.createElement("div");345346const instance = new LegacyComponent({347target: container,348props: { name: "test" }349});350351expect(container.textContent).toContain("Hello test");352353instance.$set({ name: "updated" });354expect(container.textContent).toContain("Hello updated");355356instance.$destroy();357});358```359360## Best Practices3613621. **Use sparingly**: Legacy compatibility should be temporary during migration3632. **Test thoroughly**: Ensure legacy wrappers maintain expected behavior3643. **Document usage**: Clearly mark where legacy compatibility is being used3654. **Plan migration**: Create timeline for removing legacy compatibility3665. **Monitor performance**: Legacy wrappers may have performance overhead3676. **Update incrementally**: Migrate components one at a time rather than all at once368369## Common Pitfalls3703711. **Event handling differences**: Some events may behave differently between Svelte 4 and 53722. **Lifecycle timing**: Component lifecycle may have subtle timing differences3733. **SSR compatibility**: Ensure legacy components work with server-side rendering3744. **Bundle size**: Legacy compatibility adds to bundle size3755. **Type compatibility**: TypeScript types may need adjustment for legacy components376377## Debugging Legacy Components378379```typescript380import { createClassComponent } from "svelte/legacy";381import Component from "./Component.svelte";382383const LegacyComponent = createClassComponent(Component);384385const instance = new LegacyComponent({386target: document.body,387props: { debug: true }388});389390// Access internal state for debugging391console.log("Component props:", instance.$$.props);392console.log("Component context:", instance.$$.ctx);393394// Monitor prop changes395const originalSet = instance.$set;396instance.$set = function(props) {397console.log("Legacy $set called with:", props);398return originalSet.call(this, props);399};400401// Monitor events402const originalOn = instance.$on;403instance.$on = function(event, callback) {404console.log("Legacy $on registered for:", event);405return originalOn.call(this, event, callback);406};407```