core: @vue/compiler-sfc output is not tree-shakeable
Version
3.0.4
Reproduction link
https://github.com/mgdodge/rollup-plugin-vue-treeshake-bug-vue3
Steps to reproduce
Originally logged with rollup-plugin-vue, but the tree-shaking issues seem to be coming @vue/compiler-sfc. The following steps are still valid, and still occur with the latest version.
Vue 3 tree-shaking bug
This repo has two branches - one written in Vue 2, one in Vue 3. The components and logic involved are identical (a simple diff of the branches will illustrate this). The only differences are in the dependencies introduced by Vue itself, using defineComponent in Vue 3 instead of Vue.extend for Vue 2, and the inclusion of postCSS for processing the css (required for vue3).
Reproducing the bug
Setup
- Clone repo
- Checkout
Vue 2branch - Run
npm installfollowed bynpm run buildandnpm packto create.tgzthat can be used in external projects. Rename that file todemolib-vue2.tgz - Checkout
Vue 3branch and repeat last step, renaming file todemolib-vue3.tgz - Create two sample Vue cli projects, one each for Vue 2 and Vue 3
- Install cli project dependencies, including the correct
.tgzfiles from the prior steps
Usage
Load 2 of the 3 components provided by the library. Components are Cat, Dog, and Fish.
import { Cat, Dog } from 'demolib'; // No Fish
// For Vue 2
Vue.component('cat', Cat);
Vue.component('dog', Dog);
Vue.mount('#app');
// For Vue 3
const app = createApp(App);
app.component('cat', Cat);
app.component('dog', Dog);
app.mount('#app');
<template>
<p>Pet options:</p>
<cat />
<dog />
<!-- Fish is not used -->
</template>
Verify tree-shaking
Execute npm run build in each cli project. The resulting “optimized” javascript files will include a chunk-vendors file which should include a tree-shaken version of demolib. Search this file for the following strings:
- “The cat is named”
- “The dog is named”
- “The fish is named”
If tree-shaking worked, you should not see The fish is named anywhere in the output. In the Vue 2 version, tree-shaking works properly. In the Vue 3 version, the unused code is still included.
What is expected?
Code output should be tree-shakeable
What is actually happening?
Code is not tree-shakeable
As noted in this comment on the rollup-plugin-vue bug report, adding /*__PURE__*/ comments to some of the output gets things really close, but there are still some code refactors that are required to get things working.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 16 (5 by maintainers)
Commits related to this issue
- fix(lib-mode): do not minify lib mode es output Otherwise it breaks library tree-shaking https://github.com/vuejs/vue-next/issues/2860#issuecomment-926882793 — committed to vitejs/vite by yyx990803 3 years ago
- fix(lib-mode): do not minify lib mode es output Otherwise it breaks library tree-shaking https://github.com/vuejs/vue-next/issues/2860#issuecomment-926882793 — committed to aleclarson/vite by yyx990803 3 years ago
Not surprisingly, vite.js libarary mode output, though minified, still suffers from this. Thinking this should get a bump in priority, since more prominent tooling/documentation is now promoting libarary builds which will suffer from this.
Should this issue be labelled as a bug instead of a feature? Tree shaking seems like a critical feature for vue 3 given the changes to the global API and the switch from options to composition.
This is now fixed by https://github.com/vitejs/vite/commit/316d7afc0c84e51359938a12ebe1b09ca34ea8bd + cb2d7c0e
Will need
@vitejs/plugin-vue>= 1.8.1.vue-loader@nextwill get similar fix soon.Ok, so this is because the
lib-vuebuild minifies the dist files, which removes the/*#__PURE__*/annotations in the generated code. You also forgot to add/*#__PURE__*/before your owndefineComponentcalls (I’m not sure why you are doing it in the first place, since you don’t need it if you are not using TS, or if you are using<script setup>).We should probably default to not minifying in lib mode in Vite.
The code generated by
@vitejs/plugin-vueis correct and can be treeshaken if you disable minify inlib-vite.Any progress in this topic? Sadly this is a showstopper to move our private libraries to vue 3, too.