Skip to main content

unimport vs unplugin-auto-import vs babel-plugin-auto-import: Auto-Importing in JavaScript (2026)

·PkgPulse Team

TL;DR

unimport is the UnJS auto-import engine — scans for available exports and generates import statements automatically, powers Nuxt's auto-imports (composables, utils, components). unplugin-auto-import is the universal build plugin — uses unplugin to work with Vite, Webpack, Rollup, and esbuild, auto-imports from libraries like Vue, React, and custom directories. babel-plugin-auto-import is the Babel transform — resolves missing identifiers at compile time, works with any Babel-based setup. In 2026: unplugin-auto-import for Vite/Webpack projects, unimport for framework authors building Nuxt-like DX, babel-plugin-auto-import for Babel-only setups.

Key Takeaways

  • unimport: ~5M weekly downloads — UnJS, powers Nuxt auto-imports, generates TypeScript declarations
  • unplugin-auto-import: ~3M weekly downloads — universal plugin (Vite/Webpack/Rollup), preset-based
  • babel-plugin-auto-import: ~50K weekly downloads — Babel transform, simple identifier mapping
  • Auto-importing eliminates repetitive import { ref, computed } from "vue" boilerplate
  • unimport and unplugin-auto-import generate .d.ts files for TypeScript support
  • unplugin-auto-import has presets for Vue, React, Svelte, VueUse, and more

The Problem

// Without auto-imports — every file starts with boilerplate:
import { ref, computed, watch, onMounted } from "vue"
import { useRouter, useRoute } from "vue-router"
import { storeToRefs } from "pinia"
import { useUserStore } from "@/stores/user"
import { formatDate } from "@/utils/date"
import { debounce } from "@/utils/helpers"

// With auto-imports — just use them:
const count = ref(0)
const doubled = computed(() => count.value * 2)
const router = useRouter()
const { user } = storeToRefs(useUserStore())
const formatted = formatDate(new Date())

unimport

unimport — the auto-import engine:

Basic usage

import { createUnimport } from "unimport"

const { injectImports } = createUnimport({
  // Import from packages:
  imports: [
    { name: "ref", from: "vue" },
    { name: "computed", from: "vue" },
    { name: "watch", from: "vue" },
    { name: "useRouter", from: "vue-router" },
  ],
})

// Transform source code — adds missing imports:
const input = `
const count = ref(0)
const doubled = computed(() => count.value * 2)
`

const { code } = await injectImports(input)
// Output:
// import { ref, computed } from "vue"
// const count = ref(0)
// const doubled = computed(() => count.value * 2)

Presets

import { createUnimport } from "unimport"
import { builtinPresets } from "unimport"

const { injectImports } = createUnimport({
  presets: [
    // Built-in presets for popular frameworks:
    "vue",           // ref, computed, watch, onMounted, etc.
    "vue-router",    // useRouter, useRoute, etc.
    "pinia",         // defineStore, storeToRefs, etc.
    "react",         // useState, useEffect, useCallback, etc.
    "svelte",        // onMount, onDestroy, etc.
  ],
})

Directory scanning

import { createUnimport } from "unimport"

const { injectImports } = createUnimport({
  // Auto-import from local directories:
  dirs: [
    "./src/composables",   // useAuth, useTheme, etc.
    "./src/utils",          // formatDate, debounce, etc.
    "./src/stores",         // useUserStore, useCartStore, etc.
  ],

  // Options for directory scanning:
  dirsScanOptions: {
    filePatterns: ["*.ts", "*.js"],
    fileFilter: (file) => !file.includes(".test."),
  },
})

TypeScript declaration generation

import { createUnimport } from "unimport"

const unimport = createUnimport({
  imports: [
    { name: "ref", from: "vue" },
    { name: "computed", from: "vue" },
  ],
  dirs: ["./src/composables"],
})

// Generate .d.ts for TypeScript support:
const dts = await unimport.generateTypeDeclarations()
// Writes: declare global { const ref: typeof import("vue")["ref"] }

// Generate ESLint globals config:
const eslintConfig = await unimport.generateESLintFlatConfig()

How Nuxt uses unimport

// Nuxt's auto-imports are powered by unimport:

// nuxt.config.ts — these are auto-imported without manual imports:
// useAsyncData, useFetch, useHead, useRoute, useRouter
// ref, computed, watch, onMounted
// definePageMeta, navigateTo, useState

// In your Nuxt component — no imports needed:
const { data } = await useFetch("/api/packages")
const route = useRoute()
const count = ref(0)

// Nuxt configures unimport with:
// - Vue composables (ref, computed, etc.)
// - Nuxt composables (useFetch, useState, etc.)
// - Auto-scanned composables/ directory
// - TypeScript declarations generated automatically

unplugin-auto-import

unplugin-auto-import — universal auto-import plugin:

Vite setup

// vite.config.ts
import AutoImport from "unplugin-auto-import/vite"

