• 70322阅读
  • 0回复

Derby js 的开发者对 Derby 和 Meteor 两个框架做对比 [复制链接]

上一主题 下一主题

只看楼主 倒序阅读 使用道具 楼主  发表于: 2012-04-18
— 本帖被 jinwyp 从 互联网技术与编程讨论区 移动到本区(2013-01-24) —
We have received a number of requests for a comparison. I’d like to thank Nick Retallack, who already did a great job summarizing a lot of these points on our Google Group. Many of his observations are included here.

A bit of the origin story

First of all, I should mention that Brian and I first met the Meteorteam last November when we demoed an early version of Derby at the Keeping it Realtime Conference hosted by &yet. When we met, the Meteorteam had already started on their framework, and the similarities wereobvious. Some time before, I had also met with David Greenspan (whorecently joined Meteor) to pick his brain and learn more about hisexperience writing Etherpad. Our two teams like each other, we’ve been keeping in touch, and we have all learned a lot from each other.
Our teams share a similar vision for a world where all applicationsare realtime and collaborative by default. We as well as a number ofother other developers all had a revelation about a year and a halfago—the way that web apps are currently built makes it painfullydifficult to create the best user experience, where data dynamicallyupdate everywhere.
Brian and I first discussed this vision with each other a year ago. Iwas coming from working as a Product Manager on the Google Search team,and he had been working on a number of open source Node.js projectsincluding Mongoose and everyauth.I was interested in writing a framework, because I believed it was thebest way to write an app with the kind of performance that I desired,and Brian felt that the Node.js community needed an easy to useframework for those developers who preferred tools like Rails and PHP.

The Holy Grail: server and client code sharing

From Google Search, I learned that in order to have a responsive webapp, it is critical to both render pages on the server and in thebrowser. Google can afford to do this, because it has so many engineersand speed is of paramount importance to search. To achieve fast pageloads as well as fast page updates, Google implements pretty much theentire Search front-end in C++ as well as JavaScript. They have beenworking on a number of projects to make this easier over the past coupleof years, but needless to say, such a process is too expensive and slowfor a startup or a complex app.
Gmail, Twitter, and other sites rendered only in the client werepainfully slow to load. Twitter went through the full circle onthis—they started as a server-rendered Rails app, rewrote to render everything in the client,and then realized it took their users 4 seconds to be able to read a140 character message. Now, Twitter renders half the page in Scala onthe server, and they render the other half in JavaScript in the client.This both makes it more difficult for them to maintain a code base inmultiple languages and means that the least important items on the pagepop-in a few seconds after page load. People are very sensitive tomovement, so in effect, they are distracting their users with the leastimportant information after every page load.
Thanks to the awesome re-invention of JavaScript performance startingwith V8 and the ability to easily create JavaScript servers withNode.js, lots of developers are excited about the notion of usingJavaScript for both server and client development. But despite finallyusing the same language, few Node.js applications to date deliver on theamazing ability to share code. Even with a common language, there arestill a lot of issues including very different latency and connectionstability, separate ways of dealing with URLs on the server and in thebrowser, the existence of a DOM in the browser and not on the server,and direct access to a filesystem only on the server.

Let’s get down to business!

So after all that, our teams decided to go in similar directions insome ways, but very different in others. Derby’s goal is to make itpossible for any developer to write apps that load as fast as a searchengine, are as interactive as a document editor, and work offline. Andto quote Geoff,Meteor’s goal is to create “a ‘mass-market’ app platform that could beused for 90% of the sites on the web, and for that 90%, make webdevelopment faster and within reach of more people.”


Currently, Meteor is only available under a GPL license.This means that you must contact them and arrange for a commerciallicense if you do not wish to release your source under the GPL oranother compatible license.
Derby, Racer, and all other components of our framework are releasedunder the permissive MIT license. Thus, you can do pretty much anythingyou want with it (other than sue us), and we can’t stop you or changeour minds later.
I’m no lawyer, so don’t take any of what I just said as legal advice;I don’t have a crystal ball or anything. (Yes, a lawyer once told me tosay that.)

Meteor packages vs. npm

