DEV Community

Cover image for Tree-Shaking Friendly Import/Export Patterns for Modern Frontend Projects
Hoang Nguyen
Hoang Nguyen

Posted on

Tree-Shaking Friendly Import/Export Patterns for Modern Frontend Projects

In modern frontend development, tree shaking is essential for keeping bundles lean. Yet many developers unknowingly break it with subtle mistakes in import and export usage.

Tree shaking is one of the most effective ways to reduce your JavaScript bundle size — but only if your code is written in a way that allows it.

Unfortunately, a few common export and import patterns can silently prevent tree shaking from working at all.

This guide covers the best practices to keep your code tree-shakable in modern frontend stacks (React, Vite, Webpack, etc.).

Use Named Exports Instead of default

Named exports make it easier for bundlers to remove unused code.

// ❌ Not tree-shakable
export default {
  add,
  subtract,
};

// ✅ Tree-shakable
export const add = () => {};
export const subtract = () => {};
Enter fullscreen mode Exit fullscreen mode

Tree shakers like Rollup and Webpack can’t shake off unused properties of a default-exported object.

Avoid Exporting Object Literals

Exporting a single object with all your functions may feel clean, but it bundles everything, even unused parts.

// ❌ Everything in utils is included
export const utils = {
  toDate,
  formatPrice,
};

// ✅ Only what’s used is bundled
export const toDate = () => {};
export const formatPrice = () => {};
Enter fullscreen mode Exit fullscreen mode

Don’t Export Destructured Variables

const config = {
  API_URL: '...',
  TIMEOUT: 3000,
};

// ❌ Not tree-shakable
export const { API_URL, TIMEOUT } = config;

// ✅ Better
export const API_URL = '...';
export const TIMEOUT = 3000;
Enter fullscreen mode Exit fullscreen mode

Destructuring hides the actual bindings from the bundler.

Use Direct Re-exports

// utils/index.js

// ✅ Good
export * from './math';
export * from './date';

// ✅ Even better (explicit)
export { add, subtract } from './math';
Enter fullscreen mode Exit fullscreen mode

Avoid logic-based re-exports or dynamic code.

Avoid Wildcard Imports

// ❌ Not tree-shakable
import * as utils from './utils';

// ✅ Tree-shakable
import { formatDate } from './utils';
Enter fullscreen mode Exit fullscreen mode

Wildcard imports bring in everything — even what you don’t use.

Mark sideEffects: false in package.json

This lets the bundler safely remove unused files/modules.

{
  "sideEffects": false
}
Enter fullscreen mode Exit fullscreen mode

If some files (like CSS) do have side effects, specify them:

{
  "sideEffects": ["./styles/global.css"]
}
Enter fullscreen mode Exit fullscreen mode

Avoid Dynamic Aggregation

// ❌ Cannot be tree-shaken
const all = {
  ...require('./module1'),
  ...require('./module2'),
};

export default all;
Enter fullscreen mode Exit fullscreen mode

Tree shaking only works with static imports/exports that bundlers can analyze at build time.

Final Thoughts

Writing tree-shakable code is about making your modules predictable and explicit. It's not just about saving bytes — it's about better performance, better dev experience, and cleaner architecture.

Your imports and exports are the first line of defense against bloat.

If you're optimizing a large codebase and want to refactor for better tree shaking, start by:

  • Replacing default object exports
  • Flattening utility files
  • Removing wildcard imports
  • Splitting large shared files into named modules

💬 Have more tips? Share them in the comments.

Follow me for more performance tips and frontend architecture insights.

#JavaScript #Frontend #TreeShaking #ESModules #React #Vite #Webpack #TypeScript #CleanCode #WebPerformance

Top comments (0)