swc-plugin-auto-import

SWC plugin for auto importing APIs on-demand, inspired by unplugin-auto-import
2,686
Install
npm install swc-plugin-auto-import
Latest Version:0.0.7
License:MIT
Last Updated:Apr 23, 2026
Links: GitHub  ·  npm
Maintainer: deebl

SWC Auto Import Plugin

An SWC plugin similar to unplugin-auto-import that automatically imports APIs without manually writing import statements.

🚀 Features

  • ✨ Auto import APIs from popular frameworks (Vue, React, Vue Router, etc.)
  • 🎯 Support for custom import configuration
  • 🔍 Smart detection: avoids duplicate imports and local declarations
  • ⚡ Compile-time transformation with zero runtime overhead
  • 🛠️ Native TypeScript support

📦 Installation

npm install swc-plugin-auto-import
# or
yarn add swc-plugin-auto-import
# or
pnpm add swc-plugin-auto-import

🔧 Configuration

Configure in .swcrc

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "swc-plugin-auto-import",
          {
            "imports": [
              "vue",
              "react",
              {
                "@vueuse/core": ["useMouse", "useFetch"]
              },
              {
                "from": "axios",
                "imports": [["default", "axios"]]
              }
            ],
            "debug": false
          }
        ]
      ]
    }
  }
}

Usage with Next.js

// next.config.js
module.exports = {
  experimental: {
    swcPlugins: [
      [
        'swc-plugin-auto-import',
        {
          imports: [
            'react',
            {
              'lodash-es': ['debounce', 'throttle'],
            },
          ],
        },
      ],
    ],
  },
}

Usage with Rspack

// rspack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        loader: 'builtin:swc-loader',
        options: {
          jsc: {
            experimental: {
              plugins: [
                [
                  'swc-plugin-auto-import',
                  {
                    imports: ['react'],
                  },
                ],
              ],
            },
          },
        },
      },
    ],
  },
}

📋 Import Types Summary

The plugin supports four types of imports:

Import Type Mapping Format Explicit Format Generated Code
Named "ref" { "name": "ref", "from": "vue" } import { ref } from 'vue'
Named with Alias ["useFetch", "useMyFetch"] { "name": "useFetch", "as": "useMyFetch", "from": "@vueuse/core" } import { useFetch as useMyFetch } from '@vueuse/core'
Default ["default", "axios"] { "name": "default", "as": "axios", "from": "axios" } import axios from 'axios'
Namespace ["*", "_"] { "name": "*", "as": "_", "from": "lodash" } import * as _ from 'lodash'

📖 Usage Examples

Vue 3 Auto Import

Configuration:

{
  "imports": ["vue"]
}

Input:

const count = ref(0)
const doubled = computed(() => count.value * 2)

onMounted(() => {
  console.log('Component mounted')
})

Output:

import { ref, computed, onMounted } from 'vue'

const count = ref(0)
const doubled = computed(() => count.value * 2)

onMounted(() => {
  console.log('Component mounted')
})

React Hooks Auto Import

Configuration:

{
  "imports": ["react"]
}

Input:

const [count, setCount] = useState(0)

useEffect(() => {
  console.log(count)
}, [count])

Output:

import { useState, useEffect } from 'react'

const [count, setCount] = useState(0)

useEffect(() => {
  console.log(count)
}, [count])

Custom Library Import

Configuration (using package mapping):

{
  "imports": [
    {
      "@vueuse/core": ["useMouse", "useKeyboard"]
    },
    {
      "lodash-es": ["debounce", "throttle"]
    }
  ]
}

Configuration (using explicit import array):

{
  "imports": [
    [
      { "name": "useMouse", "from": "@vueuse/core" },
      { "name": "useKeyboard", "from": "@vueuse/core" },
      { "name": "debounce", "from": "lodash-es" },
      { "name": "throttle", "from": "lodash-es" },
      { "name": "default", "as": "axios", "from": "axios" }
    ]
  ]
}

Input:

const { x, y } = useMouse()
const debouncedFn = debounce(() => {}, 300)

axios.get('/api/data')

Output:

import { useMouse } from '@vueuse/core'
import axios from 'axios'
import { debounce } from 'lodash-es'

const { x, y } = useMouse()
const debouncedFn = debounce(() => {}, 300)

axios.get('/api/data')

⚙️ Configuration Options

imports

Type: Arrayable<ImportsMap | PresetName | InlinePreset>
Default: undefined

Where:

  • Arrayable<T> = T | Array<T> - Can be a single value or an array
  • ImportsMap - Object mapping packages to their exports
  • PresetName - String like "react", "vue", etc.
  • InlinePreset - Object with from and imports fields

Import configuration. Supports multiple formats:

1. Preset String (Built-in presets)
{
  "imports": "react"
}

Or as an array:

{
  "imports": ["vue", "react", "vue-router", "react-router"]
}

Currently supported presets:

  • "vue" - Vue 3 Composition API
  • "react" - React Hooks
  • "react-dom" - React DOM APIs
  • "vue-router" - Vue Router Composition API
  • "react-router" - React Router Hooks
2. ImportsMap - Package Mapping Object

A simplified syntax for defining imports. Each key is a package name, and the value is an array of imports.

{
  "imports": {
    "package-name": [
      "namedExport",
      ["exportName", "alias"],
      ["default", "defaultName"],
      ["*", "namespace"]
    ]
  }
}

Example:

{
  "imports": {
    "@vueuse/core": ["useMouse", ["useFetch", "useMyFetch"]],
    "axios": [["default", "axios"]],
    "lodash": [["*", "_"]]
  }
}

Generated imports:

import { useFetch as useMyFetch, useMouse } from '@vueuse/core'
import axios from 'axios'
import * as _ from 'lodash'

