Mongoose: [Discussion] Node 4/ES6

Created on 16 Sep 2015  路  19Comments  路  Source: Automattic/mongoose

This issue is to start a discussion about the potential for a future release of Mongoose, that would drop support for Node JS versions less than Node 4.
This would allow Mongoose to take advantage of new ES6 features natively supported in Node 4+.

Some ideas on changes that could come with better ES6 support.

replace var with let and const

let and const are block scoped and are not hoisted, this can make the code more explicit in its intent and has been shown in _some_ benchmarks to be as fast or faster than var.

ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
ref http://davidwalsh.name/for-and-against-let
ref https://jsperf.com/let-vs-var-definition/21

replace mpromise package with native promise

This would remove a dependency and offers a more spec compliant version.

ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

replace var _this = this with arrow functions

Arrow functions pull the this keyword from the lexical parent, which is what most of the uses of var _this = this in the code are doing just that.

ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

replace Object based models with class based models

Replace the existing system for creating a new model

var Cat = mongoose.model('Cat', { name: String });

var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
  if (err) // ...
  console.log('meow');
});

With a class based system

class Cat extends MongooseModel {
   constructor (name) {
      super({name: String});
      this.name = name;
   }   
}

var kitty = new Cat('Zildjian');
kitty.save(function (err) {
  if (err) // ...
  console.log('meow');
});

This could allow mongoose to be more extensible, and offer a system familiar to users of ORMs in other languages.

ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
ref https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20&%20beyond/ch3.md#classes

backwards-breaking discussion

Most helpful comment

Thanks for the update @ChristianMurphy . We plan on dropping support for everything below node 4 before the EOL for node 4.

All 19 comments

@vkarpov15 Would a release that drops pre Node 4 support even be feasible?
and if so do any of these ideas sound interesting?

I've been working on a project called monogram that's exploring what an ES6 ODM can do. Whether mongoose will follow suit is a matter of node v4 adoption - if the vast majority of mongoose users switch over then it could make sense.

As for promises, that's a whole different story. Node v4 adoption or no, the goal for mpromise in the next major release is 'kill it with fire'. Right now I'm leaning towards "native promises if available otherwise no promises" by default for v5. Thoughts?

I've been working on a project called monogram that's exploring what an ES6 ODM can do.

cool, I'll check that out.

the goal for mpromise in the next major release is 'kill it with fire'. Right now I'm leaning towards "native promises if available otherwise no promises" by default for v5.

sounds good to me :smile:

ESLint's no-restricted-modules rule could help with the transition.

I really like this proposal and am interested in seeing it come to fruition. I'm using Node v4 where I can and would love to see the project adopt ES6 likewise.

node v4 adoption - if the vast majority of mongoose users switch over then it could make sense.

We are gearing up for eventual adoption after a few issues over there are fixed however it may be prudent to ease into the transition to allow ample migration time.

I've barely begun examining _mongoose_ issues, as the Active Maintainer on our project, to follow along what's on the horizon. I've been creating ES5.1 _(with some ES6 bits)_ in Mozilla client side however _node_ projects have their own uniqueness. From what I can tell [email protected] will be more complete and they appear to have a rather quick time table e.g. last I read was [email protected] will happen in the next month or so... Our deps are frozen at static, fixed, versions in our project but doesn't mean we want to be left behind on bug fixes just yet. Typically most migrations occur within approximately 2 weeks unless they are backward-breaking in which it takes longer depending on contribution level and interest.

+1

+1

I think the biggest feature with node 4+ that mongoose can take advantage for becoming the de facto standard working with MongoDB is to get es6 generator support. The clarity in the syntax will definitely be a huge win.

@vkarpov15 I love the idea of Monogram I have gone through the code

co(function*() {
      const db = yield monogram('mongodb://localhost:27017');
      // `Person` is a model that stores docs in the 'people' collection
      const Person = db.model({ collection: 'people' });

      const axl = new Person({ name: 'Axl Rose' });
      yield axl.$save();

      let res = yield Person.find({ name: 'Axl Rose' });
      assert.equal(res.length, 1);

      done();
    }).catch(function(error) {
      done(error);
    });

The above syntax looks so clear and concise would love to see them implemented in mongoose too. Perhaps we can build the es6 features iteratively with a flag or a es6 mode for mongoose and mark it as experimental?

@sybarite there's nothing in the above syntax that you can't do with mongoose 4.x :)

co(function*() {
      const db = mongoose.createConnection('mongodb://localhost:27017');
      // `Person` is a model that stores docs in the 'people' collection
      const Person = db.model({ collection: 'people' });

      const axl = new Person({ name: 'Axl Rose' });
      yield axl.save();

      let res = yield Person.find({ name: 'Axl Rose' });
      assert.equal(res.length, 1);

      done();
    }).catch(function(error) {
      done(error);
    });

@vkarpov15 Oh thats nice to know! I haven't gone through the code base in detail yet, just started grokking properly. I wasn't sure if there would be some gotcha using co library with mongoose.

@sybarite should be fine, I've been using those two together with great success since node 4 came out. Monogram's killer features over mongoose right now are 1) lightweight, 2) less memory usage, 3) koa-style middleware.

LTS schedule

Long Term Support for 0.12 ends next month, maintenance ends this year.

Source: https://github.com/nodejs/LTS

I agree, since node 0.12 will no longer be officially supported, no reason why mongoose 5 should still support it

I agree too but I prefer Object instead Class :p

Also a question about fat arrow functions & methods which use dynamic context (this). Any plans to pass context as argument thus it can be used inside any function?

Not in mongoose 4, but that's definitely a priority for mongoose 5. Arrow functions are too nice and I personally have a strong aversion to relying on context.

is there any plans when this can be expected? I'm particularly looking into using es6 classes. So, something like this is possible

const mongoose = require('mongoose')

const schema = new mongoose.Schema({
  name: String
})

class Task extends mongoose.Document {
  static get schema() {
    return schema
  }

  myCustomMethods() {
  }
}

module.exports = mongoose.model(Task) // schema is taken from `Task.schema`, model name is taken from `Task.name`

Update: it shouldn't be a big deal to add this (maybe I'm missing?) without breaking the existing interfaces. And I'm ok to create PR if @vkarpov15 is ok with that. Any notes/hints are very appreciated

Node 0.12 has passed EOL.
Node 4 is quickly approaching the end of maintenance.

| Release | LTS Status | Codename | Active LTS Start | Maintenance LTS Start | Maintenance LTS End |
| :--: | :---: | :---: | :---: | :---: | :---: |
| v0.10.x | End-of-Life | - | - | 2015-10-01 | 2016-10-31 |
| v0.12.x | End-of-Life | - | - | 2016-04-01 | 2016-12-31 |
| 4.x | Maintenance LTS | Argon | 2015-10-01 | 2017-04-01 | April 2018 |
| 5.x | No LTS | | | | |
| 6.x | Active LTS | Boron | 2016-10-18 | April 2018 | April 2019 |
| 7.x | No LTS | | | | |
| 8.x | Active LTS | Carbon | 2017-10-31 | April 2019 | December 20191 |
| 9.x | No LTS | | | | |
| 10.x | Pending | Pending | October 2018 | April 2020 | April 2021 |

Source: https://github.com/nodejs/Release

Thanks for the update @ChristianMurphy . We plan on dropping support for everything below node 4 before the EOL for node 4.

I'm going to close this one, this is largely done. We use let/const internally, arrow functions where it makes sense, use native promises by default, and no longer support node < 4.

The idea for creating models via extends as opposed to mongoose.model() isn't quite viable because there's no real way to pass a schema to the model if you create it with `extends.

Was this page helpful?
0 / 5 - 0 ratings