Skip to content

sxzz/unloader

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.

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

About

Node.js loader with a Rollup-like interface.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors