Subscribe on changes!

UMD build: Cannot read properties of null (reading 'setupContext')

avatar
Apr 7th 2022

Version

3.2.31

Reproduction link

stackblitz.com

Steps to reproduce

  • Copy the library that was compiled to UMD for production into the project.
  • Modify vite.config.js to include the library via optimizeDeps so that the import can be treated as an ESM.
  • Import the library as if it were an ESM into the app.
  • Try to use a component that mixes both APIs.

What is expected?

According to the documentation, I can freely mix both composition API and options API for the same component. There is no mention of there being an exception for UMD builds and I would have expected it to work regardless of the type of build.

What is actually happening?

I get a runtime error regarding runtime-core.esm-bundler.js, Cannot read properties of null (reading 'setupContext'). This issue only seems to occur for components that mix both APIs.


Tried to use Stackblitz as a means of reproducing the problem, but it appears to not honor optimizeDeps. Nevertheless, the Stackblitz provided generates an error of similar nature.

avatar
Apr 7th 2022

That's not related to the UMD Build.

It's currently not supported to access state that was defined in script setup in Options API at runtime, because the render function gets inlined into the generated setup function and is returned from it - there's no returned state for options API to access:

export default defineComponent({
  setup() {
    //  defined in render function's closure.
    const state = reactive({})
    return () => { /* render function accessing stuff in closure */}
  },
  mounted() {
    this.state // won't be accessible
  }
})

We definitely need to warn about that during runtime.

Also think this is a duplicate issue, will look it up later

avatar
Apr 7th 2022

duplicate #5673

avatar
Apr 7th 2022

@LinusBorg It doesn't happen with the ES build, and the explanation you give I do not believe applies here. Where in the following code do I commit the error you speak of? https://github.com/truefusion/vigil/blob/main/src/components/Button.vue

avatar
Apr 7th 2022

You're right, i misread this

avatar
Apr 7th 2022

I downloaded the repro, ran it locally and saw an error about the umd file not being able to resolve defineComponent

As I have no way to access the source for this umd file, and this rather seems like an issue with Vite's dependency optimization, I will close this here and ask you to take this to the Vite project.

you might also try and ask the vite community in their discord chat, they might be able to point you as to why this fails.

avatar
Apr 7th 2022

@LinusBorg According to the error on my machine, the culprit is the following line: https://github.com/vuejs/core/blob/e603fd258c1576082625943ac8b34407f5847665/packages/runtime-core/src/apiSetupHelpers.ts#L186

getCurrentInstance() is returning null. The issue is in no way related to defineComponent. It just so happens Stackblitz is not the best way to provide a duplicate of the problem.

avatar
Apr 7th 2022

I got the same error on my local machine (about defineComponent).

The line you point to is independent of the kind of build format, but:

What this rather sounds like is that you bundled Vue into this UMD build.

Which will break your app, that uses its own copy of Vue, and lead to things like getCurrentInstance() being undefined.

Since I have no access to the source or the build setup you used, and I won't debug your minified code, I can only guess.

avatar
Apr 8th 2022

@LinusBorg After much experimentation, I managed to find out the real source of the problem. There was nothing wrong with the UMD build. What was happening was Vite does not seem to be able to handle imports whose folders contain their own node_modules folder. In other words, say I have the following directory structure:

root-project/
 - node_modules/
 - git-cloned-project/
 -- node_modules/

Well, so long as I would try to import something from a directory that contained its own node_modules directory, I would get the error Cannot read properties of null (reading 'setupContext') when running the dev server. So, the solution was

root-project/
 - node_modules/
 - git-cloned-project/
 -- node_modules/ (delete this folder!)

Then

root-project/
 - node_modules/
 -- .vite/ (delete this folder!)

Then restart the Vite server so it optimizes everything again.

avatar
Apr 8th 2022

Sounds pretty much like another perspective on the issue I described: there's a second node_modules with a second "vue" package that gets included.

happ you found your solution.

avatar
Apr 8th 2022
avatar
Aug 13th 2022

I have the same problem

------- error ------- main.2ff0ecbab0eb3f2c70e2.js:634 Uncaught TypeError: Cannot read properties of null (reading 'setupContext') at sr (runtime-core.esm-bundler.js?0d3f:7489:14) at setup (index.vue?3169:39:7) at callWithErrorHandling (runtime-core.esm-bundler.js?85e2:155:24) at setupStatefulComponent (runtime-core.esm-bundler.js?85e2:7165:29) at setupComponent (runtime-core.esm-bundler.js?85e2:7120:11) at mountComponent (runtime-core.esm-bundler.js?85e2:5473:13) at processComponent (runtime-core.esm-bundler.js?85e2:5448:17) at patch (runtime-core.esm-bundler.js?85e2:5038:21) at mountChildren (runtime-core.esm-bundler.js?85e2:5234:13) at mountElement (runtime-core.esm-bundler.js?85e2:5143:17)

------- code -------

<template>
  <section :class="[ns.b(), ns.m(direction)]" :style="borderStyle">
    <div
      v-if="slots.default && direction === 'horizontal'"
      :class="[ns.e('text'), ns.is(contentPosition)]"
    >
      <slot name="default"></slot>
    </div>
  </section>
</template>

<script lang="ts">
export default {
  name: "DvDivider",
};
</script>

<script setup lang="ts">
import { PropType, useSlots, computed } from "vue";
import { useNamespace } from "../../hooks/useNamespace";

const ns = useNamespace("divider");
const slots = useSlots();

const props = defineProps({
  direction: {
    type: String as PropType<"horizontal" | "vertical">,
    default() {
      return "vertical";
    },
  },
  contentPosition: {
    type: String as PropType<"left" | "center" | "right">,
    default() {
      return "center";
    },
  },
  borderStyle: {
    type: String as PropType<"solid" | "dotted" | "dashed">,
    default() {
      return "solid";
    },
  },
});

const borderStyle = computed(() => {
  return props.direction === "horizontal"
    ? {
        "border-style": props.borderStyle,
      }
    : {};
});
</script>
avatar
Feb 6th 2023

I have the same problem

------- error ------- main.2ff0ecbab0eb3f2c70e2.js:634 Uncaught TypeError: Cannot read properties of null (reading 'setupContext') at sr (runtime-core.esm-bundler.js?0d3f:7489:14) at setup (index.vue?3169:39:7) at callWithErrorHandling (runtime-core.esm-bundler.js?85e2:155:24) at setupStatefulComponent (runtime-core.esm-bundler.js?85e2:7165:29) at setupComponent (runtime-core.esm-bundler.js?85e2:7120:11) at mountComponent (runtime-core.esm-bundler.js?85e2:5473:13) at processComponent (runtime-core.esm-bundler.js?85e2:5448:17) at patch (runtime-core.esm-bundler.js?85e2:5038:21) at mountChildren (runtime-core.esm-bundler.js?85e2:5234:13) at mountElement (runtime-core.esm-bundler.js?85e2:5143:17)

------- code -------

<template>
  <section :class="[ns.b(), ns.m(direction)]" :style="borderStyle">
    <div
      v-if="slots.default && direction === 'horizontal'"
      :class="[ns.e('text'), ns.is(contentPosition)]"
    >
      <slot name="default"></slot>
    </div>
  </section>
</template>

<script lang="ts">
export default {
  name: "DvDivider",
};
</script>

<script setup lang="ts">
import { PropType, useSlots, computed } from "vue";
import { useNamespace } from "../../hooks/useNamespace";

const ns = useNamespace("divider");
const slots = useSlots();

const props = defineProps({
  direction: {
    type: String as PropType<"horizontal" | "vertical">,
    default() {
      return "vertical";
    },
  },
  contentPosition: {
    type: String as PropType<"left" | "center" | "right">,
    default() {
      return "center";
    },
  },
  borderStyle: {
    type: String as PropType<"solid" | "dotted" | "dashed">,
    default() {
      return "solid";
    },
  },
});

const borderStyle = computed(() => {
  return props.direction === "horizontal"
    ? {
        "border-style": props.borderStyle,
      }
    : {};
});
</script>

hello i found the same problem, maybe we used useSlots