Vue: Wrong generated JS code by TypeScript and AMD ( UMD) - version 2

Created on 4 Jan 2018  ·  3Comments  ·  Source: vuejs/vue

Version

2.5.13

Reproduction link

https://github.com/80LevelElf/VueProblemApp

Steps to reproduce

Just run the app by opening the
/VueProblemApp/VueProblemApp/index.html file and you will see the error in the Console.

What is expected?

The Typescript compiler should take Vue typings and produce the right code.

What is actually happening?

The resulted JS code is not right (see comments for detail explonation).


Several days ago I created the Wrong generated JS code by TypeScript and AMD ( UMD) bug (click the link to see detail explanation of the problem).

I got an answer from @yyx990803, but I am a noob in the JS and didn't get it right from the first time.
And if I get it right now, the problem is still relevant.

Evan answered me:

There seems to be nothing in your config that points the "vue" module to the vue.js UMD build you included yourself. So the TS compiler is resolving it from node_modules/vue and using the "main" field in package.json, which is a CommonJS build. You need to specify the mapping using compilerOptions.paths in your tsconfig.

So if I get Evan right he thought that RequireJS download the wrong vue.js file.
The right one is for UMD/AMD module system, but the TS compiler makes a reference to the vue.js file for CommonJS module system. This is why I had got the error.

But it's not right. TS compiler just make a reference to

mySite/

and in my case it is:

mySite/vue.js

no matter what vue.js file is. So if there is no vue.js in this link there will be the 404 error.

Also, I try to change the main config in node_modules/vue/package.json like that: "main": "dist/vue.js" and it gives me the same error.

I have checked the vue.js file that is loading by RequireJS and it is the right file. RequireJS parse it right, the problem is in the typings.

Also if I make the import like this (like @Micene09 offered):

import { Vue } from "vue-property-decorator";

Everything works fine with loading the same vue.js file in mySite/vue.js.
So if I get you right the problem still remains.

Most helpful comment

I ran into the same issue.

From my understanding, the vue.js file should be setting the exports.default variable like the vue-class-component does.

vue-class-component.js (Line 192):
exports['default'] = Component$1;

The vue-class-component file has a special case to handle the missing default export from Vue, which is why it works.

vue-class-component.js (Line 12):
Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue;

Unfortunately, the TypeScript 2.5 compiler does not output a special case for handling the missing default. However, TypeScript 2.7 has a new option (esModuleInterop) that fixes this issue.

{
    "compilerOptions": {
        "module": "amd",
        "esModuleInterop": true,
        ...
    },
    ...
}

With esModuleInterop set to true, the output contains a function called __importDefault, which handles the missing default property properly.

var __importDefault = (this && this.__importDefault) || function (mod) {
  return (mod && mod.__esModule) ? mod : { "default": mod };
}
define(["require", "exports", "vue"], function (require, exports, vue_1) {
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  vue_1 = __importDefault(vue_1);
  var app = new vue_1.default({
        ...
  });
});

All 3 comments

I'm sorry, but this is really an out of scope question for a very specific setup that should not be resolved in issues. Issues are for bug reports that originates from Vue itself only.

@80LevelElf -- I solved this (for now) by doing the following:

import { VueConstructor } from "vue";
const Vue = require("vue") as VueConstructor;  // cast as VueConstructor to get typings. 

const app = new Vue({
  template: "<h1>Hello World</h1>
});

@yyx990803 -- I'm in a similar, but different situation. I'm using commonjs output from TypeScript (no webpack). One similarity between OP and I is that we're both using the TypeScript baseUrl option. Something is definitely wrong with the standard import in TypeScript.

I too am using Vue 2.5.13. I'm setting up SSR on Node 8.9.3 and TypeScript 2.6. My tsconfig.json looks like this:

{
  "compilerOptions": {
    "outDir": "build",
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "rootDir": "./src",
    "baseUrl": "./src",
    "noUnusedLocals": true
  },
  "exclude": [
    "node_modules",
    "typings"
  ]
}

I tried a number of other workaround, including trying to load the vue.esm.js file via the compilerOptions.paths property, without success. I was getting the exact same vue_1.default is not a constructor error as OP.

I've put together a reproduction here and opened a new issue

I ran into the same issue.

From my understanding, the vue.js file should be setting the exports.default variable like the vue-class-component does.

vue-class-component.js (Line 192):
exports['default'] = Component$1;

The vue-class-component file has a special case to handle the missing default export from Vue, which is why it works.

vue-class-component.js (Line 12):
Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue;

Unfortunately, the TypeScript 2.5 compiler does not output a special case for handling the missing default. However, TypeScript 2.7 has a new option (esModuleInterop) that fixes this issue.

{
    "compilerOptions": {
        "module": "amd",
        "esModuleInterop": true,
        ...
    },
    ...
}

With esModuleInterop set to true, the output contains a function called __importDefault, which handles the missing default property properly.

var __importDefault = (this && this.__importDefault) || function (mod) {
  return (mod && mod.__esModule) ? mod : { "default": mod };
}
define(["require", "exports", "vue"], function (require, exports, vue_1) {
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  vue_1 = __importDefault(vue_1);
  var app = new vue_1.default({
        ...
  });
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

loki0609 picture loki0609  ·  3Comments

lmnsg picture lmnsg  ·  3Comments

bfis picture bfis  ·  3Comments

julianxhokaxhiu picture julianxhokaxhiu  ·  3Comments

hiendv picture hiendv  ·  3Comments