external-bundle

SkillDev tools

Add, use, or migrate a module to the external bundle system in sy-f-misc. Trigger when: user asks to reduce bundle size, move a module to external, use dynamic import for a large module, or asks about @external imports.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the external-bundle skill

What this skill tells your AI

The instructions your AI receives, as published by frostime/sy-f-misc in .agents/skills/external-bundle/SKILL.md and read by ahel’s review.

What This Skill Covers

The external bundle system lets you split large/infrequently-used modules out of the main index.js bundle. They are compiled to separate .js files under external/ and loaded at runtime via dynamic import().

Full architecture detailsdev-doc


When to Use External Modules

Use external bundle for a module when all of the following are true:

  • Size > ~5 KB (use pnpm run build + check bundle stats, or estimate from file size)
  • Not on the startup critical path (not imported top-level in index.ts chain)
  • Feature is triggered by user action, not automatically on plugin load
  • Module is self-contained (doesn't depend heavily on other src/ internals)

Step-by-Step Workflow

A. Create a New External Module

  1. Create the source file in src/external/:

    // src/external/my-module.ts
    export function myFunction(input: string): string {
        return input.trim();
    }
    export default class MyClass { /* ... */ }
    

    For a directory module:

    src/external/my-lib/
      index.ts    ← entry point
      helpers.ts  ← internal (bundled into my-lib.js)
    
  2. Register in vite.config.ts:

    // ============ 配置区域 ============
    const EXTERNAL_MODULES = ["sandbox", "text-edit-engine", "my-module"];
    // =================================
    
  3. Import dynamically in business code:

    // In an async function
    const mod = await import('@external/my-module');
    const result = mod.myFunction('hello');
    const instance = new mod.default();
    
  4. Verify build: Run pnpm dev or pnpm build, confirm:

    • dev/external/my-module.js (or dist/external/) is generated
    • No warnings about unregistered modules in console

B. Migrate Existing Module to External

  1. Move the file:

    src/libs/heavy-module.ts  →  src/external/heavy-module.ts
    
  2. Register in vite.config.ts EXTERNAL_MODULES array.

  3. Update all import sites — replace static imports with dynamic:

    // Before (static)
    import HeavyModule from '@/libs/heavy-module';
    
    // After (dynamic) — must be inside async function
    const { default: HeavyModule } = await import('@external/heavy-module');
    
  4. Remove old file from src/libs/ if no longer needed there.

  5. For TypeScript types — use import type at the top (safe, no runtime effect):

    import type { MyType } from '@external/heavy-module';
    

C. Use an Existing External Module

// Pattern 1: default export class
const SandboxModule = await import('@external/sandbox');
const JavaScriptSandBox = SandboxModule.default;
const instance = new JavaScriptSandBox();
await instance.init();

// Pattern 2: named exports
const { doSomething, MyClass } = await import('@external/my-module');

// Pattern 3: store module for reuse (avoid repeated imports)
let _sandboxMod: typeof import('@external/sandbox') | null = null;
async function getSandbox() {
    _sandboxMod ??= await import('@external/sandbox');
    return _sandboxMod;
}

Checklist Before Finishing

  • Module file exists in src/external/
  • Module name added to EXTERNAL_MODULES in vite.config.ts
  • All import sites use await import('@external/...') (no static imports)
  • import type is used for type-only access if needed
  • Build runs without warnings about unregistered modules
  • Output file appears in dev/external/ or dist/external/
  • Old file removed from its original location (if migrating)

Common Mistakes

MistakeEffectFix
import X from '@external/foo' (static)Plugin removes it, runtime crashUse await import(...)
Module not in EXTERNAL_MODULESBuild warning, runtime 404Add to config array
Calling import('@external/foo') at top levelCJS bundle error with top-level awaitMove into async function
External module imports from @/ (main src)Compile error or missing referenceCopy utility or extract to npm package
Forgot to save vite.config.ts after adding moduleModule not builtConfirm the config change

Key Files

FileRole
vite.config.tsEXTERNAL_MODULES list + plugin setup
vite-plugin-external-modules.tsPlugin implementation (scan, build, transform)
src/external/Source directory for all external modules
dev/external/ / dist/external/Build output

Signals

GitHub stars
29
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
external-bundle
Source
github.com/frostime/sy-f-misc