Format explanation:

  • Named import: "useMouse" → import { useMouse } from '@vueuse/core'
  • Named import with alias: ["useFetch", "useMyFetch"] → import { useFetch as useMyFetch } from '@vueuse/core'
  • Default import: ["default", "axios"] → import axios from 'axios'
  • Namespace import: ["*", "_"] → import * as _ from 'lodash'
3. InlinePreset - Inline Import Configuration

An object with from field specifying the module and imports array:

{
  "imports": {
    "from": "react",
    "imports": ["useState", "useEffect", ["useMemo", "useMemoized"]]
  }
}

Generated imports:

import { useEffect, useMemo as useMemoized, useState } from 'react'

The imports array can contain:

  • String: "useState" - simple named import
  • Tuple: ["useMemo", "useMemoized"] - named import with alias
  • Object: { "name": "useEffect", "as": "useReactEffect" } - named import with optional alias
  • Nested InlinePreset: Another InlinePreset object for grouping

Example with nested presets:

{
  "imports": {
    "from": "react",
    "imports": [
      "useState",
      {
        "from": "react-dom",
        "imports": ["createPortal", "flushSync"]
      }
    ]
  }
}

Generated imports:

import { useState } from 'react'
import { createPortal, flushSync } from 'react-dom'
4. Explicit Import Array (Legacy)

An array of import items where each item specifies the name, optional as (alias), and from (package) fields:

{
  "imports": [
    [
      { "name": "ref", "from": "vue" },
      { "name": "useState", "as": "useSignal", "from": "react" },
      { "name": "default", "as": "_", "from": "lodash" },
      { "name": "*", "as": "lodash", "from": "lodash-es" }
    ]
  ]
}

Generated imports:

import _ from 'lodash'
import * as lodash from 'lodash-es'
import { useState as useSignal } from 'react'
import { ref } from 'vue'

Format explanation:

  • Named import: { "name": "ref", "from": "vue" } → import { ref } from 'vue'
  • Named import with alias: { "name": "useState", "as": "useSignal", "from": "react" } → import { useState as useSignal } from 'react'
  • Default import: { "name": "default", "as": "_", "from": "lodash" } → import _ from 'lodash'
  • Namespace import: { "name": "*", "as": "lodash", "from": "lodash-es" } → import * as lodash from 'lodash-es'
Mixed Format

You can combine all formats in an array:

{
  "imports": [
    "react",
    "react-dom",
    {
      "@vueuse/core": ["useMouse", "useFetch"]
    },
    {
      "from": "axios",
      "imports": [["default", "axios"]]
    },
    [{ "name": "computed", "from": "vue" }]
  ]
}

debug

Type: boolean
Default: false

Enable debug mode (reserved field in current version).

📋 Built-in Presets

Vue Preset

ref, computed, reactive, watch, watchEffect, onMounted, onUnmounted,
onBeforeMount, onBeforeUnmount, onUpdated, onBeforeUpdate, nextTick,
defineComponent, createApp, toRef, toRefs, unref, isRef

React Preset

useState, useEffect, useContext, useReducer, useCallback, useMemo,
useRef, useLayoutEffect, useImperativeHandle

Vue Router Preset

useRouter, useRoute

React Router Preset

useNavigate, useLocation, useParams, useSearchParams

🎯 Smart Features

1. No Duplicate Imports

If an API is already imported, the plugin won't add it again:

// Input
import { ref } from 'vue'
const count = ref(0)

// Output - unchanged
import { ref } from 'vue'
const count = ref(0)

2. No Import for Local Declarations

If an identifier is locally declared, the plugin won't add an import:

// Input
function ref() {
  return 'local ref'
}
const data = ref()

// Output - unchanged, no import added
function ref() {
  return 'local ref'
}
const data = ref()

🔄 Comparison with unplugin-auto-import

Feature unplugin-auto-import swc-auto-import
Runtime Vite/Webpack/Rollup SWC Compiler
Performance Fast Very Fast
.d.ts Generation ✅ Planned
TypeScript Support ✅ ✅
Custom Resolvers ✅ Planned
ESLint Integration ✅ Planned

🛠️ Development

Build Plugin

# Build WASM plugin
cargo build-wasip1 --release

# Run tests
cargo test

Project Structure

swc-plugin-auto-import/
├── src/
│   ├── lib.rs          # Plugin source
│   ├── config.rs       # Configuration
│   ├── presets.rs      # Presets
│   ├── collector.rs    # Identifier collector
│   └── visitor.rs      # AST visitor
├── Cargo.toml          # Rust configuration
├── package.json        # npm package config
└── README.md           # Documentation

📝 How It Works

  1. Scanning Phase: Traverse AST to collect used, imported, and declared identifiers
  2. Matching Phase: Find identifiers that need auto-import based on presets and custom config
  3. Filtering Phase: Exclude already imported and locally declared identifiers
  4. Insertion Phase: Insert generated import statements at the top of the module

🤝 Contributing

Issues and Pull Requests are welcome!

📄 License

ISC License

🔗 Links

Related Packages

swc-plugin-vue-jsx

SWC plugin for transforming Vue JSX.

11,721 98
@xieyezi/auto-import

Register global imports on demand for Vite and Webpack

891
unplugin-auto-import

Register global imports on demand for Vite and Webpack

40,166,207 3,799
app-location

A package to avoid repetition with Routes, Links and URLs, and reduce boilerplat...

34,498 19
server-side-render-resource

server side render resource dependence

22,685

Version History

Version Released License
0.0.7 MIT
0.0.5 MIT
0.0.2 MIT
0.0.1 MIT
0.0.0 MIT
Pre-releases (2)
Version Released License
0.0.6-next-16.0.10 MIT
0.0.5-next-16.0.10 MIT