unimport
用于在模块中自动导入 API 的统一工具,用于 nuxt 和 unplugin-auto-import
Features
- 由 unplugin 提供支持,为 Vite、Webpack 或 esbuild 自动导入注册 API
- TypeScript 声明文件生成
- 针对特定目录下定义的自定义 API 的自动导入
- 针对 Vue 模板的自动导入
Install
# npm
npm install unimport
# yarn
yarn add unimport
# pnpm
pnpm install unimport
用法
插件用法
由 unplugin 提供支持,unimport 为打包器提供插件接口。
Vite / Rollup
// vite.config.js / rollup.config.js
import Unimport from 'unimport/unplugin'
export default {
plugins: [
Unimport.vite({ /* plugin options */ })
]
}
Webpack
// 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' },
]
将作为以下内容注入:
import { useState as useSignal } from 'react'
import { ref } from 'vue'
默认导入
imports: [
{ name: 'default', as: '_', from: 'lodash' }
]
将作为以下内容注入:
import _ from 'lodash'
命名空间导入
imports: [
{ name: '*', as: '_', from: 'lodash' }
]
将作为以下形式注入:
import * as _ from 'lodash'
导出赋值导入
这是针对使用 TypeScript 的 export = 语法 编写的库的特殊情况。大多数时候你不需要它。
imports: [
{ name: '=', as: 'browser', from: 'webextension-polyfill' }
]
将作为以下内容注入:
import browser from 'webextension-polyfill'
并且类型声明将添加为:
const browser: typeof import('webextension-polyfill')
自定义预设
预设是声明来自同一包的导入的简写方式:
presets: [
{
from: 'vue',
imports: [
'ref',
'reactive',
// ...
]
}
]
将等同于:
imports: [
{ name: 'ref', from: 'vue' },
{ name: 'reactive', from: 'vue' },
// ...
]
内置预设
unimport 还为常用库提供了一些内置预设:
presets: [
'vue',
'pinia',
'vue-i18n',
// ...
]
您可以查看 src/presets 以了解所有可用选项,或参考类型声明。
Exports Auto Scan
自 unimport v0.7.0 起,我们还支持从本地安装的包中自动扫描示例,例如:
presets: [
{
package: 'h3',
ignore: ['isStream', /^[A-Z]/, /^[a-z]*$/, r => r.length > 8]
}
]
这将扩展为:
imports: [
{
from: 'h3',
name: 'appendHeader',
},
{
from: 'h3',
name: 'appendHeaders',
},
{
from: 'h3',
name: 'appendResponseHeader',
},
// ...
]
ignore 选项用于过滤导出项,它可以是一个字符串、正则表达式或返回布尔值的函数。
默认情况下,结果会根据包的版本进行强缓存。你可以通过设置 cache: false 来禁用此功能。
类型声明
Unimport.vite({
dts: true // or a path to generated file
})
目录自动导入
Unimport.vite({
dirs: [
'./composables/*',
]
})
扫描 ./composables 下的模块并自动导入命名导出。
嵌套目录
Unimport.vite({
dirs: [
'./composables/**/*',
{
glob: './composables/nested/**/*',
types: false // disable scan the type declarations
}
]
})
./composables/**/* 下模块的命名导出将被注册用于自动导入,并过滤掉 ./composables/nested/**/* 中的类型。
目录扫描选项
你也可以为目录扫描提供自定义选项,例如:
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
}
]
})
自动导入的排除
你可以通过添加注释来为特定模块排除自动导入:
// @unimport-disable
可通过设置 commentsDisable 进行自定义:
Unimport.vite({
commentsDisable: [
'@unimport-disable',
'@custom-imports-disable',
]
})
解析器
默认情况下,unimport 使用 RegExp 来检测未导入的条目。在某些情况下,RegExp 可能无法检测所有条目(误报与漏报)。
为了获得更准确的结果,你可以切换到基于 AST 的解析器:
acorn— 由 acorn 提供支持。假设输入是有效的原生 JavaScript,因此通常应在转换和转译之后使用。oxc— 由 oxc-parser 提供支持。比acorn快得多,并且支持 TypeScript 和 JSX。需要安装rolldown或oxc-parser作为可选的 peer dependency。(如果两者都安装了,则优先使用rolldown。)
Unimport.vite({
parser: 'oxc' // or 'acorn' or 'regex' (default)
})
要使用 oxc 解析器,请在 unimport 旁边安装 rolldown 或 oxc-parser:
npm install rolldown
# or
npm install oxc-parser
Vue 模板自动导入
在 Vue 模板中,API 的使用上下文与普通模块不同。因此需要一些自定义转换。要启用此功能,请将 addons.vueTemplate 设置为 true:
Unimport.vite({
addons: {
vueTemplate: true
}
})
注意事项
自动导入 ref 时,内联操作不会被自动解包。
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>
我们建议使用 Volar 进行类型检查,这将帮助您识别误用。
Vue 指令自动导入和 TypeScript 声明生成
在 Vue 模板中,指令的使用上下文与普通模块不同。因此,需要一些自定义转换。要启用此功能,请将 addons.vueDirectives 设置为 true:
Unimport.vite({
addons: {
vueDirectives: true
}
})
库作者
在预设中包含指令时,您应该:
- 提供相应的导入,并将
meta.vueDirective设置为true,否则,unimport将无法检测到您的指令。 - 使用命名导出用于您的指令,或使用默认导出并在 Import 中使用
as。 - 如果您为指令提供了类型声明,请将
dtsDisabled设置为true。
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'
}]
})
使用目录扫描和本地指令
如果你在项目中为本地指令添加了目录扫描,你需要:
- 在
vueDirectives中提供isDirective:unimport将使用它来检测它们(对于meta.vueDirective设置为true的导入,永远不会被调用)。 - 为你的指令始终使用命名导出。
Unimport.vite({
dirs: ['./directives/**'],
addons: {
vueDirectives: {
isDirective: (normalizedImportFrom, _importEntry) => {
return normalizedImportFrom.includes('/directives/')
}
}
}
})
💻 开发
- 克隆此仓库
- 使用
corepack enable启用 Corepack(对于 Node.js < 16.10 请使用npm i -g corepack) - 使用
pnpm install安装依赖 - 使用
pnpm dev运行交互式测试
许可证
用 💛 制作
依据 MIT 许可证 发布。