vue.jsfrontendvue-reactivity

Vue's "Component which was made a reactive object" Warning


I've written a component using the defineComponent syntax, with a template, like this:

<script>
import MySvgComponent from './MySvgComponent.vue'
const MyComponent = defineComponent({
  components: {
    MySvgComponent
  },
  template: `
    <div><MySvgComponent /></div>
  `,
})
</script>

For some reason, when I do this, I get the following warning:

"Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with markRaw or using shallowRef instead of ref"

The solution here is to wrap the imported component in either markRaw or shallowRef, which resolves the warning, like this:

<script>
import { markRaw } from 'vue'
import MySvgComponent from './MySvgComponent.vue'
const MyRawSvgComponent = markRaw(MySvgComponent);
const MyComponent = defineComponent({
  components: {
    MyRawSvgComponent
  },
  template: `
    <div><MyRawSvgComponent /></div>
  `,
})
</script>

Why does this resolve the warning?

It looks like based on the documentation that wrapping a Javascript object in markRaw returns a non-proxied version of the original object. Why do we need to do that here, and what exactly is the performance issue going on here that we're resolving by using the markRaw or shallowRef functions?


Solution

  • It is all explained in the documentation.

    The problem is that

    1. Component instances are much more expensive than plain DOM nodes, and creating too many of them due to abstraction patterns will incur performance costs.
      Read More

    2. In addition, Vue's reactivity system is deep by default. While this makes state management intuitive, it does create a certain level of overhead when the data size is large, because every property access triggers proxy traps that perform dependency tracking. This typically becomes noticeable when dealing with large arrays of deeply nested objects, where a single render needs to access 100,000+ properties, so it should only affect very specific use cases.
      Read More

    To avoid these issues Vue component instances/objects without the shallowRef or markRaw() needs to be flagged, this is to ensure optimisation and performance.

    shallowRef is typically used for performance optimizations of large data structures, or integration with external state management systems.
    Read More about Shallow Ref

    markRaw() on the other hand marks an object so that it will never be converted to a proxy. Returns the object itself.
    Read More about markRaw()