Unified utils for auto importing APIs in modules.
682
stars
684
commits
TypeScript
primary language
Sep 10, 2026
updated
Unified utils for auto importing APIs in modules, used in nuxt and unplugin-auto-import
# npm
npm install unimport
# yarn
yarn add unimport
# pnpm
pnpm install unimport
Powered by unplugin, unimport provides a plugin interface for bundlers.
// vite.config.js / rollup.config.js
import Unimport from 'unimport/unplugin'
export default {
plugins: [
Unimport.vite({ /* plugin options */ })
]
}
// webpack.config.js
import Unimport from 'unimport/unplugin'
module.exports = {
plugins: [
Unimport.webpack({ /* plugin options */ })
]
}
// ESM
import { createUnimport } from 'unimport'
// CommonJS
const { createUnimport } = require('unimport')
const { injectImports } = createUnimport({
imports: [{ name: 'fooBar', from: 'test-id' }]
})
// { code: "import { fooBar } from 'test-id';console.log(fooBar())" }
console.log(injectImports('console.log(fooBar())'))
imports: [
{ name: 'ref', from: 'vue' },
{ name: 'useState', as: 'useSignal', from: 'react' },
]
Will be injected as:
import { useState as useSignal } from 'react'
import { ref } from 'vue'
imports: [
{ name: 'default', as: '_', from: 'lodash' }
]
Will be injected as:
import _ from 'lodash'
imports: [
{ name: '*', as: '_', from: 'lodash' }
]
Will be injected as:
import * as _ from 'lodash'
This is a special case for libraries authored with TypeScript's export = syntax. You don't need it the most of the time.
imports: [
{ name: '=', as: 'browser', from: 'webextension-polyfill' }
]
Will be injected as:
import browser from 'webextension-polyfill'
And the type declaration will be added as:
const browser: typeof import('webextension-polyfill')
Presets are provided as a shorthand for declaring imports from the same package:
presets: [
{
from: 'vue',
imports: [
'ref',
'reactive',
// ...
]
}
]
Will be equivalent as:
imports: [
{ name: 'ref', from: 'vue' },
{ name: 'reactive', from: 'vue' },
// ...
]
unimport also provides some built-in presets for common libraries:
presets: [
'vue',
'pinia',
'vue-i18n',
// ...
]
You can check out src/presets for all the options available or refer to the type declaration.
Since unimport v0.7.0, we also support auto scanning the examples from a local installed package, for example:
presets: [
{
package: 'h3',
ignore: ['isStream', /^[A-Z]/, /^[a-z]*$/, r => r.length > 8]
}
]
This will be expanded into:
imports: [
{
from: 'h3',
name: 'appendHeader',
},
{
from: 'h3',
name: 'appendHeaders',
},
{
from: 'h3',
name: 'appendResponseHeader',
},
// ...
]
The ignore option is used to filter out the exports, it can be a string, regex or a function that returns a boolean.
By default, the result is strongly cached by the version of the package. You can disable this by setting cache: false.
Unimport.vite({
dts: true // or a path to generated file
})
Unimport.vite({
dirs: [
'./composables/*',
]
})
Scan for modules under ./composables and auto-import the named exports.
Unimport.vite({
dirs: [
'./composables/**/*',
{
glob: './composables/nested/**/*',
types: false // disable scan the type declarations
}
]
})
Named exports for modules under ./composables/**/* will be registered for auto imports, and filter out the types in ./composables/nested/**/*.
You can also provide custom options for directory scan, for example:
Unimport.vite({
dirsScanOptions: {
filePatterns: ['*.ts'], // optional, default `['*.{ts,js,mjs,cjs,mts,cts}']`, glob patterns for matching files
fileFilter: file => file.endsWith('.ts'), // optional, default `() => true`, filter files
types: true, // optional, default `true`, enable/disable scan the type declarations
cwd: process.cwd(), // optional, default `process.cwd()`, custom cwd for directory scan
},
dirs: [
'./composables/**/*',
{
glob: './composables/nested/**/*',
types: false
}
]
})
You can opt-out auto-import for specific modules by adding a comment:
// @unimport-disable
It can be customized by setting commentsDisable:
Unimport.vite({
commentsDisable: [
'@unimport-disable',
'@custom-imports-disable',
]
})
By default, unimport uses RegExp to detect unimport entries. In some cases, RegExp might not be able to detect all the entries (false positive & false negative).
For a more accurate result, you can switch to an AST-based parser:
acorn — powered by acorn. Assumes the input is valid vanilla JavaScript, so it should usually be used after transformations and transpilation.oxc — powered by oxc-parser. Much faster than acorn and accepts TypeScript and JSX. Requires installing either rolldown or oxc-parser as an optional peer dependency. (If both are installed, rolldown is preferred.)Unimport.vite({
parser: 'oxc' // or 'acorn' or 'regex' (default)
})
To use the oxc parser, install rolldown or oxc-parser alongside unimport:
npm install rolldown
# or
npm install oxc-parser
In Vue's template, the usage of API is in a different context than plain modules. Thus some custom transformations are required. To enable it, set addons.vueTemplate to true:
Unimport.vite({
addons: {
vueTemplate: true
}
})
When auto-import a ref, inline operations won't be auto-unwrapped.
export const counter = ref(0)
<template>
<!-- this is ok -->
<div>{{ counter }}</div>
<!-- counter here is a ref, this won't work, volar will throw -->
<div>{{ counter + 1 }}</div>
<!-- use this instead -->
<div>{{ counter.value + 1 }}</div>
</template>
We recommend using Volar for type checking, which will help you to identify the misusage.
In Vue's template, the usage of directives is in a different context than plain modules. Thus some custom transformations are required. To enable it, set addons.vueDirectives to true:
Unimport.vite({
addons: {
vueDirectives: true
}
})
When including directives in your presets, you should:
meta.vueDirective set to true, otherwise, unimport will not be able to detect your directives.as in the Import.dtsDisabled to true if you provide a type declaration for your directives.import type { InlinePreset } from 'unimport'
import { defineUnimportPreset } from 'unimport'
export const composables = defineUnimportPreset({
from: 'my-unimport-library/composables',
/* imports and other options */
})
export const directives = defineUnimportPreset({
from: 'my-unimport-library/directives',
// disable dts generation globally
dtsEnabled: false,
// you can declare the vue directive globally
meta: {
vueDirective: true
},
imports: [{
name: 'ClickOutside',
// disable dts generation per import
dtsEnabled: false,
// you can declare the vue directive per import
meta: {
vueDirective: true
}
}, {
name: 'default',
// you should declare `as` for default exports
as: 'Focus'
}]
})
If you add a directory scan for your local directives in the project, you need to:
isDirective in the vueDirectives: unimport will use it to detect them (will never be called for imports with meta.vueDirective set to true).Unimport.vite({
dirs: ['./directives/**'],
addons: {
vueDirectives: {
isDirective: (normalizedImportFrom, _importEntry) => {
return normalizedImportFrom.includes('/directives/')
}
}
}
})
corepack enable (use npm i -g corepack for Node.js < 16.10)pnpm installpnpm devMade with 💛
Published under MIT License.
(top 30 of 64)
TypeScript
95.2%
JavaScript
3.8%
Unified utils for auto importing APIs in modules.
682
stars
684
commits
TypeScript
primary language
Sep 10, 2026
updated
Unified utils for auto importing APIs in modules, used in nuxt and unplugin-auto-import
# npm
npm install unimport
# yarn
yarn add unimport
# pnpm
pnpm install unimport
Powered by unplugin, unimport provides a plugin interface for bundlers.
// vite.config.js / rollup.config.js
import Unimport from 'unimport/unplugin'
export default {
plugins: [
Unimport.vite({ /* plugin options */ })
]
}
// webpack.config.js
import Unimport from 'unimport/unplugin'
module.exports = {
plugins: [
Unimport.webpack({ /* plugin options */ })
]
}
// ESM
import { createUnimport } from 'unimport'
// CommonJS
const { createUnimport } = require('unimport')
const { injectImports } = createUnimport({
imports: [{ name: 'fooBar', from: 'test-id' }]
})
// { code: "import { fooBar } from 'test-id';console.log(fooBar())" }
console.log(injectImports('console.log(fooBar())'))
imports: [
{ name: 'ref', from: 'vue' },
{ name: 'useState', as: 'useSignal', from: 'react' },
]
Will be injected as:
import { useState as useSignal } from 'react'
import { ref } from 'vue'
imports: [
{ name: 'default', as: '_', from: 'lodash' }
]
Will be injected as:
import _ from 'lodash'
imports: [
{ name: '*', as: '_', from: 'lodash' }
]
Will be injected as:
import * as _ from 'lodash'
This is a special case for libraries authored with TypeScript's export = syntax. You don't need it the most of the time.
imports: [
{ name: '=', as: 'browser', from: 'webextension-polyfill' }
]
Will be injected as:
import browser from 'webextension-polyfill'
And the type declaration will be added as:
const browser: typeof import('webextension-polyfill')
Presets are provided as a shorthand for declaring imports from the same package:
presets: [
{
from: 'vue',
imports: [
'ref',
'reactive',
// ...
]
}
]
Will be equivalent as:
imports: [
{ name: 'ref', from: 'vue' },
{ name: 'reactive', from: 'vue' },
// ...
]
unimport also provides some built-in presets for common libraries:
presets: [
'vue',
'pinia',
'vue-i18n',
// ...
]
You can check out src/presets for all the options available or refer to the type declaration.
Since unimport v0.7.0, we also support auto scanning the examples from a local installed package, for example:
presets: [
{
package: 'h3',
ignore: ['isStream', /^[A-Z]/, /^[a-z]*$/, r => r.length > 8]
}
]
This will be expanded into:
imports: [
{
from: 'h3',
name: 'appendHeader',
},
{
from: 'h3',
name: 'appendHeaders',
},
{
from: 'h3',
name: 'appendResponseHeader',
},
// ...
]
The ignore option is used to filter out the exports, it can be a string, regex or a function that returns a boolean.
By default, the result is strongly cached by the version of the package. You can disable this by setting cache: false.
Unimport.vite({
dts: true // or a path to generated file
})
Unimport.vite({
dirs: [
'./composables/*',
]
})
Scan for modules under ./composables and auto-import the named exports.
Unimport.vite({
dirs: [
'./composables/**/*',
{
glob: './composables/nested/**/*',
types: false // disable scan the type declarations
}
]
})
Named exports for modules under ./composables/**/* will be registered for auto imports, and filter out the types in ./composables/nested/**/*.
You can also provide custom options for directory scan, for example:
Unimport.vite({
dirsScanOptions: {
filePatterns: ['*.ts'], // optional, default `['*.{ts,js,mjs,cjs,mts,cts}']`, glob patterns for matching files
fileFilter: file => file.endsWith('.ts'), // optional, default `() => true`, filter files
types: true, // optional, default `true`, enable/disable scan the type declarations
cwd: process.cwd(), // optional, default `process.cwd()`, custom cwd for directory scan
},
dirs: [
'./composables/**/*',
{
glob: './composables/nested/**/*',
types: false
}
]
})
You can opt-out auto-import for specific modules by adding a comment:
// @unimport-disable
It can be customized by setting commentsDisable:
Unimport.vite({
commentsDisable: [
'@unimport-disable',
'@custom-imports-disable',
]
})
By default, unimport uses RegExp to detect unimport entries. In some cases, RegExp might not be able to detect all the entries (false positive & false negative).
For a more accurate result, you can switch to an AST-based parser:
acorn — powered by acorn. Assumes the input is valid vanilla JavaScript, so it should usually be used after transformations and transpilation.oxc — powered by oxc-parser. Much faster than acorn and accepts TypeScript and JSX. Requires installing either rolldown or oxc-parser as an optional peer dependency. (If both are installed, rolldown is preferred.)Unimport.vite({
parser: 'oxc' // or 'acorn' or 'regex' (default)
})
To use the oxc parser, install rolldown or oxc-parser alongside unimport:
npm install rolldown
# or
npm install oxc-parser
In Vue's template, the usage of API is in a different context than plain modules. Thus some custom transformations are required. To enable it, set addons.vueTemplate to true:
Unimport.vite({
addons: {
vueTemplate: true
}
})
When auto-import a ref, inline operations won't be auto-unwrapped.
export const counter = ref(0)
<template>
<!-- this is ok -->
<div>{{ counter }}</div>
<!-- counter here is a ref, this won't work, volar will throw -->
<div>{{ counter + 1 }}</div>
<!-- use this instead -->
<div>{{ counter.value + 1 }}</div>
</template>
We recommend using Volar for type checking, which will help you to identify the misusage.
In Vue's template, the usage of directives is in a different context than plain modules. Thus some custom transformations are required. To enable it, set addons.vueDirectives to true:
Unimport.vite({
addons: {
vueDirectives: true
}
})
When including directives in your presets, you should:
meta.vueDirective set to true, otherwise, unimport will not be able to detect your directives.as in the Import.dtsDisabled to true if you provide a type declaration for your directives.import type { InlinePreset } from 'unimport'
import { defineUnimportPreset } from 'unimport'
export const composables = defineUnimportPreset({
from: 'my-unimport-library/composables',
/* imports and other options */
})
export const directives = defineUnimportPreset({
from: 'my-unimport-library/directives',
// disable dts generation globally
dtsEnabled: false,
// you can declare the vue directive globally
meta: {
vueDirective: true
},
imports: [{
name: 'ClickOutside',
// disable dts generation per import
dtsEnabled: false,
// you can declare the vue directive per import
meta: {
vueDirective: true
}
}, {
name: 'default',
// you should declare `as` for default exports
as: 'Focus'
}]
})
If you add a directory scan for your local directives in the project, you need to:
isDirective in the vueDirectives: unimport will use it to detect them (will never be called for imports with meta.vueDirective set to true).Unimport.vite({
dirs: ['./directives/**'],
addons: {
vueDirectives: {
isDirective: (normalizedImportFrom, _importEntry) => {
return normalizedImportFrom.includes('/directives/')
}
}
}
})
corepack enable (use npm i -g corepack for Node.js < 16.10)pnpm installpnpm devMade with 💛
Published under MIT License.
(top 30 of 64)
TypeScript
95.2%
JavaScript
3.8%