Meteor has created their own package system and means for distributing packages.
Node.js modules are clearly defined by the CommonJS format and thebuilt-in module APIs. However, it does not include a means fordistributing modules. In the early days, Node.js had a few competingpackage managers, but pretty much everyone has now finalized on using npm. It is so universal, that npm is now distributed directly with the official Node.js binary distributions.
Frankly, this is the main thing that concerns me about Meteor. It islikely that many people trying Meteor will never have used Node.jsbefore, and they won’t appreciate the great benefits of distribution vianpm. I and many other developers view npm as one of Node.js’s corestrengths, and I would be very sad to see it weakened by an incompatiblepackage system.
Like pretty much every other Node.js project out there, we primarilydistribute Derby, Racer, and all plugins for these projects as npmmodules. We will continue to break out our projects into smaller modulesso that they can be better reused by others. Perhaps you don’t useDerby, but you need to parse some HTML. We had to write a simple andfast HTML parser for our templates to work, so you’ll be able to usejust that in any Node.js project. Connectis great example of a project that has a rich ecosystem of middlewaredesigned to work with it that are all distributed via npm, and we hopeto follow in the same pattern.

Compatibility with other libraries

Meteor makes it possible to replace parts of it with other libraries.It is especially flexible when it comes to substituting in client-sidelibraries, though those libraries must first be wrapped as a Meteorpackage.
Meteor mostly manages the creation of a server in a custom way. Thismakes it easy to create and deploy a Meteor app to their hostingservice, but it makes it much harder to use Meteor as a module of a moretraditional Node.js server.
In contrast, Derby is just a normal npm module that you can add to any Node.js server. If you want to use any of the 8900 packages in npm (at the moment), simply add them to your package.json file and npm install away!
Derby does not provide any sort of hosting solution, though there arelots of great hosting services for Node.js out there. We will providebetter instructions for how to get Derby apps up and running quickly on apublic server in the future.
Racer (therealtime engine powering Derby’s models) is a separate module, and itcan be used independently of Derby. You could hook pretty much any UIlayer up to Racer and handle the methods that it emits as the model isupdated. Racer is built on top of the very popular Socket.IO module, which you can use directly if you need to.
Derby also uses popular modules at its core, especially Express for routing and Browserify, which can bundle up most Node.js modules for the browser automatically.

MongoDB API vs. Racer methods

Meteor takes the MongoDB API all the way to the browser. The MongoDBAPI is powerful and easy to use from JavaScript. It has also been aroundfor some time, so there are well established patterns for using it domost things that an application might need to do. A lot of people seemto think this is a fun way to build apps, and it reduces need tounderstand multiple layers of abstraction. Some have expressed concernsover the security implications, but I think we should reserve judgmentuntil the Meteor team has more time to address what they think is thebest approach for authentication and authorization.
Racer has its own API based around a set of mutator methods andpaths. This API maps pretty much 1:1 with any document store, includingMongoDB. This has some pluses and minuses, but we believe it is theright choice for a few reasons:

Conflict resolution

Paths and methods map well to conflict detection techniques that wethink will be one of the major benefits of using Racer. For now, ourdefault mode is last-writer-wins, which is equivalent to how Meteorsaves data. However, we have preliminary implementations of conflictresolution via Software Transactional Memory and OperationalTransformation methods. Such techniques will make it possible to use aDerby app offline and then resync correctly. It will also make itpossible to easily add features like Google-Docs-style realtimecollaborative text editing in any text box.

Datastore portability

Our paths and methods are granular enough to take advantage of thecapabilities of most datastores, but it is possible to switch from onedatastore to another or to use them with multiple datastoressimultaneously. Swapping in Riak, Postgres, CouchDB, or another serviceshould be straightforward without modifying application code.

Efficient PubSub

Paths map well to PubSub, which is how we propagate changes inrealtime. In contrast, Meteor’s LiveMongo implementation simply writesto the database and polls it frequently for the data in use by everyconnected client. The advantage to polling is that it can supportsubscriptions to pretty much any kind of Mongo query, but we haveimplemented most queries and query PubSub without needing to poll thedatabase. We have no real-world evidence yet, but we expect PubSub toscale much better than database polling.

API plugins

It will be possible to create plugins that act like datastores, eventhough they are communicating with a backend service or a 3rd party API.Database adapters are built on top of a system of routes that can beused in a custom manner.

Server rendering and shared routes