export default defineConfig({
  plugins: [
    AutoImport({
      // Presets for popular libraries:
      imports: [
        "vue",
        "vue-router",
        "pinia",
        "@vueuse/core",
      ],

      // Auto-import from directories:
      dirs: [
        "./src/composables",
        "./src/stores",
      ],

      // Generate TypeScript declarations:
      dts: "./auto-imports.d.ts",

      // Generate ESLint config:
      eslintrc: {
        enabled: true,
      },
    }),
  ],
})

Webpack setup

// webpack.config.js
const AutoImport = require("unplugin-auto-import/webpack")

module.exports = {
  plugins: [
    AutoImport({
      imports: ["react", "react-router-dom"],
      dts: "./auto-imports.d.ts",
    }),
  ],
}

React preset

// vite.config.ts
import AutoImport from "unplugin-auto-import/vite"

export default defineConfig({
  plugins: [
    AutoImport({
      imports: [
        "react",
        // Custom imports:
        {
          "react-router-dom": [
            "useNavigate",
            "useParams",
            "useSearchParams",
            "Link",
          ],
          "@tanstack/react-query": [
            "useQuery",
            "useMutation",
            "useQueryClient",
          ],
        },
      ],
      dts: true,
    }),
  ],
})

// Now in any component — no imports needed:
function PackageList() {
  const [search, setSearch] = useState("")
  const navigate = useNavigate()
  const { data } = useQuery({
    queryKey: ["packages", search],
    queryFn: () => fetchPackages(search),
  })
  // useState, useNavigate, useQuery all auto-imported
}

Custom resolvers

import AutoImport from "unplugin-auto-import/vite"

export default defineConfig({
  plugins: [
    AutoImport({
      imports: ["vue"],

      // Custom resolvers for complex cases:
      resolvers: [
        // Auto-import from a UI library:
        (name) => {
          if (name.startsWith("El"))
            return { name, from: "element-plus" }
        },
      ],

      // Ignore specific auto-imports:
      ignore: ["useFetch"],

      // Transform options:
      include: [
        /\.[tj]sx?$/,  // .ts, .tsx, .js, .jsx
        /\.vue$/,
        /\.vue\?vue/,
      ],
    }),
  ],
})

VueUse preset

import AutoImport from "unplugin-auto-import/vite"

export default defineConfig({
  plugins: [
    AutoImport({
      imports: [
        "vue",
        "@vueuse/core",
        "@vueuse/head",
      ],
      dts: true,
    }),
  ],
})

// All VueUse composables available without imports:
const { x, y } = useMouse()
const isDark = useDark()
const { copy } = useClipboard()
const { isFullscreen, toggle } = useFullscreen()

babel-plugin-auto-import

babel-plugin-auto-import — Babel-based auto-import:

Basic setup

// babel.config.json
{
  "plugins": [
    ["auto-import", {
      "declarations": [
        { "default": "React", "path": "react" },
        { "members": ["useState", "useEffect", "useCallback"], "path": "react" },
        { "members": ["useNavigate", "Link"], "path": "react-router-dom" }
      ]
    }]
  ]
}

Usage

// Input (no imports):
function App() {
  const [count, setCount] = useState(0)
  const navigate = useNavigate()
  return <div onClick={() => setCount(count + 1)}>{count}</div>
}

// Babel transforms to:
import React, { useState } from "react"
import { useNavigate } from "react-router-dom"

function App() {
  const [count, setCount] = useState(0)
  const navigate = useNavigate()
  return <div onClick={() => setCount(count + 1)}>{count}</div>
}

Limitations

babel-plugin-auto-import:
  ✅ Works with any Babel setup
  ✅ Simple configuration
  ✅ No build tool dependency

  ❌ No directory scanning
  ❌ No TypeScript declarations
  ❌ No presets — must list every import manually
  ❌ No ESLint integration
  ❌ Babel-only — doesn't work with esbuild/SWC
  ❌ Not actively maintained

For most projects: use unplugin-auto-import instead

Feature Comparison

Featureunimportunplugin-auto-importbabel-plugin-auto-import
Build tool supportProgrammaticVite, Webpack, Rollup, esbuildBabel only
PresetsVue, React, Svelte, etc.Vue, React, Svelte, VueUse, etc.❌ (manual)
Directory scanning
TypeScript .d.ts
ESLint config
Custom resolvers
Framework useNuxt corePlugin for any projectBabel projects
API levelLow-level engineBuild pluginBabel transform
Weekly downloads~5M~3M~50K

When to Use Each

Use unimport if:

  • Building a framework with Nuxt-like auto-import DX
  • Need a programmatic auto-import engine
  • Want full control over import injection and scanning
  • Building custom tooling that needs import resolution

Use unplugin-auto-import if:

  • Want auto-imports in your Vite, Webpack, or Rollup project
  • Need presets for Vue, React, VueUse, etc.
  • Want TypeScript declarations and ESLint config generated
  • Building an app (not a framework)

Use babel-plugin-auto-import if:

  • Stuck with a Babel-only build pipeline
  • Need simple identifier-to-import mapping
  • Can't use build plugins (legacy setup)

Methodology

Download data from npm registry (weekly average, February 2026). Feature comparison based on unimport v3.x, unplugin-auto-import v0.18.x, and babel-plugin-auto-import v1.x.

Compare auto-import tools and developer utilities on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.