起因
这个事情的起因是,最近我开源了一个npm包 vue3-tree-shaking可以处理setup语法糖的vue3单文件组件代码字符串,移除script中无用的代码。
然后我就尝试在技术社群分享,希望能跟大家交流一下技术问题(企图混几个star)
发出去不久马上就有同学提出疑问:
内部不就有tree shaking吗?
当时我只是回复我这边的场景比较少见,是为了处理低代码产生的代码字符串中的冗余信息,并没有深究,后面想想勾起了我的探究欲:
- 我这个包除了能减少代码量,是有必要的吗?
- 实际vite打包的tree-shaking结果是怎么样的?
探索
1.首先建一个测试工程:
npx create-vite
npm install
npm run dev
2.然后将初始工程里的src\components\HelloWorld.vue组件稍加改造:
<script setup>
import { onMounted, reactive, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
defineProps({
msg: String,
});
const emit = defineEmits(["inFocus", "submit"]);
function buttonClick() {
emit("submit");
}
const count = ref(0);
const count_useLess = ref(1110);
const count_useLess2 = ref(22222);
const state = reactive({
a: "123",
b: 666,
});
const state_useLess = reactive({
a: "789",
b: 10000,
});
let useLessVar = "useLessVar";
const useLessConst = "useLessConst";
function useLessFn() {
emit("submit");
}
const useLessArrowFn = () => {
emit("submit");
};
let useVar = "useVar";
console.log("first output");
defineExpose({
count,
buttonClick,
});
onMounted(() => {
let router = "useRouter()";
count_useLess2.value = "xxxxxx";
console.log("second output");
});
</script>
<template>
<h1 :xx="state.a">{{ msg }} ::{{ useVar }}</h1>
<div class="card">
<button type="button" @click="count++">count is {{ count }}</button>
</div>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
直接打包的话会发现,默认是打包成一个js文件的,这样不方便我们观察打包产物
这里稍微修改一下vite.config.js文件:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes("node_modules")) {
return "vendor";
}
},
},
},
},
});
再次打包,保存借助vscode配置的保存自动格式化:
这样产物就会划分为两个部分,node_modules下的依赖会输出到单独的文件
仔细观察不难发现,没有用到的顶层/局部 变量/常量如useLessVar,useLessConst,useLessFn,router都没有输出到最终产物
我发现很奇怪的点出现了:
count_useLess,state_useLess 这两个没有使用到的ref/reactive 只shaking掉了前面的常量值,但是会保留右侧的表达式
想很久没有感觉靠谱的答案,也求教各位佬,猜测,可能是某种情况的无用响应式值会存在“副作用”?
最后
在这个过程里面简单窥探了vue3代码经过vite打包的结果,欢迎讨论下上面的问题
回答一下上面提出的问题,目前看来,在我这个场景下,剔除无用代码也是存在意义的,在vite的基础上继续优化了产物体积,当然这是建立在,我确定这样的移除不会造成任何影响的前提下
最后的最后,推一下我发的npm包,基本使用非常简单: GitHub:github.com/daigang666/… 求个star
npm install vue3-tree-shaking -save-dev
import { treeShakeVueSFC } from 'vue3-tree-shaking';
import vue_sfc from "./test/vue_sfc.vue?raw";
const { code } = treeShakeVueSFC(vue_sfc);
console.log('code :', code);