向满屏的 Import 语句说再见!
在开发大型项目时,密集的导入语句不仅会影响代码的整洁性,也会让维护工作变得更加复杂。如何优雅地管理这些导入语句,避免“全屏占用”?本文将探讨生成大量导入语句的原因、可能带来的问题,以及如何从多个角度优化和管理导入语句。
拒绝使用模块重新导出
模块重新导出是一种常见的技术,广泛应用于大公司的组件库中,比如 Twitter、字节跳动和谷歌等。
示例:字节跳动的 Arco Design 组件库
在字节跳动的 arco-design 组件库 中,采用模块重新导出可以简化组件的使用:
// 不要使用命名导入
import Modal from '@arco-design/web-react/es/Modal'
import Checkbox from '@arco-design/web-react/es/Checkbox'
import Message from '@arco-design/web-react/es/Message'
// 使用命名导入
import { Modal, Checkbox, Message } from '@arco-design/web-react'
通过 components/index.tsx 重新导出所有组件,简化了导入路径,使得代码更加简洁可读。
重新导出的几种形式
- 直接重新导出:从另一个模块导出特定成员。 - export { foo, bar } from './moduleA';
- 重命名并重新导出:导入后重命名再导出。 - export { foo as newFoo, bar as newBar } from './moduleA'; export { default as ModuleDDefault } from './moduleD';
- 重新导出整个模块(不包括默认导出): - export * from './moduleA';
- 合并导入和重新导出: - import { foo, bar } from './moduleA'; export { foo, bar };
这些方式让我们能够灵活管理模块,提升代码的组织性。
使用 require.context
require.context 是一个强大的工具,能够动态导入模块,尤其适用于项目路由和状态管理等场景。在有大量页面时,这可以减少显式的导入操作:
const routesContext = require.context('./routes', false, /.ts$/);
const routes = [];
routesContext.keys().forEach(modulePath => {
  const route = routesContext(modulePath);
  routes.push(route.default || route);
});
export default routes;
使用动态导入
动态导入可以按需加载模块,有效地减少初始包的大小,提高性能。与 require.context 类似,可以动态打包模块。
对 ProvidePlugin 的谨慎使用
webpack.ProvidePlugin 可以自动为项目提供全局变量,避免每次都导入常用库:
const webpack = require('webpack');
module.exports = {
  plugins: [
    new webpack.ProvidePlugin({
      React: 'react',
      _: 'lodash',
      dayjs: 'dayjs',
    })
  ]
};
虽然 ProvidePlugin 减少了导入操作,但它不能减少打包大小。因此应谨慎使用,只在必要时配置。
大量的 TypeScript 类型导入
在 TS 项目中,大量的类型导入可能使代码显得臃肿。使用 TypeScript 的命名空间可以减少导入量:
// account.ts
declare namespace IAccount {
  type IList<T = IItem> = {
    count: number;
    list: T[];
  };
  interface IUser {
    id: number;
    name: string;
    avatar: string;
  }
}
// 使用时无需导入
const [list, setList] = useState<IAccount.IList | undefined>();
const [user, setUser] = useState<IAccount.IUser | undefined>();
充分利用 Babel 功能
React 17 之前,每个文件都需要显式导入 React。从 17 版本开始,JSX 编译器会自动导入。对于较早版本的 React,可以通过 Babel 自动处理这些导入。
其他技巧
- Webpack 和 TypeScript 别名:通过别名缩短导入路径。 - resolve: { alias: { "@components": path.resolve(__dirname, 'src/components/') } }
- Prettier 的 - printWidth配置:合理的- printWidth(如 120)可以避免过多换行,提升代码的可读性。
- Babel 插件 - babel-plugin-import:按需导入库,减少打包大小。- { "plugins": [ ["import", { "libraryName": "@arco-design/web-react", "libraryDirectory": "es", "style": true }] ] }
总结
大量导入语句常常是复杂项目的难题。通过模块重新导出、动态导入、webpack.ProvidePlugin、TypeScript 命名空间等技术,我们可以大幅减少显式导入,提升代码的整洁性和可维护性。