UMD build: Cannot read properties of null (reading 'setupContext')
Version
3.2.31
Reproduction link
Steps to reproduce
- Copy the library that was compiled to UMD for production into the project.
- Modify
vite.config.js
to include the library viaoptimizeDeps
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.
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
@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
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.
@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.
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.
@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.
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.
Tip: https://vitejs.dev/config/#resolve-dedupe could also help.
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>
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