
Research
/Security News
Miasma Mini Shai-Hulud Hits ImmobiliareLabs npm Packages
Miasma Mini Shai-Hulud hits @immobiliarelabs Backstage plugins, targeting GitLab and LDAP auth packages on npm.
@shined/babel-plugin-transform-import-declaration
Advanced tools
A Babel plugin to transform import declarations for tree-shaking and on-demand loading
一个 Babel 插件,用于转换 JavaScript/TypeScript 模块导入声明,实现按需加载和 Tree Shaking,有效减小打包体积。
npm install --save-dev @shined/babel-plugin-transform-import-declaration
# 或
pnpm add -D @shined/babel-plugin-transform-import-declaration
# 或
yarn add -D @shined/babel-plugin-transform-import-declaration
在 .babelrc 或 babel.config.js 中配置:
{
"plugins": [
[
"@shined/babel-plugin-transform-import-declaration",
{
"config": [
{
"source": "antd",
"filename": "kebabCase",
"output": ["antd/es/{{ filename }}/index.js"]
}
]
}
]
]
}
输入:
import { Button, DatePicker } from 'antd';
输出:
import Button from 'antd/es/button/index.js';
import DatePicker from 'antd/es/date-picker/index.js';
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
source | string | 是 | - | 要转换的源模块名称 |
filename | FilenameCase | 否 | "camelCase" | 文件名转换规则 |
output | string[] | 是 | - | 输出路径模板数组。第一个元素生成主导入(带标识符),后续元素生成副作用导入(如样式文件) |
specifier | SpecifierType | 否 | "default" | 导入说明符类型 |
include | string[] | 否 | - | 只处理指定的组件名称(白名单) |
exclude | string[] | 否 | - | 排除指定的组件名称(黑名单) |
注意:
filename 默认为 camelCase,如果不指定会将 DatePicker 转换为 datePickerinclude 和 exclude 互斥,不能同时使用output 是一个字符串数组,用于定义生成的导入语句:
第一个元素(必需): 生成主导入语句,包含导入标识符
// output[0]: "antd/es/{{ filename }}/index.js"
import Button from "antd/es/button/index.js"; // 带标识符 Button
后续元素(可选): 生成副作用导入语句,不包含标识符,通常用于导入样式文件
// output[1]: "antd/es/{{ filename }}/style/index.css"
import "antd/es/button/style/index.css"; // 无标识符,仅导入副作用
⚠️ 重要: 数组顺序非常重要!第一个必须是组件路径,样式文件必须放在后面。
| 值 | 说明 | 转换示例 |
|---|---|---|
kebabCase | 小写字母,用连字符分隔 | Button → button, DatePicker → date-picker |
camelCase | 驼峰命名,首字母小写 | Button → button, DatePicker → datePicker |
snakeCase | 小写字母,用下划线分隔 | Button → button, DatePicker → date_picker |
pascalCase | 帕斯卡命名,首字母大写 | Button → Button, DatePicker → DatePicker |
| 值 | 生成的导入语句 | 使用场景 |
|---|---|---|
default | import Button from "path" | 模块使用 export default 导出 |
named | import { Button } from "path" | 模块使用 export { Button } 导出 |
namespace | import * as Button from "path" | 导入整个模块作为对象 |
最简单的用法,将命名导入转换为默认导入。
// 配置
{
"source": "antd",
"filename": "kebabCase",
"output": ["antd/es/{{ filename }}/index.js"]
}
// 转换前
import { Button } from "antd";
// 转换后 👇
import Button from "antd/es/button/index.js";
除了组件,还可以自动导入对应的样式文件。
// 配置
{
"source": "antd",
"filename": "kebabCase",
"output": [
"antd/es/{{ filename }}/index.js",
"antd/es/{{ filename }}/style/index.css"
]
}
// 转换前
import { Button } from "antd";
// 转换后 👇
import Button from "antd/es/button/index.js";
import "antd/es/button/style/index.css";
使用 exclude 排除不需要转换的组件。
// 配置
{
"source": "antd",
"filename": "kebabCase",
"output": ["antd/es/{{ filename }}/index.js"],
"exclude": ["Button"]
}
// 转换前
import { Button, DatePicker } from "antd";
// 转换后 👇
import { Button } from "antd"; // Button 被排除,保持原样
import DatePicker from "antd/es/date-picker/index.js";
使用 include 只处理指定的组件。
// 配置
{
"source": "antd",
"filename": "kebabCase",
"output": ["antd/es/{{ filename }}/index.js"],
"include": ["Button", "Input"]
}
// 转换前
import { Button, DatePicker, Input } from "antd";
// 转换后 👇
import Button from "antd/es/button/index.js";
import Input from "antd/es/input/index.js";
import { DatePicker } from "antd"; // DatePicker 不在 include 中,保持原样
不同的组件可以使用不同的转换规则。
// 配置
{
"config": [
{
"source": "antd",
"filename": "kebabCase",
"output": [
"antd/es/{{ filename }}/index.js",
"antd/es/{{ filename }}/style/index.css"
],
"exclude": ["Button"]
},
{
"source": "antd",
"filename": "kebabCase",
"output": [
"antd/es/{{ filename }}/index.js",
"antd/es/{{ filename }}/style/index.less"
],
"include": ["Button"]
}
]
}
// 转换前
import { Button, DatePicker } from "antd";
// 转换后 👇
import DatePicker from "antd/es/date-picker/index.js";
import "antd/es/date-picker/style/index.css"; // 使用第一个规则
import Button from "antd/es/button/index.js";
import "antd/es/button/style/index.less"; // 使用第二个规则
// 配置
{
"source": "antd",
"filename": "kebabCase",
"specifier": "default",
"output": ["antd/es/{{ filename }}/index.js"]
}
// 转换前
import { Button } from "antd";
// 转换后 👇
import Button from "antd/es/button/index.js";
// 配置
{
"source": "lodash",
"filename": "kebabCase",
"specifier": "named",
"output": ["lodash/{{ filename }}.js"]
}
// 转换前
import { debounce } from "lodash";
// 转换后 👇
import { debounce } from "lodash/debounce.js";
// 配置
{
"source": "utils",
"filename": "camelCase",
"specifier": "namespace",
"output": ["utils/{{ filename }}.js"]
}
// 转换前
import { DateUtils } from "utils";
// 转换后 👇
import * as DateUtils from "utils/dateUtils.js";
// kebabCase
{
"filename": "kebabCase",
"output": ["lib/{{ filename }}.js"]
}
// DatePicker → lib/date-picker.js
// camelCase
{
"filename": "camelCase",
"output": ["lib/{{ filename }}.js"]
}
// DatePicker → lib/datePicker.js
// snakeCase
{
"filename": "snakeCase",
"output": ["lib/{{ filename }}.js"]
}
// DatePicker → lib/date_picker.js
// pascalCase
{
"filename": "pascalCase",
"output": ["lib/{{ filename }}.js"]
}
// DatePicker → lib/DatePicker.js
{
"plugins": [
[
"@shined/babel-plugin-transform-import-declaration",
{
"config": [
{
"source": "antd",
"filename": "kebabCase",
"output": [
"antd/es/{{ filename }}/index.js",
"antd/es/{{ filename }}/style/index.css"
]
}
]
}
]
]
}
效果:
// 开发时写法
import { Button, Table, Form } from 'antd';
// 自动转换为
import Button from 'antd/es/button/index.js';
import 'antd/es/button/style/index.css';
import Table from 'antd/es/table/index.js';
import 'antd/es/table/style/index.css';
import Form from 'antd/es/form/index.js';
import 'antd/es/form/style/index.css';
{
"source": "lodash",
"filename": "camelCase",
"specifier": "default",
"output": ["lodash/{{ filename }}.js"]
}
效果:
// 开发时写法
import { debounce, throttle, cloneDeep } from 'lodash';
// 自动转换为
import debounce from 'lodash/debounce.js';
import throttle from 'lodash/throttle.js';
import cloneDeep from 'lodash/cloneDeep.js';
{
"source": "element-plus",
"filename": "kebabCase",
"output": [
"element-plus/es/components/{{ filename }}/index.js",
"element-plus/es/components/{{ filename }}/style/index.css"
]
}
效果:
// 开发时写法
import { ElButton, ElTable } from 'element-plus';
// 自动转换为
import ElButton from 'element-plus/es/components/el-button/index.js';
import 'element-plus/es/components/el-button/style/index.css';
import ElTable from 'element-plus/es/components/el-table/index.js';
import 'element-plus/es/components/el-table/style/index.css';
本插件完全支持 TypeScript,会自动跳过类型导入:
// 这些不会被转换
import type { ButtonProps } from 'antd';
import { type InputProps, Button } from 'antd';
// 只有 Button 会被转换
A: ⚠️ 不可以! output 数组必须至少包含一个元素,否则插件会在启动时抛出错误。
❌ 错误配置:
{
"source": "antd",
"filename": "kebabCase",
"output": [] // ❌ 空数组会导致错误!
}
错误信息:
Config #0 (source: 'antd'): 'output' must be a non-empty array.
The 'output' array defines the import paths to generate:
- First element: main import (with identifier)
- Remaining elements: side-effect imports (e.g., styles)
✅ 正确配置:
{
"source": "antd",
"filename": "kebabCase",
"output": ["antd/es/{{ filename }}/index.js"] // ✅ 至少一个元素
}
A: ⚠️ 非常重要! output 数组的顺序决定了生成的导入类型:
❌ 错误配置:
{
"output": [
"antd/es/{{ filename }}/style/index.css", // ❌ 样式不应该在第一个!
"antd/es/{{ filename }}/index.js"
]
}
✅ 正确配置:
{
"output": [
"antd/es/{{ filename }}/index.js", // ✅ 组件在第一个
"antd/es/{{ filename }}/style/index.css" // ✅ 样式在后面
]
}
A: 不可以,include 和 exclude 是互斥的,只能使用其中一个。
A: 支持。插件只关心 source 字段匹配,之后的路径转换由你的构建工具(Webpack/Rspack)的别名配置处理。
A: 不会。插件会自动识别并跳过类型导入(import type 或 type 关键字)。
不使用插件:
import { Button } from 'antd'; // 可能导入整个库(~2MB+)
使用插件后:
import Button from 'antd/es/button/index.js'; // 只导入 Button(~50KB)
# 安装依赖
pnpm install
# 运行测试
pnpm test
# 监听模式
pnpm test:watch
# 构建
pnpm build
# 开发模式
pnpm dev
本插件包含完整的测试:
所有 22 个测试全部通过 ✅
如果你追求更高的性能,可以考虑使用 SWC 版本:
MIT
ityuany
欢迎提交 Issue 和 Pull Request!
如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!
FAQs
A Babel plugin to transform import declarations for tree-shaking and on-demand loading
We found that @shined/babel-plugin-transform-import-declaration demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Miasma Mini Shai-Hulud hits @immobiliarelabs Backstage plugins, targeting GitLab and LDAP auth packages on npm.

Security News
Rolldown paused Rust React Compiler integration after a 5MB binary size increase raised concerns about shipping React-specific code to all Vite users.

Security News
/Research
Mini Shai-Hulud expands into the Go ecosystem after hitting LeoPlatform npm packages and targeting GitHub Actions workflows.