Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SFC is not tree-shakeable: lang=ts and 2 <script> blocks #5988

Closed
0x009922 opened this issue May 23, 2022 · 2 comments
Closed

SFC is not tree-shakeable: lang=ts and 2 <script> blocks #5988

0x009922 opened this issue May 23, 2022 · 2 comments

Comments

@0x009922
Copy link

Vue version

3.2+

Link to minimal reproduction

https://github.com/0x009922/vue-sfc-tree-shaking-issue

Steps to reproduce

  • Create a component:

    <script lang="ts">
    export default defineComponent({
        name: 'SampleComponent'
    })
    </script>
    
    <script setup lang="ts">
    import { ref } from 'vue'
    
    const counter = ref(0)
    </script>
    
    <template>
        <button @click="counter++">{{ counter }}</button>
    </template>
  • Re-export it from a module with other stuff:

    // FILE: lib.ts
    export { default as SampleComponent } from './SampleComponent.vue'
    
    export function someUtility(): number {
        return 42
    }
  • Import other stuff in a bundler entry:

    // FILE: entry.ts
    import { someUtility } from './lib'
    
    console.log(someUtility())
  • Bundle it (I use Vite's library mode)

What is expected?

Bundler output:

function someUtility() {
  return 42;
}

console.log(someUtility());

What is actually happening?

Bundled file weight is 42kb with the whole Vue.

System Info

System:
    OS: Linux 5.15 Manjaro Linux
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 25.44 GB / 31.17 GB
    Container: Yes
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.15.0 - ~/.nvm/versions/node/v16.15.0/bin/node
    npm: 8.5.5 - ~/.nvm/versions/node/v16.15.0/bin/npm
  Browsers:
    Firefox: 100.0
  npmPackages:
    vue: ^3.2.36 => 3.2.36

Any additional comments?

If you remove lang=ts and leave just 2 <script> blocks, then tree-shaking works. But even in that case the bundle output has a dirt:

defineComponent({
    name: 'SampleComponentJs'
});

function someUtility() {
  return 42;
}

console.log(someUtility());

Context: we have a component library, and we use lang=ts for components. Due to this bug, we can't tree-shake unused stuff from our library.

Maybe related? #2860

@yyx990803
Copy link
Member

yyx990803 commented May 23, 2022

You are manually calling defineComponent(), which makes it look like it has side effects to the bundler. This is unnecessary if you are just defining a component name - just do export default { name: '...' }.

Also, since 3.2.24 SFCs using <script setup> automatically infers name option based on filename so it's not even necessary to use a separate <script> block.

If you do need defineComponent() for whatever reason, mark it as side-effect free with the pure annotation (this works in both webpack and vite):

/*#__PURE__*/ defineComponent({
    name: 'SampleComponentJs'
});

@0x009922
Copy link
Author

0x009922 commented May 25, 2022

Thank you very much!
By the way, neither /* @__PURE__ */ nor /*#__PURE__*/ works - these marks don't make any sense.

@github-actions github-actions bot locked and limited conversation to collaborators Sep 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants