首页 / WXT 浏览器扩展框架教程 / TypeScript 与自动导入

WXT 浏览器扩展框架教程

TypeScript 与自动导入

本教程共 45 篇 · 第 29 篇 · 更新于 2026-08-13 · 约 3 分钟阅读

WXTTypeScripttsconfig自动导入auto-importsunimport路径别名#imports

本节目标:搞懂 WXT 的类型从哪来、路径别名怎么配,再学会自动导入机制的使用、关闭与显式导入。

WXT 是 TypeScript 友好型框架:类型自动生成、别名开箱即用、API 免 import。这一章把它们逐个讲清楚。

wxt prepare:类型从哪来

WXT 会在构建前生成一堆类型文件。执行 wxt prepare 后,项目里会出现 .wxt/tsconfig.json——这是 WXT 生成的基座配置。你根目录的 tsconfig.json 只需要继承它:

// <rootDir>/tsconfig.json
{
  "extends": ".wxt/tsconfig.json"
}

如果是 monorepo,可能不想继承这份配置。那就把生成的声明文件手动引入 TypeScript 项目:

/// <reference path="./.wxt/wxt.d.ts" />
Note

wxt prepare 也是 §06 提到的入口加载机制的一部分,dev/build 命令会自动执行它。手动跑一遍的场景主要是:装完依赖后让编辑器恢复类型提示。

路径别名:不用写一长串相对路径

WXT 默认提供四个别名(§22 已讲过它们在模块导入中的作用,这里看配置层面):

别名指向示例
~~<rootDir>/*import "~~/package.json"
@@<rootDir>/*import "@@/package.json"
~<srcDir>/*import "~/utils/strings"
@<srcDir>/*import "@/utils/strings"

想加自己的别名,别改 tsconfig.json,要用 wxt.config.tsalias 选项:

import { resolve } from 'node:path';

export default defineConfig({
  alias: {
    testing: resolve('utils/testing'), // 目录别名
    strings: resolve('utils/strings.ts'), // 文件别名
  },
});

这样配的好处:下次跑 wxt prepare,别名会同时写进 .wxt/tsconfig.json(让编辑器认识)和打包器(让构建能解析)。两处同步,不会出现「编辑器不报错、构建却找不到」的怪问题。

import { fakeTab } from 'testing/fake-objects';
import { toLowerCase } from 'strings';

自定义编译选项的两条路

想改编译选项,有两条路:

  1. 直接覆盖:在根目录 tsconfig.json 里重写 compilerOptions,比如 "jsx": "preserve"。适合布尔值、单个枚举这类简单设置。
  2. 钩子合并:用 prepare:tsconfig 钩子改生成前的配置对象,适合 pathslib 这种需要「追加」的复杂选项:
export default defineConfig({
  hooks: {
    'prepare:tsconfig': (wxt, { tsconfig }) => {
      tsconfig.compilerOptions.lib.push('WebWorker');
    },
  },
});

为什么需要钩子?因为 tsconfig 的继承机制做不到「给数组追加一项」——子配置写 lib 就直接覆盖了父配置。钩子可以在文件写出前直接改对象,加、删、合并都行。

自动导入:不用 import 就能用

WXT 用 unimport(和 Nuxt 同款工具)实现自动导入(auto-imports)。默认情况下,两样东西会被自动导入:

  • WXT 自己的全部 API,比如 defineContentScriptdefineBackground
  • 项目里四个目录的导出:<srcDir>/components/*<srcDir>/composables/*<srcDir>/hooks/*<srcDir>/utils/*

这些目录里文件的所有具名导出和默认导出,在项目任何地方都能直接用,不用写 import。想看完整清单,跑一次 wxt prepare,然后打开 .wxt/types/imports-module.d.ts

自动导入的配置项通过 imports 字段传给 unimport:

export default defineConfig({
  imports: {
    // unimport 的配置项
  },
});

编辑器与 ESLint

TypeScript 和编辑器要识别自动导入的变量,前提是跑过 wxt prepare。建议把它挂到 postinstall 脚本,装完依赖自动执行:

// package.json
{
  "scripts": {
    "postinstall": "wxt prepare"
  }
}

ESLint 默认不知道这些「凭空出现」的变量。WXT 检测到项目装了 ESLint 时,会自动生成对应的 globals 配置;没自动生成就手动开启:

export default defineConfig({
  imports: {
    eslintrc: {
      enabled: 9, // ESLint >= 9;ESLint <= 8 用 8
    },
  },
});

然后在 ESLint 配置里引入生成的文件:

// eslint.config.mjs(ESLint >= 9)
import autoImports from './.wxt/eslint-auto-imports.mjs';

export default [autoImports];

ESLint 8 及以下则是在 .eslintrc.mjsextends: ['./.wxt/eslintrc-auto-import.json']

不喜欢自动导入?两条退路

自动导入不是强制绑定的。

方式一:整体关闭。

export default defineConfig({
  imports: false,
});

方式二:用 #imports 显式导入。 所有 WXT 的 API 都可以从这个虚拟模块手动引入:

import {
  createShadowRootUi,
  ContentScriptContext,
  MatchPattern,
} from '#imports';

即使没关自动导入,#imports 也能用。它本质上就是自动导入的「显式形态」:同一个来源,一次是隐式全局,一次是显式 import。mkext 这类团队项目为了代码可读性,常用 imports: false 配合 #imports,各入口文件开头一眼就能看出用了哪些 API。

小结

  • 项目继承 .wxt/tsconfig.json@/@@/ 等别名开箱即用。
  • 自动导入免去手写 import,#imports 是它的显式形态,可按团队习惯二选一。
  • ESLint 与类型生成都挂在 wxt prepare 上,装完依赖记得跑。