Webpack之: Tree-shaking

166 阅读2分钟

Tree-shaking 静态分析代码, 把无用代码给删掉 什么才是无用的代码或者永不到的代码?

函数引用类型的TreeShaking

  1. 如果被引用的是一个纯函数, 那么当该纯函数没有被使用引用指针没有被传递下去最终使用 就会被shaking掉
// index.js
import { funcA, funcB } from './util';

const name = funcA();
// funcB 是一个纯函数, 返回 'funcB', 给 a, 但是没有使用a
// 所以会被shaking掉
const a = funcB();

console.log(name);

// util.js
function funcA() {
  return 'AAAAA';
}
function funcB() {
  return '12';
}

export { funcA, funcB };

最终打包之后的结果

(() => {
  'use strict';
  console.log('AAAAA');
})();
// 可以看到我们的funcB 被shaking 

  1. 如果是有副作用的函数, webpack不会shaking掉, 因为副作用函数有可能是不返回, 但是还是修改了外界的值
// index.js
import { funcA, funcB } from './util';

const name = funcA();
const a = funcB();
console.log(name);

// util.js
function funcA() {
  return 'AAAAA';
}
// funcB是一个副作用函数, 他修改了外界的值
// (body.innerText)
function funcB() {
  document.body.innerText = '副作用函数';
  return 'BBBBB';
}

export { funcA, funcB };

打包之后的 dist/main.js:

(() => 
  'use strict';
  (document.body.innerText = '副作用函数'), console.log('AAAAA');
})();

可以看到如果是副作用函数, 如果使用了,那么不管返回值有没有被引用, 都会打包进来

export 方式不同, TreeShaking 不同

export default {
  funcA() {
    return 'AAAAA';
  },
  funcB() {
    document.body.innerText = '副作用'; // 会被打包进去
  },
};

export default {
  funcA() {
    return 'AAAAA';
  },
  funcB() {
    return 'BBB'; // 没有副作用, 如果funcB 没有被引用使用, 就不会被打包进去了
  },
};

打包结果:

(() => {
  'use strict';
  const n = {
    funcA: () => 'AAAAA',
    funcB() {
      document.body.innerText = '123';
    },
  }.funcA();
  console.log(n);
})();
  1. 另一种 export default 方式
// util.js
function funcA() {
  return 'AAAA';
}
// 这种方式的export 不管funcB是否副作用函数, 只要没有调用
// 就不会被打包进去
function funcB() {
  document.body.innerText = '副作用';
}
export default { funcA, funcB };

打包结果:

// 调用了 funcB()
(() => {
  'use strict';
  const n = function () {
      document.body.innerText = '123';
    },
    o = (function () {
      return 'AAAA';
    })();
  n(), console.log(o);
})();

这种方式的export, 只要funcB没有被调用就不会被打包进去

总结分析:

  1. 从两个export default的方式我们可以知道, export default {funcA, funcB} 会export 出两个东西, no;
  2. export default{funcA(){}, funcB(){}}, 会明确export 出一个 default 对象, 里面有两个属性 funcAfuncB, 所以是否会打包进去, 与该属性的函数是否是一个副作用函数有关.