Derby is one of the only frameworks designed to run all rendering androuting code on the server and in the browser. It’s even possible touse Derby to render static pages that share templates with dynamic apps.
This means you get crazy fast page loads with no effort. Even for asimple client-rendered app, pages typically take a second or two to loadand then be displayed to the user. Simple Derby apps can fire theonload event in less than 200ms. As apps get more complex, serverrendering has an even more drastic effect.
Lots of big companies including Google, Amazon, and Facebook dedicatemassive resources to optimizing page load time, because it directlytranslates into better conversion rates and more revenue. I died alittle bit inside the day Gmail added a loading progress bar. Don’t dothat.
In addition, server-rendering is critical for search engineoptimization, and it provides accessibility to screen readers andbrowsers without JavaScript.
Derby exposes routes as anExpress middleware on the server, so you can use it alongside otherserver-only Express routes for tasks like uploading files, and you caneven write multiple apps that handle different sets of routes on thesame Express server. For example, you might write a separate admin appor a separate mobile app that doesn’t load all of the code for a desktopbrowser app.
While Derby gives you all of the speed and accessibility advantagesof a more traditional multi-page app, it also creates fully optimizedsingle-page applications that can render any template or route in thebrowser. Client-side routes simply render any links that they canwithout doing a page refresh; you don’t have to call methods on aspecial browser-side routing API. Just put a normal HTML link on thepage, and Derby will render it client-side.
Meteor does not have these features yet, though they recently rewrote their templating engine to use strings so that it is now possible for them to add.

Model-view data bindings

Meteor uses a reactive functional programming approach to updatingtemplates that could potentially work with any template engine. As atemplate is rendered, all of the data that is used to render thattemplate is assumed to be an input to that chunk of the UI. Later, whenthat data changes, the template is re-rendered, and its output iscompared with the DOM. Meteor then patches up the DOM to apply theminimum required changes. Effectively, every single variable andfunction in a template is bound. The big advantage to this approach isits simplicity and ability to support any template language.
In contrast, Derby has its own template language based on Handlebars. Bindingsare declared explicitly, and the HTML of the template is parsed inorder to figure out which parts of the DOM need to be updated. UnlikeMeteor’s, Derby’s bindings are two way; when form elements are bound,the model is automatically updated as users type in text inputs, checkcheckboxes, and select items in drop downs. In addition, it is possibleto bind everything or to optimize the performance of templates by onlybinding what is necessary. Outputting non-bound data may also bepreferred if a developer wishes to update the view via manual DOMmanipulation in special cases.

DOM event handlers

It is a relatively minor difference, but Meteor uses CSS selectors onspecific templates, and Derby uses HTML attributes within templates todeclare event handlers. jQuery and Backbone have popularized the CSS selector method of scoping event handlers. Knockout and Angular use HTML attributes.
We prefer the HTML markup approach,because it is more work to figure out what CSS selector matches thecorrect elements, and it is reasonably likely that HTML structure willchange and silently break CSS selectors. With the markup approach, it isless likely that function names will be changed inadvertently, and anerror will be thrown when the function can no longer be found.
Derby also has an innovative approach to event bubbling that is moreefficient and intuitive compared to typical event bubbling. Instead ofbubbling up the entire DOM to the root documentElement for every event,Derby will stop bubbling once it finds an element that is bound to theevent. Like with routes, bubbling can be continued by calling a next() method passed to the event handler.


Meteor uses the Fibersextension for Node.js that makes it possible to write synchronouslooking code on the server instead of the more common callback styleused by most Node.js projects. Some prefer this way of writingasynchronous code, others strongly disagree with it. There are a numberof arguments on both sides.
This is very contentious issue at the moment, and we prefer to stay out of it. A very small percentage of modules in npm are written this way, so we have stuck to the more traditional Node.js style of callbacks.

Wrapping it up

You can achieve many of the same things with both frameworks. Bothare powerful tools for implementing features that are very difficult towrite in more traditional web frameworks like Rails and PHP.
Derby has been more focused on making sure it can support advancedfeatures like conflict detection, offline clients, and extremely fastrendering. We are also more focused on compatibility with other modulesin the existing Node.js ecosystem, and we have a permissive open sourcelicense.
Ultimately, we are all trying to create the best tools fordevelopers, and competition can help to breed innovation. We are happyto see other approaches like Meteor, SpaceMagic, and Firebase, because we will all learn from each other. We will end up with better tools, a better web, and better experiences for users.
If you’re interested in what we’re working on, follow us on Twitter and GitHub.
限100 字节
上一个 下一个