《Tree-Shaking进阶秘法——从入门到飞升》

6 阅读3分钟

文/ 天机阁首席剪枝师

(菩提树下,青衣道人手持金剪,周身环绕着无数代码枝叶)

"今日传授尔等Tree-Shaking剪枝大法。须知前端修行,如同培育灵树,枝叶繁茂固然可喜,但冗余枝叶过多,反会拖累修行进度。且看这株代码灵树——"


第一章:Tree-Shaking的境界

凝气期(基础剪枝)

// 灵树初成,需剪去明显枯枝
import { unUsedFunction } from 'old-library'; // 枯枝
import { usedFunction } from 'new-library';  // 生机

export function main() {
  usedFunction(); // 保留
  // unUsedFunction(); // 剪除
}

筑基期(深度剪枝)

// 识别嵌套枝叶
import { map, filter } from 'lodash-es'; // 按需引入

const result = [1, 2, 3]
  .map(x => x * 2)    // 保留
  .filter(x => x > 3) // 保留
  // .reduce()        // 剪除

元婴期(动态剪枝)

// 识别条件分支
if (process.env.NODE_ENV === 'production') {
  require('./prod-only'); // 生产环境保留
} else {
  require('./dev-only');  // 开发环境保留
}

第二章:剪枝七式

第一式:开枝散叶(项目初始化)

mkdir tree-shaking-demo
cd tree-shaking-demo
npm init -y
npm install webpack webpack-cli --save-dev

第二式:识别灵根(配置webpack)

// webpack.config.js
module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true, // 识别使用枝叶
    minimize: true,    // 压缩灵气
    sideEffects: true  // 识别副作用
  }
};

第三式:净化灵气(package.json)

{
  "sideEffects": [
    "*.css",  // 保留样式
    "*.scss",
    "!*.js"   // 其他文件启用剪枝
  ]
}

第四式:注入生机(Babel配置)

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      modules: false // 保持ES模块结构
    }]
  ]
};

第五式:天眼通(分析工具)

npm install webpack-bundle-analyzer --save-dev
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
  .BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin() // 开启天眼
  ]
};

第六式:金剪诀(自定义剪枝)

// custom-shaking-plugin.js
class CustomShakingPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('CustomShaking', (compilation) => {
      compilation.hooks.optimizeChunks.tap('CustomShaking', (chunks) => {
        chunks.forEach(chunk => {
          chunk.modulesIterable.forEach(module => {
            if (module.resource && module.resource.includes('unused')) {
              compilation.chunkGraph.disconnectChunkAndModule(chunk, module);
            }
          });
        });
      });
    });
  }
}

第七式:渡劫飞升(持续优化)

# 使用最新工具链
npm install terser-webpack-plugin --save-dev

# 配置高级压缩
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            pure_funcs: ['console.log'], // 移除调试代码
            dead_code: true             // 移除死代码
          }
        }
      })
    ]
  }
};

第三章:剪枝心法

"剪枝五要:
1️⃣ 使用ES模块(import/export)
2️⃣ 标记副作用(sideEffects)
3️⃣ 避免动态导入(eval/new Function)
4️⃣ 保持引用透明(纯函数优先)
5️⃣ 慎用全局变量(污染作用域)"

第四章:实战演练

基础剪枝

// 正确示例
import { used } from 'library';

// 错误示例
import * as all from 'library'; // 引入全树

高级剪枝

// 按需加载
const LazyComponent = React.lazy(() => import('./LazyComponent'));

// 条件加载
if (featureFlag) {
  import('./feature').then(module => {
    module.enableFeature();
  });
}

第五章:剪枝禁忌

魔道案例

// 错误:动态属性访问
const utils = require('utils');
const method = 'unUsedMethod';
utils[method](); // 无法静态分析

// 错误:副作用污染
window.globalVar = '污染全局';

正道解法

// 正确:静态引用
import { usedMethod } from 'utils';
usedMethod();

// 正确:纯函数
function pureFunction(input) {
  return input * 2; // 无副作用
}

(突然,灵树剧烈摇晃,枝叶纷纷坠落)

弟子:"师尊!我的Tree-Shaking失效了!"

道人:"痴儿!定是使用了CommonJS模块,导致无法静态分析。且看这招——"

道人挥动金剪,虚空中浮现代码:

// 将CommonJS转为ES模块
import { createRequire } from 'module';
const require = createRequire(import.meta.url);

// 使用动态import
import('cjs-module').then(module => {
  module.default();
});

飞升天象:

当Tree-Shaking修炼至大乘期,可:

  • 识别深层嵌套引用
  • 消除跨模块副作用
  • 预计算常量表达式
  • 内联小型函数

(道人化作万千金剪,虚空中浮现最后箴言)

"记住,Tree-Shaking之道在于'静中求动'。如同园丁不会盲目剪枝,而是通过静态分析让代码自然精简......"

(菩提树绽放金光,飘落一片金叶:《Tree-Shaking进阶秘法——从入门到飞升》)