webpack在打包的过程中,借鉴了rollup的tree shaking功能,降低了代码打包体积。之前一直是来自书本的理解,就是es module的静态检查功能使得 tree shaking 成为现实。但是在实际工作中,有一次关于 vconsole 的代码,我发现擦除失败,一直在思考为什么,本着实践出真知的想法,于是今天就写了一点简单的代码测试一下webpack5中tree shaking的一个实际情况。可能存在很多不足,希望大家可以在评论区里面指正。
先贴上webpack的基本配置信息:
// webpack ^5.72.0
// webpack-cli ^4.9.2
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
},
mode: 'production',
};
Es module 导入
Es module 导出
使用export default导出
// 入口文件 index.js
import HW from './helloworld';
document.write(HW.a());
// helloworld.js
function a() {
return 'hello world a';
}
function b() {
return 'hello world b';
}
export default {
a,
b,
};
// bundle.js
(() => {
'use strict';
document.write('hello world a');
})();
结论:function b 被 tree shaking 清除,虽然也可以擦除,但是不推荐这样的导出方式
使用export导出
// 入口文件 index.js
import { a } from './helloworld';
document.write(a());
export function a() {
return 'hello world a';
}
export function b() {
return 'hello world b';
}
(() => {
'use strict';
document.write('hello world a');
})();
结论:function b 被 tree shaking 清除
Commonjs 导出
使用 module.exports 导出
// 入口文件 index.js
import { a } from './helloworld';
document.write(a());
function a() {
return 'hello world a';
}
function b() {
return 'hello world b';
}
module.exports = {
a,
b,
};
(() => {
var r = {
694: r => {
r.exports = {
a: function () {
return 'hello world a';
},
b: function () {
return 'hello world b';
},
};
},
},
e = {};
function t(o) {
var n = e[o];
if (void 0 !== n) return n.exports;
var a = (e[o] = { exports: {} });
return r[o](a, a.exports, t), a.exports;
}
(t.n = r => {
var e = r && r.__esModule ? () => r.default : () => r;
return t.d(e, { a: e }), e;
}),
(t.d = (r, e) => {
for (var o in e) t.o(e, o) && !t.o(r, o) && Object.defineProperty(r, o, { enumerable: !0, get: e[o] });
}),
(t.o = (r, e) => Object.prototype.hasOwnProperty.call(r, e)),
(() => {
'use strict';
var r = t(694);
document.write((0, r.a)());
})();
})();
结论:function b 没有被擦除,tree shaking无效
使用 exports 导出
// 入口文件 index.js
import { a } from './helloworld';
document.write(a());
exports.a = function a() {
return 'hello world a';
};
exports.b = function b() {
return 'hello world b';
};
(() => {
var r = {
694: (r, t) => {
t.a = function () {
return 'hello world a';
};
},
},
t = {};
function e(o) {
var n = t[o];
if (void 0 !== n) return n.exports;
var a = (t[o] = { exports: {} });
return r[o](a, a.exports, e), a.exports;
}
(() => {
'use strict';
var r = e(694);
document.write((0, r.a)());
})();
})();
结论:function b 被 tree shaking 清除,就是看起来打包后的代码啰里啰嗦的
Commonjs 导入
Es module 导出
使用export default导出
// 入口文件 index.js
const HW = require('./helloworld');
document.write(HW.default.a());
// helloworld.js
function a() {
return 'hello world a';
}
function b() {
return 'hello world b';
}
export default {
a,
b,
};
// bundle.js
(() => {
var e = {
694: (e, r, t) => {
'use strict';
t.r(r), t.d(r, { default: () => o });
const o = {
a: function () {
return 'hello world a';
},
b: function () {
return 'hello world b';
},
};
},
},
r = {};
function t(o) {
var n = r[o];
if (void 0 !== n) return n.exports;
var l = (r[o] = { exports: {} });
return e[o](l, l.exports, t), l.exports;
}
(t.d = (e, r) => {
for (var o in r) t.o(r, o) && !t.o(e, o) && Object.defineProperty(e, o, { enumerable: !0, get: r[o] });
}),
(t.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)),
(t.r = e => {
'undefined' != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: 'Module' }),
Object.defineProperty(e, '__esModule', { value: !0 });
}),
(() => {
const e = t(694);
document.write(e.default.a());
})();
})();
结论:function b 没有被擦除,tree shaking无效
使用export导出
// 入口文件 index.js
const HW = require('./helloworld');
document.write(HW.a());
export function a() {
return 'hello world a';
}
export function b() {
return 'hello world b';
}
(() => {
var e = {
694: (e, r, o) => {
'use strict';
function t() {
return 'hello world a';
}
function n() {
return 'hello world b';
}
o.r(r), o.d(r, { a: () => t, b: () => n });
},
},
r = {};
function o(t) {
var n = r[t];
if (void 0 !== n) return n.exports;
var l = (r[t] = { exports: {} });
return e[t](l, l.exports, o), l.exports;
}
(o.d = (e, r) => {
for (var t in r) o.o(r, t) && !o.o(e, t) && Object.defineProperty(e, t, { enumerable: !0, get: r[t] });
}),
(o.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)),
(o.r = e => {
'undefined' != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: 'Module' }),
Object.defineProperty(e, '__esModule', { value: !0 });
}),
(() => {
const e = o(694);
document.write(e.a());
})();
})();
结论:function b 没有被擦除,tree shaking无效
Commonjs 导入
使用 module.exports 导出
// 入口文件 index.js
const HW = require('./helloworld');
document.write(HW.a());
function a() {
return 'hello world a';
}
function b() {
return 'hello world b';
}
module.exports = {
a,
b,
};
(() => {
var r = {
694: r => {
r.exports = {
a: function () {
return 'hello world a';
},
b: function () {
return 'hello world b';
},
};
},
},
o = {};
function t(e) {
var n = o[e];
if (void 0 !== n) return n.exports;
var u = (o[e] = { exports: {} });
return r[e](u, u.exports, t), u.exports;
}
(() => {
const r = t(694);
document.write(r.a());
})();
})();
结论:function b 没有被擦除,tree shaking无效
使用 exports 导出
// 入口文件 index.js
const HW = require('./helloworld');
document.write(HW.a());
exports.a = function a() {
return 'hello world a';
}
exports.b = function b() {
return 'hello world b';
}
(() => {
var r = {
694: (r, o) => {
(o.a = function () {
return 'hello world a';
}),
(o.b = function () {
return 'hello world b';
});
},
},
o = {};
function t(e) {
var n = o[e];
if (void 0 !== n) return n.exports;
var u = (o[e] = { exports: {} });
return r[e](u, u.exports, t), u.exports;
}
(() => {
const r = t(694);
document.write(r.a());
})();
})();
结论:function b 没有被擦除,tree shaking无效
结论:
- 如果导入方式采用的是commonjs的形式,那么tree shaking无法生效
- 如果导入方式采用的是es module,除了 module 采用了 module.exports 这样的形式导出接口外,其余情况都可以生效
- 当然这个测试是比较简单的纯函数,真实的项目里面情况比这个复杂,推荐阅读 你的Tree-Shaking并没什么卵用
最后: 本人在4月初被百度公司按违纪解除劳动合同,公司拒绝沟通,不出具具体原因。在疫情情况下,蒙受损失,还有许许多多人和我一样的遭遇,拿不到股票,那不多签字费。在金3银4的末尾,友情提醒大家一旦公司开始作恶,那么它就是会一直作恶,毕竟“简单可以赖”,希望大家可以找到心仪的工作。