unloader

Node.js loader with a Rollup-like interface.

  • Types
  • ESM
License
MIT
Install Size
22 kB(615.8 kB)
Vulns
0
Published

Get started

$npm install unloader@0.10.0
$pnpm add unloader@0.10.0
$yarn add unloader@0.10.0
$bun add unloader@0.10.0
$deno add npm:unloader@0.10.0
$vlt install unloader@0.10.0
$vp add unloader@0.10.0
$nub add unloader@0.10.0

Readme

unloader

npm version npm downloads Unit Test

Node.js loader with a Rollup-like interface.

Overview

unloader is a Node.js loader framework. Similar to Rollup as a general bundler, unloader provides customization capabilities through a subset of Rollup plugin API.

unloader is designed to be a general-purpose loader, which can be used to develop various loaders, such as Oxc loader, TypeScript loader, etc.

Install

Pre-requisites

Node.js v22.18 and above

npm i unloader

Usage

CLI
node --import unloader/register ...

Plugin Development

Hooks
Hook Description
options Modify the options from userland.
resolveId Resolve the module id.
load Load the module.
transform Transform the module.
ESM and CJS

unloader supports both ESM and CJS. All hooks are synchronous.

import { readFileSync } from 'node:fs'
import type { Plugin } from 'unloader'

const plugin: Plugin = {
  name: 'my-plugin',
  resolveId(source, importer, options) {
    const result = this.resolve(`${source}.js`, importer, options)
    if (result) {
      console.log(result)
      return result
    }
  },
  load(id) {
    const contents = readFileSync(id, 'utf8')
    console.log(contents)
    return contents
  },
}
Example
demo.ts
let context: PluginContext

export function demoPlugin(): Plugin {
  return {
    name: 'demo-plugin',
    options(config) {
      config.sourcemap = true
    },
    buildStart(_context) {
      context = _context
      context.log('hello world')
    },
    resolveId(source, importer, options) {
      if (source.startsWith('node:')) return

      // Feature: virtual module
      if (source === 'virtual-mod') {
        return '/virtual-mod'
      }

      // Feature: try resolve with different extensions
      const result = this.resolve(`${source}.js`, importer, options)
      if (result) return result
    },

    load(id) {
      if (id === '/virtual-mod') {
        return { code: 'export const count = 42' }
      }
    },
    transform(code, id) {
      if (typeof code === 'string') {
        // Feature: source map
        const s = new MagicString(code)
        s.prepend('// header\n')
        const map = s.generateMap({
          file: id,
          hires: 'boundary',
          includeContent: true,
        })
        return {
          code: s.toString(),
          map,
        }
      }
    },
  }
}

See demo plugin and unloader.config.ts for more details.

unplugin

unloader is supported as a framework in unplugin.

// unloader.config.ts
import Oxc from 'unplugin-oxc/unloader'

export default {
  plugins: [
    Oxc({
      // options
    }),
  ],
}

Credits

  • Thanks to tsx!

Sponsors

License

MIT License © 2025-PRESENT Kevin Deng