Skip to main content
A Rollup plugin that enables importing ESM modules from CDN URLs for local processing, allowing tree-shaking on non-local resources.

Features

  • CDN Imports - Import npm packages directly from CDN URLs
  • Tree-shaking - Full tree-shaking support for CDN modules
  • Multiple CDNs - Support for Skypack with fallback chains
  • Version Pinning - Pin specific package versions
  • Custom Resolvers - Use any CDN with custom URL resolvers

Installation

npm install rollup-plugin-import-cdn

Quick Start

import { importCdn } from "rollup-plugin-import-cdn";

export default {
  input: "src/index.js",
  output: { file: "dist/bundle.js", format: "esm" },
  plugins: [importCdn()],
};
Now you can import packages directly from URLs:
// Resolved via Skypack by default
import { debounce } from "lodash-es";

// Direct URL import
import confetti from "https://esm.sh/canvas-confetti";

Configuration

Version Pinning

Pin specific versions for reproducible builds:
importCdn({
  versions: {
    react: "18.2.0",
    "react-dom": "18.2.0",
    lodash: "4.17.21",
  },
});

Custom CDN Resolvers

Use any CDN by providing custom resolver functions:
importCdn({
  priority: [
    // Try esm.sh first
    (packageName) => `https://esm.sh/${packageName}`,
    // Fall back to Skypack
    "skypack",
    // Then try unpkg
    (packageName) => `https://unpkg.com/${packageName}?module`,
  ],
});

Custom Fetch Implementation

For environments without global fetch or for adding custom headers:
import nodeFetch from "node-fetch";

importCdn({
  fetchImpl: nodeFetch,
});

How It Works

  1. Resolution: When Rollup encounters an import, the plugin checks if it’s a CDN-resolvable module
  2. Fetching: The module is fetched from the configured CDN(s)
  3. Transformation: Relative imports within the fetched module are resolved to absolute CDN URLs
  4. Bundling: Rollup processes the module like any local file, enabling tree-shaking

Import Resolution

Import TypeExampleBehavior
Package nameimport "lodash"Resolved via CDN
Scoped packageimport "@tanstack/react-query"Resolved via CDN
Direct URLimport "https://esm.sh/react"Fetched directly
Local relativeimport "./local"Ignored (handled by Rollup)
// esm.sh - Fast, global CDN
(pkg) => `https://esm.sh/${pkg}`

// unpkg - npm CDN
(pkg) => `https://unpkg.com/${pkg}?module`

// jsDelivr - Multi-CDN
(pkg) => `https://cdn.jsdelivr.net/npm/${pkg}/+esm`

API Reference

importCdn(options?)

Creates the Rollup plugin.

Options

OptionTypeDefaultDescription
fetchImplFetchImplglobalThis.fetchFetch implementation for HTTP requests
priorityArray<AvailableCDNs | (key: string) => string>["skypack"]CDN resolution priority
versionsRecord<string, string>{}Package version pinning

Examples

Vite Configuration

// vite.config.js
import { defineConfig } from "vite";
import { importCdn } from "rollup-plugin-import-cdn";

export default defineConfig({
  build: {
    rollupOptions: {
      plugins: [
        importCdn({
          versions: { three: "0.160.0" },
        }),
      ],
    },
  },
});

Multi-CDN Fallback

importCdn({
  priority: [
    (pkg) => `https://esm.sh/${pkg}`,
    "skypack",
    (pkg) => `https://unpkg.com/${pkg}?module`,
  ],
});

Types

import type {
  PluginOptions,
  FetchImpl,
  AvailableCDNs,
  Dependency,
} from "rollup-plugin-import-cdn";

Compatibility

  • Rollup: 3.x, 4.x
  • Node.js: 18+ (requires fetch or custom fetchImpl)