vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.71k stars 8.33k forks source link

fix(reactivity): optimising getDepFromReactive #12007

Closed yangxiuxiu1115 closed 1 month ago

yangxiuxiu1115 commented 1 month ago

ObjectRefImpl in toRef depends on getDepFromReactive

github-actions[bot] commented 1 month ago

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 101 kB (+1 B) 38 kB (-10 B) 34.2 kB (-44 B)
vue.global.prod.js 160 kB (+1 B) 58 kB (-9 B) 51.5 kB (+51 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 49 kB 18.9 kB 17.2 kB
createApp 55.6 kB 21.4 kB 19.6 kB
createSSRApp 59.6 kB 23.1 kB 21 kB
defineCustomElement 60.4 kB 22.9 kB 20.9 kB
overall 69.3 kB 26.5 kB 24 kB
pkg-pr-new[bot] commented 1 month ago

Open in Stackblitz

@vue/compiler-core

``` pnpm add https://pkg.pr.new/@vue/compiler-core@12007 ```

@vue/compiler-sfc

``` pnpm add https://pkg.pr.new/@vue/compiler-sfc@12007 ```

@vue/compiler-dom

``` pnpm add https://pkg.pr.new/@vue/compiler-dom@12007 ```

@vue/compiler-ssr

``` pnpm add https://pkg.pr.new/@vue/compiler-ssr@12007 ```

@vue/reactivity

``` pnpm add https://pkg.pr.new/@vue/reactivity@12007 ```

@vue/runtime-core

``` pnpm add https://pkg.pr.new/@vue/runtime-core@12007 ```

@vue/runtime-dom

``` pnpm add https://pkg.pr.new/@vue/runtime-dom@12007 ```

@vue/server-renderer

``` pnpm add https://pkg.pr.new/@vue/server-renderer@12007 ```

@vue/shared

``` pnpm add https://pkg.pr.new/@vue/shared@12007 ```

vue

``` pnpm add https://pkg.pr.new/vue@12007 ```

@vue/compat

``` pnpm add https://pkg.pr.new/@vue/compat@12007 ```

commit: 619c58e

skirtles-code commented 1 month ago

Avoiding ?. is intended to reduce the file size, but it looks like this has increased it by 3 bytes. I was curious about why...

It looks like the ?. version gets inlined into the get dep getter in ObjectRefImpl. Even though it expands to something fairly verbose, the inlining shaves off lots of bytes. Removing the ?. seems to prevent that inlining, leading to a larger build.

I did a bit of experimenting, and the best I could do just by rewriting getDepFromReactive was this:

export const getDepFromReactive = (
  object: any,
  key: string | number | symbol,
  depMap = targetMap.get(object),
): Dep | undefined => {
  return depMap && depMap.get(key)
}

It's a bit hacky, but it got it down from +3 to -8.

But this still doesn't benefit from the inlining seen with the original code.

So I tried just rewriting the get dep in ref.ts:

  // `import` changes not shown

  get dep(): Dep | undefined {
    const depMap = targetMap.get(toRaw(this._object))
    return depMap && depMap.get(this._key)
  }

This got it down to -26, with small improvements in the zipped versions too:

File Size Gzip Brotli
runtime-dom.global.prod.js 101 kB (-26 B) 38 kB (-16 B) 34.2 kB (-43 B)
vue.global.prod.js 160 kB (-26 B) 58 kB (-15 B) 51.5 kB (+12 B)

The downside being direct access of targetMap in ref.ts.

I'll let others decide whether any of this matters... :laughing: