Skip to content

Proposal: CDN Usage Guide for TypeScript Projects #996

Open

Description

@Qsppl

Hi team! I've prepared a guide for using Orbit.js via CDN in TypeScript projects without bundlers. It covers:

  • CDN imports with full TypeScript support
  • tsconfig.json setup
  • Cross-dependency resolution

Would you consider adding this to the official docs? Here's the full guide:

CDN Usage Guide for TypeScript Projects

This guide explains how to use Orbit.js with CDN imports while maintaining full TypeScript support in ESNext projects without bundlers.

Installation

First, install Orbit.js packages locally to get type definitions:

npm install @orbit/jsonapi @orbit/records

ES2015/ES6/ES2020/ES2022/ESNext

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "paths": {
       // Names for Orbit CDN Package Imports
       "https://esm.sh/@orbit/jsonapi": ["node_modules/@orbit/jsonapi/dist/modules/index"],
       "https://esm.sh/@orbit/records": ["node_modules/@orbit/records/dist/modules/index"],

       // For cross-package imports
       "@orbit/coordinator": ["node_modules/@orbit/coordinator/dist/modules/index"],
       "@orbit/core": ["node_modules/@orbit/core/dist/modules/index"],
       "@orbit/data": ["node_modules/@orbit/data/dist/modules/index"],
       "@orbit/identity-map": ["node_modules/@orbit/identity-map/dist/modules/index"],
       "@orbit/immutable": ["node_modules/@orbit/immutable/dist/modules/index"],
       "@orbit/indexeddb": ["node_modules/@orbit/indexeddb/dist/modules/index"],
       "@orbit/indexeddb-bucket": ["node_modules/@orbit/indexeddb-bucket/dist/modules/index"],
       "@orbit/jsonapi": ["node_modules/@orbit/jsonapi/dist/modules/index"],
       "@orbit/local-storage": ["node_modules/@orbit/local-storage/dist/modules/index"],
       "@orbit/local-storage-bucket": ["node_modules/@orbit/local-storage-bucket/dist/modules/index"],
       "@orbit/memory": ["node_modules/@orbit/memory/dist/modules/index"],
       "@orbit/record-cache": ["node_modules/@orbit/record-cache/dist/modules/index"],
       "@orbit/records": ["node_modules/@orbit/records/dist/modules/index"],
       "@orbit/serializers": ["node_modules/@orbit/serializers/dist/modules/index"],
       "@orbit/utils": ["node_modules/@orbit/utils/dist/modules/index"],
       "@orbit/validators": ["node_modules/@orbit/validators/dist/modules/index"],
    }
  }
}

The same pattern works for all Orbit.js packages:

  • @orbit/coordinator
  • @orbit/identity-map
  • @orbit/indexeddb
  • @orbit/local-storage
  • @orbit/memory
  • @orbit/utils
  • etc.

Simply follow the same URL pattern:

"https://esm.sh/@orbit/<package>@<version>": ["node_modules/@orbit/<package>/dist/modules/index"]
// For cross-package imports
"@orbit/<package>": ["node_modules/@orbit/<package>/dist/modules/index"]

Node16/Node18/NodeNext

Just use module declarations:

// global.d.ts
declare module "https://cdn.investprojects.info/@orbit/core@0.17.0" {
  export * from "@orbit/core";
}

Usage Example

import JSONAPISource from "https://cdn.investprojects.info/@orbit/jsonapi"
import { RecordSchema } from "https://cdn.investprojects.info/@orbit/records"

const schema = new RecordSchema({
  models: {
    planet: {
      attributes: {
        name: { type: "string" },
        classification: { type: "string" },
        atmosphere: { type: "boolean" },
      },
      relationships: {
        moons: { kind: "hasMany", type: "moon", inverse: "planet" },
      },
    },
    moon: {
      attributes: {
        name: { type: "string" },
      },
      relationships: {
        planet: { kind: "hasOne", type: "planet", inverse: "moons" },
      },
    },
  },
})

const remote = new JSONAPISource({
  schema: schema,
  host: "/my-entry",
})

Key Points

  1. Version Pinning: Always specify package versions in CDN URLs
  2. Path Resolution: TypeScript finds types via paths mapping
  3. No Bundler Needed: Works with native browser ESM
  4. Cross-Package Dependencies: Internal imports are resolved through local node_modules

Troubleshooting

If types aren't being resolved:

  1. Verify paths point to existing files in node_modules
  2. Run tsc --traceResolution to debug path resolution
  3. If your server's web root is not set to "/" but to "/web", "/public", etc., then this needs to be explicitly specified in your tsconfig:
    {
    "compilerOptions": {
        "target": "ES2022",
        "module": "ESNext",
        "baseUrl": "./web/",
        "paths": {
        // NOT "node_modules/...", BUT "../node_modules/..." relative by "baseUrl"!
        "https://esm.sh/@orbit/coordinator": ["../node_modules/@orbit/coordinator/dist/modules/index"],
        "https://esm.sh/@orbit/core": ["../node_modules/@orbit/core/dist/modules/index"],
        ...
        }
    }
    }

Why This Works

  • The paths setting redirects CDN imports to local type definitions
  • Local npm packages provide complete type information

This could help developers who need CDN-based workflows while keeping type safety.

This guide provides a complete solution for:
✅ CDN usage with type safety
✅ No bundler required
✅ Cross-package dependency resolution
✅ Clean developer experience

Would you like me to make any adjustments before you submit it to the Orbit.js repository?

Activity

  1. dgeb commented on Apr 9, 2025

    @dgeb
    Member

    This sounds great! I think this will modernize the CDN-based workflows while keeping type safety.

  2. steodor commented on Apr 15, 2025

    @steodor

    Nice! Just a few typos in tsconfig.json, some node_modules@orbit here and there, and "..@orbit/local-storage-bucket i think was also supposed to be like node_modules/@orbit...? Thanks!

  3. Qsppl commented on Apr 17, 2025

    @Qsppl
    Author

    Nice! Just a few typos in tsconfig.json, some node_modules@orbit here and there, and "..@orbit/local-storage-bucket i think was also supposed to be like node_modules/@orbit...? Thanks!

    Thanks, I checked the imports and corrected the typos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions