减少打包体积和 tree shaking

Apr-12, 2025 · 2min

motion

https://m.dev/docs/react-reduce-bundle-size#reduce-size

在 motion 库中如何要减少打包的体积,需要使用

import * as m from 'motion/react-m'

来导入 motion 的组件,这样在打包的时候有 tree shaking

解释

foo.ts
function add(a: number, b: number) {
  return a + b
}

function sub(a: number, b: number) {
  return a - b
}

console.log('11111111')
const module = {
  add,
  sub,
}

export default module
index.ts
import foo from './foo'

console.log(foo.add(1, 2))

最终打包产物, 可以看到即使没有使用 sub 函数,也会被打包进去

index.js
// src/foo.ts
function add(a, b) {
  return a + b
}
function sub(a, b) {
  return a - b
}
console.log('11111111')
var module = {
  add,
  sub,
}
var foo_default = module

// src/index.ts
console.log(foo_default.add(1, 2))
//# sourceMappingURL=index.js.map

使用 * as 导入模块

bar.ts
export function add(a: number, b: number) {
  return a + b
}

console.log('111111')
export function sub(a: number, b: number) {
  return a - b
}
index.ts
import * as bar from './bar'

console.log(bar.add(1, 2))

最终打包产物

index.js
// src/bar.ts
function add(a, b) {
  return a + b
}
console.log('111111')

// src/index.ts
console.log(add(1, 2))
//# sourceMappingURL=index.js.map

可以看出使用 * as 导入模块,在打包的时候有 tree shaking, 并且可以识别到 console.log 是副作用

使用 unplugin-auto-import 简化写法

为了避免持续的使用 * as m 没有办法自动导入,可以使用 unplugin-auto-import 来简化写法导入

这是一段 nextjs 的配置

next.config.ts
const nextConfig: NextConfig = {
  output: 'export',
  experimental: {
    reactCompiler: true,
  },
  webpack: (config) => {
    config.plugins.push(
      AutoImport({
        include: [
          /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
        ],
        imports: [
          'react',
          {
            // 自动导入 motion 的组件, 并且可以 tree shaking
            from: 'motion/react-m',
            imports: [['*', 'motion']],
          },
        ],
        dts: true,
      }),
    )

    return config
  },
}
auto-import.d.ts
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
  const motion: typeof import('motion/react-m')
}