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

esModule option stopped working in version 14 #1172

Closed
bendytree opened this issue Feb 21, 2018 · 6 comments
Closed

esModule option stopped working in version 14 #1172

bendytree opened this issue Feb 21, 2018 · 6 comments

Comments

@bendytree
Copy link

Version

14.1.0

Reproduction link

https://gist.github.com/bendytree/ea50ef622936f38169a17f252c70b775

Steps to reproduce

require a *.vue file with esModule: false

What is expected?

The component should be available at:

const component = require("./component.vue");

What is actually happening?

The component is available at:

const component = require("./component.vue").default;

Looks like esModule became true by default in v13.

In v14 it was removed from the code base.

The docs still show it as an option.

@BrainBacon
Copy link

BrainBacon commented Feb 23, 2018

Isn't it still a bit premature to remove this option entirely? ES Modules still haven't landed in Node natively. We use CommonJS everywhere to alleviate context switching overhead and allow for isomorphic modules. We don't plan on adding a transpile step to our server-side code, and I don't see many other developers planning to do so either. I understand I could just use .default on the require calls, but It's easy to forget and results in cryptic errors when omitted. So far this makes v14 a non-starter.

This SO post shows one of the cryptic errors:
https://stackoverflow.com/questions/47883370/vue-js-typeerror-cannot-set-property-props-of-object-which-has-only-a-get?rq=1

See here for the status of ES Modules in Node:
https://github.com/nodejs/node/labels/ES%20Modules

@yyx990803
Copy link
Member

This is an intentional removal (and that's why it's a new major version). We forgot to remove it from the docs when publishing v14. That said, do read the release notes before upgrading major versions!

Currently there are no major new features in v14.0 so you can safely stay on v13.x, but in the long run, you definitely should consider migrating towards ES modules whenever possible.

@BrainBacon for server-side code, I'm not quite following why you'd have the problem if you are using webpack to bundle your code - are you using require hooks to directly load Vue files on the server?

@BrainBacon
Copy link

BrainBacon commented Mar 12, 2018

@yyx990803 I'm not talking about Vue's server-side rendering. I'm saying in our workflow we devlop more than just client-side code. Specifically we devlop server-side code like REST services on Express. I've authored a shared style-guide that encompasses all of client-side and server-side (Node.js) JavaScript. What I'm remarking on specifically is that there is a mental burden when context switching between ESM style import syntax and CommonJS require syntax. I do not plan on switching client-side to ESM until Node.js proper supports it in an actual release. Additionally we have isomorphic modules that run in a Vue context and in a server-side non-Vue context. These would by nature have to be in the CommonJS format in order to run on the server without tooling.

More than half of my developers don't even know what ESM is, and the same applies to a majority of JavaScript developers in the wild. I completely agree that ESM needs to be the future of JavaScript and the switch needs to be swift and as painless as possible. Yes, Vue is the "progressive" framework, so it makes sense to adopt these technologies quickly. However, with that being said, shouldn't we wait until it's at least supported by the underlying system running that code?

My personal plan is to wait until Node.js ships with ESM (without a flag) and instruct all my developers on it's immediate ubiquitious usage. I do not plan on supporting a fractured code with band-aid tooling just for the time being.

I personally follow ESM very closely for the reason that it's a great standard, and I supported the push away from Node's .mjs proposals. The rapid progression in the JavaScript community is one of the reasons I love it, but this is a case where the community is getting a little ahead of itself, and it's actually hindering progress rather than pushing us forward.

@yyx990803
Copy link
Member

There are practical reasons why you should use ESM for client-side code. When you continue to use CommonJS syntax in webpack-bundled code, you won't get any of the three-shaking benefits because they require ESM syntax to work. This means you are likely causing your client-side payload to be bigger than it should be when you stay on CommonJS.

IMO that alone is worth using ESM for client-side code. Plus, I myself have been writing client-side code in ESM and Node code in CommonJS concurrently for quite some time and haven't really find the context switch cost noticeable.

If you insist on staying on CommonJS, you can write a custom babel plugin that appends .default to any require() calls that ends in *.vue.

@BrainBacon
Copy link

BrainBacon commented Mar 12, 2018

I may not have been entirely clear about how adopting ESM too quickly can hinder progress. There are road blocks to confidence in ESM at this point. The Babel/Webpack implementation is non-standard and developing ESM in it's current format could prove to lead libraries into an unsupported dead-end. Here's a pull-request in Babel that showcases the uncertainty facing ESM implementation. If libraries choose to continue down this path early, then the possible price to pay in the future of the library is incompatibility with the final standard. Vue is not the only library headed down this path and it causes self-reflection in the community on weather or not to adopt something non-standard over standards because it's "the way we're already doing it!"

I definitely understand the practicality of tree-shaking and other benefits of ESM and I don't disagree. I think developers that want that functionality today are well within the scope of Vue's progressive vision, but forcing the entirety of the community to adopt a technology that isn't ready is a bit unreasonable. Shouldn't the term "progressive enhancement" apply here?

I think the way it was handled before was fine. Was there a technical limitation to maintaing multiple distributions in this library specifically? Couldn't we just have a vue-loader.common.js?

Edit: now that I think about it, it would require different logic in the library for converting the transpiled module code. Please disregard my suggestion for a different distribution.

@yyx990803
Copy link
Member

ES modules as a spec is done. It's already a formal part of the language. There's no uncertainty regarding its syntax or semantics in client-side JavaScript. The uncertainty applies to Node only, and no matter how Node decides to adopt ESM, the part that is already in the language spec is not going to change.

Maintaining parallel support for both ESM and CommonJS in vue-loader adds complexity and extra burden to the maintainers when it may only be valuable to a niche group of users. As I suggested, your needs (not having to write .default when requiring Vue files) can be addressed with a Babel plugin without having to cobble it into vue-loader.

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

3 participants