bennycode / welovecoding

https://welovecoding.herokuapp.com/
1 stars 0 forks source link

Investigation: Replace Sequelize #44

Open bennycode opened 7 years ago

bennycode commented 7 years ago

Sequelize is a very well-known JavaScript ORM for Node.js. However, I have the feeling that it's becoming the dinosaur of JavaScript ORMs. My assertion is based on the following observations:

Built with ES5

Sequelize was built with ES5 and is slowly converting to ECMAScript 6. This has the disadvantage of getting auto-generated ES5 code when using sequelize-cli. Here is an example of running sequelize init:

backend/models/index.js

'use strict';

var fs        = require('fs');
var path      = require('path');
var Sequelize = require('sequelize');
var basename  = path.basename(module.filename);
var env       = process.env.NODE_ENV || 'development';
var config    = require(__dirname + '/..\config\config.json')[env];
var db        = {};

if (config.use_env_variable) {
  var sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  var sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(function(file) {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(function(file) {
    var model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach(function(modelName) {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Same applies to generating database models. The output of sequelize model:create --name User --attributes name:string is ES5 code:

backend/models/user.js

'use strict';
module.exports = function(sequelize, DataTypes) {
  var User = sequelize.define('User', {
    name: DataTypes.STRING
  }, {
    classMethods: {
      associate: function(models) {
        // associations can be defined here
      }
    }
  });
  return User;
};

The ES5 code then needs to get manually transpiled into ES6 code.

Lack of native Promises

Promises in Sequelize are build with a promise library called Bluebird. Since Promises are part of the ES6 standard, there is no need for a third-party library like Bluebird. In fact using Bluebird makes it worse because it implements functions like .finally which makes it difficault to distinguish between standard Promises and Bluebird Promises.

No typings

In our project we use TypeScript. To make typings work for Sequelize (which doesn't support type definition files by default) we are dependant on @types/sequelize. This limits us to the features which @types/sequelize exposes.

In addition we are dependant on sequelize-typescript. A Sequelize decorator library maintained by a single guy.

Alternatives

There are a few other Node.js ORMs on the field. Namely:

My current favorite is Objection.js because it's Promised-based, developed with ES6 and comes with type definitions by default. Especially the "native" TypeScript definitions are a huge win for us!

We should evaluate if we could use Objection.js in favor of Sequelize as long as our database models are still small. What do you think, @TN1ck & @Yserz?

TN1ck commented 7 years ago

Sequelize is the only framework which supports migrations, which is why i chose it. The stuff works fine currently and I don't see the reason to replace them. The promise stuff is not an issue for me and you can hold me to this statement: It never will be. That sequelize-typescript is only coded by a single guy is troublesome, but it works really good and we can always opt out for the parts where it causes problems. As for the CLI generated scripts: We don't need this functionality anymore, the stuff is already there.