ITADN
unjs/unimport
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

unimport

npm version npm downloads Codecov

用于在模块中自动导入 API 的统一工具,用于 nuxtunplugin-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。需要安装 rolldownoxc-parser 作为可选的 peer dependency。(如果两者都安装了,则优先使用 rolldown。)
Unimport.vite({
  parser: 'oxc' // or 'acorn' or 'regex' (default)
})

要使用 oxc 解析器,请在 unimport 旁边安装 rolldownoxc-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 中提供 isDirectiveunimport 将使用它来检测它们(对于 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 许可证 发布。