unimport
Unified utils for auto importing APIs in modules, used in nuxt and unplugin-auto-import
Features
- Auto import register APIs for Vite, Webpack or esbuild powered by unplugin
- TypeScript declaration file generation
- Auto import for custom APIs defined under specific directories
- Auto import for Vue template
Install
npm install unimport
yarn add unimport
pnpm install unimport
Usage
Plugin Usage
Powered by unplugin, unimport
provides a plugin interface for bundlers.
Vite / Rollup
import Unimport from 'unimport/unplugin'
export default {
plugins: [
Unimport.vite({ })
]
}
Webpack
import Unimport from 'unimport/unplugin'
module.exports = {
plugins: [
Unimport.webpack({ })
]
}
Programmatic Usage
import { createUnimport } from 'unimport'
const { createUnimport } = require('unimport')
const { injectImports } = createUnimport({
imports: [{ name: 'fooBar', from: 'test-id' }]
})
console.log(injectImports('console.log(fooBar())'))
Configurations
Imports Item
Named import
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'
Default import
imports: [
{ name: 'default', as: '_', from: 'lodash' }
]
Will be injected as:
import _ from 'lodash'
Namespace import
imports: [
{ name: '*', as: '_', from: 'lodash' }
]
Will be injected as:
import * as _ from 'lodash'
Export assignment import
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')
Custom Presets
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' },
]
Built-in Presets
unimport
also provides some builtin 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.
Exports Auto Scan
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
.
Type Declarations
Unimport.vite({
dts: true
})
Directory Auto Import
Unimport.vite({
dirs: [
'./composables/**/*',
{
glob: './composables/nested/**/*',
types: false
}
]
})
Named exports for modules under ./composables/**/*
will be registered for auto imports, and filter out the types in ./composables/nested/**/*
.
Directory Scan Options
You can also provide custom options for directory scan, for example:
Unimport.vite({
dirsScanOptions: {
filePatterns: ['*.ts'],
fileFilter: file => file.endsWith('.ts'),
types: true,
cwd: process.cwd(),
},
dirs: [
'./composables/**/*',
{
glob: './composables/nested/**/*',
types: false
}
]
})
Opt-out Auto Import
You can opt-out auto-import for specific modules by adding a comment:
It can be customized by setting commentsDisable
:
Unimport.vite({
commentsDisable: [
'@unimport-disable',
'@custom-imports-disable',
]
})
Acorn Parser
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).
We introduced a new AST-based parser powered by acorn, providing a more accurate result. The limitation is when using Acorn, it assumes all input code are valid and vanilla JavaScript code.
Unimport.vite({
parser: 'acorn'
})
Vue Template Auto Import
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
}
})
Caveats
When auto-import a ref, inline operations won't be auto-unwrapped.
export const counter = ref(0)
<template>
<div>{{ counter }}</div>
<div>{{ counter + 1 }}</div>
<div>{{ counter.value + 1 }}</div>
</template>
We recommend using Volar for type checking, which will help you to identify the misusage.
Vue Directives Auto Import and TypeScript Declaration Generation
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
}
})
Library Authors
When including directives in your presets, you should:
- provide the corresponding imports with
meta.vueDirective
set to true
, otherwise, unimport
will not be able to detect your directives. - use named exports for your directives, or use default export and use
as
in the Import. - set
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',
})
export const directives = defineUnimportPreset({
from: 'my-unimport-library/directives',
dtsEnabled: false,
meta: {
vueDirective: true
},
imports: [{
name: 'ClickOutside',
dtsEnabled: false,
meta: {
vueDirective: true
}
}, {
name: 'default',
as: 'Focus'
}]
})
Using Directory Scan and Local Directives
If you add a directory scan for your local directives in the project, you need to:
- provide
isDirective
in the vueDirectives
: unimport
will use it to detect them (will never be called for imports with meta.vueDirective
set to true
). - use always named exports for your directives.
Unimport.vite({
dirs: ['./directives/**'],
addons: {
vueDirectives: {
isDirective: (normalizedImportFrom, _importEntry) => {
return normalizedImportFrom.includes('/directives/')
}
}
}
})
💻 Development
- Clone this repository
- Enable Corepack using
corepack enable
(use npm i -g corepack
for Node.js < 16.10) - Install dependencies using
pnpm install
- Run interactive tests using
pnpm dev
License
Made with 💛
Published under MIT License.