Frontend Development 11 min read

Managing and Optimizing Import Statements in Frontend Projects

This article explains why import statements can fill an entire file, examines the problems caused by excessive imports, and presents practical techniques such as module re‑export, require.context, dynamic import, webpack ProvidePlugin, Vite plugins, TypeScript namespaces, aliasing, and Babel plugins to keep import sections concise and maintainable.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Managing and Optimizing Import Statements in Frontend Projects

Preface

Seeing a file filled with import statements can be overwhelming and challenges code organization. This article explores why imports dominate a file, the issues they cause, and how to manage them elegantly.

How Do Imports Fill the Screen?

Rejecting Module Re‑export

Module re‑export is widely used in component libraries of major companies. For example, the Arco Design library exposes all components through components/index.tsx , allowing a single import to bring in many components.

// Without re‑export
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'
...

// With re‑export
import { Modal, Checkbox, Message } from '@arco-design/web-react'

Re‑export typically gathers modules of the same type (e.g., components, routes, utils, hooks) into an index.tsx file, simplifying import paths and improving readability and maintainability.

Forms of Re‑export

1. Direct Re‑export

export { foo, bar } from './moduleA';

2. Renamed Re‑export (including default)

// Named re‑export
export { foo as newFoo, bar as newBar } from './moduleA';
// Default re‑export renamed
export { default as ModuleDDefault } from './moduleD';

3. Export Everything (excluding default)

export * from './moduleA';

4. Import Then Re‑export

import { foo, bar } from './moduleA';
export { foo, bar };

Choosing the appropriate form helps build a clearer and more efficient code structure.

Using require.context

require.context enables dynamic import of a group of modules without listing each one, which is especially useful for routing or state‑management files where many pages need to be imported.

// Without require.context
import A from '@/pages/A'
import B from '@/pages/B'
...

// Using require.context in routes/index.ts
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;

Dynamic import()

Dynamic import() can achieve similar functionality to require.context , allowing on‑demand loading of modules.

webpack ProvidePlugin

The webpack.ProvidePlugin automatically injects specified modules (e.g., React, lodash, dayjs) wherever they are used, reducing repetitive import statements.

const webpack = require('webpack');
module.exports = {
  plugins: [
    new webpack.ProvidePlugin({
      React: 'react',
      _: 'lodash',
      dayjs: 'dayjs',
      Utils: path.resolve(__dirname, 'src/utils.js')
    })
  ]
};

While it cleans up code, it does not shrink bundle size because the libraries are still included.

Vite Alternative – vite-plugin-inject

import inject from 'vite-plugin-inject';
export default {
  plugins: [
    inject({
      dayjs: 'dayjs',
      // add other globals here
    })
  ]
};

Massive TypeScript Import Types

Using TypeScript namespaces can eliminate the need to import type definitions explicitly.

// accout.ts
declare namespace IAccount {
  type IList
= {
    count: number;
    list: T[];
  };
  interface IUser {
    id: number;
    name: string;
    avatar: string;
  }
}

// Anywhere without import
const [list, setList] = useState
();
const [user, setUser] = useState
();

Other Practical Tips

1. Configure Webpack/TS Aliases

resolve: {
  alias: {
    "@src": path.resolve(__dirname, 'src/'),
    "@components": path.resolve(__dirname, 'src/components/'),
    "@utils": path.resolve(__dirname, 'src/utils/')
  }
}
// Usage
import MyComponent from '@components/MyComponent';

2. Adjust Prettier printWidth

{
  "printWidth": 120,
  ...
}

3. Dynamically Load Global Components

// Asynchronously load a global modal
Vue.component('IMessage', function (resolve) {
  if (/^\/pagea|pageb/.test(location.pathname)) {
    require.ensure(['./components/message/index.vue'], function() {
      resolve(require('./components/message/index.vue'));
    });
  }
});

4. Use babel-plugin-import for On‑Demand Imports

// .babelrc
{
  "plugins": [
    ["import", {
      "libraryName": "@arco-design/web-react",
      "libraryDirectory": "es",
      "style": true
    }, "@arco-design/web-react"]
  ]
}
// Transformed code
import Button from '@arco-design/web-react/es/button';
import '@arco-design/web-react/es/button/style/css.js';

Conclusion

Various techniques—module re‑export, require.context , dynamic import() , webpack ProvidePlugin, Vite inject plugin, TypeScript namespaces, aliasing, and Babel plugins—can dramatically reduce the visual clutter of import statements and improve code maintainability.

When you think creatively, almost any import‑related problem can be solved.

frontendWebpackcode organization@Importmodule re-export
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.