Node.js vs Play Framework (with Japanese subtitles)

  • Published on
    15-Jan-2015

  • View
    24.136

  • Download
    3

Embed Size (px)

DESCRIPTION

Video: http://www.nicovideo.jp/watch/1410857293 Here's the showdown you've been waiting for: Node.js vs Play Framework. Both are popular open source web frameworks that are built for developer productivity, asynchronous I/O, and the real time web. But which one is easier to learn, test, deploy, debug, and scale? Should you pick Javascript or Scala? The Google v8 engine or the JVM? NPM or Ivy? Grunt or SBT? Two frameworks enter, one framework leaves. This version of the presentation has Japanese subtitles. For the English only version, see http://www.slideshare.net/brikis98/nodejs-vs-play-framework

Transcript

<ul><li> 1. VSNode.js vs Play Framework</li></ul><p> 2. Node.js: server-side JavaScript runtime environment;open source; single threaded; non-blocking I/O.Node.js: JSOSSI/O 3. express.js: the most popular webframework for Node.js.express.js: Node.js Web 4. Play Framework: Java/Scala web framework; opensource; multithreaded; non-blocking I/O.Play: Java/Scala WebOSSI/O 5. Yevgeniy BrikmanFormer Play Tech Lead at LinkedIn. Long time Node.js user.LinkedInPlay Tech LeadNode.js 6. The framework scorecardLearnDevelopTestSecureBuildDeployDebugScaleMaintainShare 7. For each feature we discuss...1Much worse than most frameworksAbout the same as most frameworksMuch better than most frameworks5101 = 5 = 10 = 8. The framework scorecardLearnDevelopTestSecureBuildDeployDebugScaleMaintainShare 9. Node.js: 1-click installers for every OSOS 10. var http = require('http');http.createServer(function (req, res) {res.writeHead(200, {'Content-Type': 'text/plain'});res.end('Hello Worldn');}).listen(1337, '127.0.0.1');console.log('Server running at http://127.0.0.1:1337/');server.jsThe Hello World Node app: 1 file, 6 lines of code. 11. var express = require('express');var app = express();app.get('/', function(req, res){res.send('Hello World');});var server = app.listen(1337, function() {console.log('Listening on port %d', server.address().port);});server.jsThe Hello World Express app: 1 file, 8 lines of code. 12. Run using node . Starts instantly! 13. Hit http://localhost:1337 to test 14. nodeschool.io 15. Node Beginner Book, Mastering Node.js,Node: Up and Running, Node.js in Action 16. Node API Docs 17. Express.js guide 18. Express Web Application Development Express.js Guide 19. Express.js API docs 20. And much, much moreTons of resources; very gradual learning curve. 21. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 22. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 23. Play: download from playframework.com,extract, add activator to your PATHPlayactivator PATH 24. Generate a new app using activator new 25. The Hello World Play app: ~35 files and folders 26. Run the app using activator run 27. (Downloading all dependencies can take awhile the first time around)jar 28. Hit http://localhost:9000 to test 29. Play Framework Documentation 30. Activator Templates 31. Play for Scala Learning Play Framework 2 32. Ultimate Guide to Getting Started with Play.Not as many resources; steep learning curve. 33. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 7 34. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 7 35. GET clients/:id Clients.show(id: Long)def show(id: Long) = Action { request =&gt;getClient(id).map { client =&gt;Ok(views.html.clients.show(client))}}Routingapp.get('clients/:id', function(req, res) {getClient(req.params.id, function(client) {res.render('show', client);});});RESTful routing. Extracts query &amp; pathparams.RESTful routing. Extracts query &amp; pathparams. Type safe. Actions arecomposable. Reverse routing. 36. @(name: String, headline: String)</p> <div>@name<div>Headline: @headline</div></div> <p>Templates</p> <div>{{name}}<div>Headline: {{headline}}</div></div> <p>Many template options: handlebars,mustache, dust, jade, etc. Most supportclient-side rendering!Twirl templates are compiled into Scalafunctions: type safe and composable!Other template types via plugins. 37. i18nTranslations: i18next-node, i18n-node.Formatting: moment.js, numeral.js.Translations: Play i18n API.Formatting: Java formatting libraries.</p> <div>{{name}}<div>{{t "headline.label" headline=headline}}</div></div> <p>@(name: String, headline: String)</p> <div>@name<div>Messages("headline.label", headline)</div></div> <p> 38. var regForm = forms.create({name: fields.string({required: true}),age: fields.number({min: 18})Forms, node-formidable, validator.js. Play form binding and validation API.Form binding and validation});regForm.handle(req, {success: function(form) { ... },error: function(form) { ... }});val regForm = Form(mapping("name" -&gt; nonEmptyText,"age" -&gt; number(min = 18))(UserData.apply)(UserData.unapply))regForm.bindFromRequest.fold(err =&gt; BadRequest("Validation error"),data =&gt; Ok(s"Hi $data.name!")) 39. // Automatically parse application/json bodyapp.use(bodyParser.json());app.post('/clients', function (req, res, next) {var name = req.body.name;var age = req.body.age;res.send(name + " is " + age + " years old.");});POST /clients Clients.createcase class Person(name: String, age: Int)implicit val prsnFmt = Json.format[Person]def create = Action(parse.json) { request =&gt;val person = request.body.as[Person]Ok(s"$person.name is $person.age years old")}bodyParser, xml2js, node-formidable. Play JSON, XML, File Upload APIs.JSON, XML, File Upload 40. DataSlick, Anorm, Ebean, JPAMySQL, MariaDB, PostgreSLQ, SQLite, Oracle, SQL Server,DB2, Derby, H2Sequelize, Bookshelf.js, node-orm2 SQLMySQL, MariaDB, PostgreSQL, SQLiteNoSQLmongojs/mongoose, cassandra-client,cradle/nano, node_redis, node-neo4jMongoDB, Cassandra, CouchDB, Redis, Neo4jReactiveMongo, DataStax, sprouch, play-plugins-redis, Neo4j-play, JPAMongoDB, Cassandra, CouchDB, Redis, Neo4jnode-memcached, connect-cache Cachingmemcached, in-memory (not recommended)play2-memcached, memcontinuationed,Play Cache, ehcache, Guavamemcached, in-memorynode-db-migrate, node-migrate Schemas Play database evolutions 41. socket.io: server &amp; client APIs;WebSockets, Flash Sockets, polling, etc.Play WebSockets, Comet, andEventSource APIs. Server-side only.Real-time web// server codeio.on('connection', function (socket) {socket.emit('msg', 'Server says hi!');socket.on('msg', function (msg) { });});def chat = WebSocket.acceptWithActor {request =&gt; out =&gt; Props(new Chat(out))}class Chat(out: ActorRef) extends Actor {def receive = {case m: String =&gt; out ! s"Got msg: $m"}}// client codesocket.emit('msg', 'Client says hi!');socket.on('msg', function (msg) { }); 42. Express.js is a minimal framework Play is a full stack framework You need plugins for most tasks Finding good plugins takes time Gluing plugins together takes time There are defaults for most tasks Defaults are mostly high quality All defaults can be replacedExpress.jsPlay 43. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 10 44. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 10 45. Unit testing: Jasmine, Mocha, QUnit,nodeunit, Expresso or Vows 46. var request = require('supertest'), app = require('express')();app.get('/user', function(req, res){res.send(200, { name: 'tobi' });});request(app).get('/user').expect('Content-Type', /json/).expect(200);Functional testing: use supertest or callserver.listen directly. 47. UI testing: phantom.js or zombie.js 48. Code coverage: Istanbul or Blanket.js 49. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 50. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 51. Unit testing: junit, ScalaTest, specs2, or testng 52. "respond to the index Action" in new App(FakeApplication()) {val Some(result) = route(FakeRequest(GET, "/Bob"))status(result) mustEqual OKcontentType(result) mustEqual Some("text/html")charset(result) mustEqual Some("utf-8")contentAsString(result) must include ("Hello Bob")}Functional testing: use Plays built-infunctional test helpers. 53. class ExampleSpec extends PlaySpec with OneServerPerSuite with OneBrowserPerSuite {"The OneBrowserPerTest trait" must {"provide a web driver" in {go to (s"http://localhost:$port/testing")pageTitle mustBe "Test Page"click on find(name("b")).valueeventually { pageTitle mustBe "scalatest" }}}}UI testing: use Plays built-in integration testhelpers and built-in Selenium support. 54. Code coverage: jacoco4sbt or scct 55. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 10 56. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 10 57. (not enabled by default!) Connect CSRF Middleware CSRF(not enabled by default!)Depends on template engine XSS Twirl escapes correctlyVulnerabilities: eval, setTimeout, InjectionSecurityCSRFFiltersetInterval, new Function Few vulnerabilities of this sortHelmet middleware Headers SecurityHeadersFilterpassport.js, everyauth Auth SecureSocial, deadbolt, play-authenticateNode Security Project Advisories Play Security Vulnerabilities 58. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 8 59. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 8 60. {"name": "Hello World App","version": "0.0.3","dependencies": {"express": "4.8.0","underscore": "1.6.0"},"scripts": {"test": "node tests/run.js"}}Node.js uses NPM to manage dependencies andbasic build commandsNode.jsNPM 61. Many options available for more complicatedbuilds: grunt.js, gulp.js, or broccoligrunt.js, gulp.js, broccoli 62. Thousands of plugins for all common build tasks 63. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 64. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 65. Play uses SBT as the build system. SBT is aninteractive build system.Play SBT 66. object AppBuild extends Build {lazy val root = Project(id = "root", base = file(".")).settings(name := "test-play-app",version := version,libraryDependencies += Seq("org.scala-tools" % "scala-stm_2.11.1" % "0.3","org.apache.derby" % "derby" % "10.4.1.3"))def version = Option(System.getProperty("version")).getOrElse("0.0.3")}In SBT, build definitions are written in Scala! But the learning curve is very steep.Scala 67. Dependencies are managed using Ivy:familiar, but slow.Ivy 68. Play uses sbt-web to build static content: fewplugins; depends on Rhino (slow) or node.js (!).Playsbt-web 69. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 7 70. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 7 71. Many node-friendly hosting options: Heroku,Joyent, Azure, OpenShift, NodejitsuNode.js 72. Monitoring: New Relic, Nodetime,AppDynamics, node-monitor 73. if (cluster.isMaster) {for (var i = 0; i &lt; numCPUs; i++) {cluster.fork(); // Fork workers}cluster.on('exit', function(worker, code, signal) {console.log('worker ' + worker.process.pid + ' died');});} else {http.createServer(function(req, res) {// ...}).listen(8000);}Use cluster to run one node instance per CPUcluster 74. Use forever, monit, or Domain to handle crashes. 75. {"dbConfig": {"host": "localhost","port": 5984,"dbName": "customers"}}config/default.jsonvar config = require('config');var host = config.get('dbConfig.host');server.jsConfiguration: node-config or nconf 76. Use nginx, apache, or ATS to load balance,serve static content, terminate SSLClientData CenterReverse proxy(e.g. nginx) DBStatic server(e.g. nginx)NodeinstNaondceeinstNaondceeinstNaondceeinstNaondceeinstanceNodeinstNaondceeinstNaondceeinstNaondceeinstanceNodeinstNaondceeinstNaondceeinstNaondceeinstanceSSL Termination 77. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 78. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 79. A few Play-friendly hosting options: Heroku,playframework-cloud, CloudBeesPlay 80. Monitoring: New Relic, metrics-play 81. Use the SBT Native Packager to package theapp as tgz, deb, RPM, etc.App 82. dbConfig = {host: "localhost",port: 5984,dbName: "customers"}conf/application.confval host = Play.current.configuration.getString("dbConfig.host")app/controllers/Application.scalaConfiguration: Play comes with Typesafe Config 83. Use nginx, apache, or ATS to load balance,serve static content, terminate SSLClientData CenterReverse proxy(e.g. nginx)Play appDBStatic server(e.g. nginx)Play appPlay app 84. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 7 85. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 7 86. Node.js: use IntelliJ or node-inspector to debugNode.jsIntelliJ 87. Use DTrace, TraceGL, node-stackviz, and node-profilerto debug perf issues 88. var winston = require("winston");winston.info("CHILL WINSTON! ... I put it in the logs.");Use winston, log4js, or bunyan for logging 89. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 710 90. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 710 91. Play runs on the JVM, so you can use yourfavorite IDE to debug: IntelliJ, Eclipse, NetBeansPlayIDE 92. In dev, Play shows errors right in the browser 93. Use YourKit, VisualVM, BTrace, and jmap todebug perf issues 94. Use logback, slf4j, or log4j for logging 95. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 710 10 96. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 710 10 97. Part 1: scaling for lots of traffic 98. TechEmpower benchmarks.Warning: microbenchmarks are not a substitute for real world perf testing! 99. JSON serialization 100. Single query(Note: JDBC is blocking!) 101. Multiple queries(Note: JDBC is blocking!) 102. Internet LoadBalancerFrontendServerFrontendServerFrontendServerBackendServerBackendServerBackendServerBackendServerBackendServerDataStoreDataStoreDataStoreDataStoreLinkedIn experience #1: Play and Node.js are veryfast in a service oriented architecture with NIO.LinkedInNode.jsPlay 103. // BAD: write files synchronouslyfs.writeFileSync('message.txt', 'Hello Node');console.log("It's saved, but you just blocked ALL requests!");// Good: write files asynchronouslyfs.writeFile('message.txt', 'Hello Node', function (err) {console.log("It's saved and the server remains responsive!");});LinkedIn experience #2: Play is ok with blocking I/O&amp; CPU/memory bound use cases. Node.js is not.I/OCPUNode.js 104. Part 2: scaling for large teams and projects 105. Node.js: best for small projects, short projects, small teams.Node.js 106. Play: best for longer projects. Slower ramp up, but scales well with team &amp; project size.Play 107. For comparison: Spring MVC 108. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 710101010 109. LearnDevelopTestSecureBuildThe framework scorecardDeployDebugScaleMaintainShare10 78 1010 106 810 78 710101010 110. Maintenance: the good parts 111. Functional programming: first class functions,closures, underscore.js 112. JavaScript is ubiquitous...JS 113. ...Which means you can share devel...</p>