Dynamic Component gives TypeError: Cannot read property '__esModule' of undefined

3.4k Views Asked by At

I'm roughly trying to follow this article to import vue components dynamically from my asp.net core webapi

MyComponent.vue

<template>
  <h2>Hello from the Distribution Server!</h2>
</template>

Which I converted to a .umd.min.js with this command:

npx vue-cli-service build --target lib --formats umd-min --no-clean --dest server/components/MyComponent --name "MyComponent.[chunkhash]" server/components/MyComponent/MyComponent.vue

Everythnig seems to run fine when imporing the component, but it doesn't appear in the app and i can see this error in the console:

Uncaught (in promise) TypeError: Cannot read property '__esModule' of undefined
    at ensureCtor (vue.js:3595)
    at vue.js:3668
    at vue.js:351

What am I doing wrong?

umd.min.js output:

(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t():"function"===typeof define&&define.amd?define([],t):"object"===typeof exports?exports["MyComponent.c9b7fae39bb9d71ad3e7"]=t():e["MyComponent.c9b7fae39bb9d71ad3e7"]=t()})("undefined"!==typeof self?self:this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s="fb15")}({f6fd:function(e,t){(function(e){var t="currentScript",n=e.getElementsByTagName("script");t in e||Object.defineProperty(e,t,{get:function(){try{throw new Error}catch(r){var e,t=(/.*at [^\(]*\((.*):.+:.+\)$/gi.exec(r.stack)||[!1])[1];for(e in n)if(n[e].src==t||"interactive"==n[e].readyState)return n[e];return null}}})})(document)},fb15:function(e,t,n){"use strict";var r;(n.r(t),"undefined"!==typeof window)&&(n("f6fd"),(r=window.document.currentScript)&&(r=r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))&&(n.p=r[1]));var o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("h2",[e._v("Hello from the Distribution Server!")])},i=[];function f(e,t,n,r,o,i,f,u){var c,a="function"===typeof e?e.options:e;if(t&&(a.render=t,a.staticRenderFns=n,a._compiled=!0),r&&(a.functional=!0),i&&(a._scopeId="data-v-"+i),f?(c=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"===typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),o&&o.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(f)},a._ssrRegister=c):o&&(c=u?function(){o.call(this,(a.functional?this.parent:this).$root.$options.shadowRoot)}:o),c)if(a.functional){a._injectStyles=c;var s=a.render;a.render=function(e,t){return c.call(t),s(e,t)}}else{var d=a.beforeCreate;a.beforeCreate=d?[].concat(d,c):[c]}return{exports:e,options:a}}var u={},c=f(u,o,i,!1,null,null,null),a=c.exports;t["default"]=a}})["default"]}));
//# sourceMappingURL=https://localhost:44385/api/DistributedComponent/TestSourceMap

Main vue component

<script lang="ts">
    import { Vue, Component, Mixins } from "vue-property-decorator";

    import externalComponent from '../../js/util/external-component';

    @Component({
        name: "Dashboard",
        components: {
            MyComponent: async () => await externalComponent('https://localhost:44385/api/DistributedComponent/Test')
        }
    })
    export default class Dashboard extends Vue {
        constructor() {
            super();
        }
    }
</script>

external-component.js

export default async function externalComponent(url) {
    const name = 'MyComponent'; 

    if (window[name]) return window[name];

    window[name] = await new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.async = true;
        script.addEventListener('load', () => {
            resolve(window[name]);
        });
        script.addEventListener('error', () => {
            reject(new Error(`Error loading ${url}`));
        });
        script.src = url;
        document.head.appendChild(script);
    });

    return window[name];
}
1

There are 1 best solutions below

0
On BEST ANSWER

The problem here was in external-component.js

It seems that the name variable should match the name of the actual file passed from the server

This can't just match the name string passed in to the File(bytes, file, "name") call, but the actual file name in the file system (excluding the .vue extension)

After setting that value properly it's working fine