Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing default export when using SystemJS or RequireJS makes Vue unusable with TypeScript #6815

Closed
ciddan opened this issue Oct 14, 2017 · 12 comments

Comments

@ciddan
Copy link

ciddan commented Oct 14, 2017

Version

2.5.2

Reproduction link

https://github.com/ciddan/vue-2.5-issues

Steps to reproduce

  1. Clone the repo.
  2. npm install.
  3. run "gulp".
  4. Navigate to the appropriate address in your browser (default http://localhost:3000).
  5. Note console output.

The project is configured to use SystemJS by default. You can switch to RequireJS by modifying index.html and src/login/Login.ts and uncommenting the RequireJS code (and commenting out the SystemJS code).

What is expected?

No errors in console and vue_1.default being defined.

What is actually happening?

SystemJS (Firefox Developer Edition):
Error: class heritage vue_1.default is not an object or null
Evaluating http://localhost:8080/dist/src/login/Login.js
Loading app.bootstrap.js

RequireJS (Firefox Developer Edition):
TypeError: class heritage vue_1.default is not an object or null


This bug appeared after upgrading a major project from Vue 2.4 to Vue 2.5.
We do not use Webpack in our project, nor do we want to switch to it.

@yyx990803
Copy link
Member

yyx990803 commented Oct 14, 2017

I am mostly certain this is a problem with your setup. I'm not familiar with SystemJS but you probably want to adjust this to use the ES modules build (vue.runtime.esm.js).

@ktsn
Copy link
Member

ktsn commented Oct 14, 2017

Vue's declaration is now switched to ES module style declaration and we need to use vue(.runtime).esm.js if we want to use ES module.
Both RequireJS and SystemJS seem not to support ES module. Then you may need to migrate to a tool supporting ES module if you want to use >= v2.5 with TypeScript.

@ciddan
Copy link
Author

ciddan commented Oct 14, 2017

If I switch SystemJS to use .esm.js then I have to add a (pointless) babel plugin to transpile the compiled JS. And If I do that, then SystemJS will complain that "process" is undefined: Error: process is not defined.

I cannot fix that in my config, since the meta/globals override config is only supported under "cjs" and "global" module formats.

This is driving me slightly mad.

It seems to me that this could be fixed with a simple exports['default'] = Vue$3; at the bottom of vue(.runtime).common.js (i.e. what vue-class-component does).

ping @ktsn @DanielRosenwasser

@yyx990803
Copy link
Member

The esm.js is still pre-transpiled, the only ES2015+ thing left in it is the export syntax. It sounds pretty odd that SystemJS can't do a simple global replacement of process.env.NODE_ENV when using ES modules - but you can just shim it yourself.

@ciddan
Copy link
Author

ciddan commented Oct 14, 2017

I am trying to shim it right here: https://github.com/ciddan/vue-2.5-issues/blob/7e4dad6f81a8d4c21c7c76fb794738f69fcafddb/system.config.js#L25

But I suppose I'll just have to include this thing in index.html:

<script>
    window.process = {
        env: {
            NODE_ENV: "development",
            VUE_ENV: "client"
        }
    };
</script>

@DanielRosenwasser
Copy link

Maybe I'm missing something, but my understanding was that SystemJS gives you the "intended" behavior with default imports, but you need to turn on TypeScript's --allowSyntheticDefaultImports flag.

@ciddan
Copy link
Author

ciddan commented Oct 14, 2017

Just to boil this down into a simple example:

// Login.ts
import Vue from "vue";
export default class Login extends Vue {
}

// Compiled Login.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1 = require("vue");
class Login extends vue_1.default { // <== Crash!
}
exports.default = Login;

vue_1 is the constructor function, vue_1.default is undefined.
--allowSyntheticDefaultImports doesn't affect emitted code, that's only for compile time, and it doesn't fix the issue. The compiled code above is the same whether its on or not.

@DanielRosenwasser
Copy link

DanielRosenwasser commented Oct 14, 2017

Looks like you're emitting to CommonJS which by default doesn't do any sort of default synthesis. Since you're already targeting SystemJS, you might as well switch your module target to system and things should work well again.

@HerringtonDarkholme
Copy link
Member

I'm not familiar with SystemJS. But from this thread, it seems that SystemJS's author think that default synthesis should be handled by transpiler. And I'm quite sure TypeScript does not handle synthesis by design.

You do need another transpiler for now. Or trying out Daniel's suggestion listed in the thread linked above.

@ciddan
Copy link
Author

ciddan commented Oct 15, 2017

Thanks @DanielRosenwasser. That did the trick. I wasn't aware of the System-specific module target.

@viT-1
Copy link

viT-1 commented Aug 20, 2019

@ciddan You deleted repo https://github.com/ciddan/vue-2.5-issues
Do you have an example with working Vue on SystemJS?
I have the same error: "Cannot read property 'default' of undefined"
and Daniel's trick with double import is not helped =(

@viT-1
Copy link

viT-1 commented Aug 21, 2019

Just solved in my repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants