{"id":928,"date":"2018-03-25T16:55:44","date_gmt":"2018-03-25T13:55:44","guid":{"rendered":"https:\/\/iamakulov.com\/notes\/?p=928"},"modified":"2018-03-25T17:47:51","modified_gmt":"2018-03-25T14:47:51","slug":"backend-nodejs","status":"publish","type":"post","link":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/","title":{"rendered":"Backend for front-end devs: Part 1, Node.js"},"content":{"rendered":"<p>A few months ago, I had to build a full-stack app having only front-end experience. This is an overview of backend tools and practices if you discover yourself in the same situation.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png\" alt=\"\" width=\"1500\" height=\"787\" class=\"alignnone size-full wp-image-1057\" srcset=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png 1500w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46-300x157.png 300w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46-768x403.png 768w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46-1024x537.png 1024w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46-1200x630.png 1200w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<h2 id=\"write-backend-app\" id=\"write-backend-app\" id=\"write-backend-app\">I\u2019m a front-end dev, but I need to write a full-stack app. What to do?<a href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#write-backend-app\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>To write an app, you\u2019ll have to figure out three things: a programming language for the backend, a database to store data, and infrastructure.<\/p>\n<p>Popular backend languages include Ruby, Python, JavaScript (Node.js), Java and PHP. <mark>If you\u2019re a front-end developer, start with Node.js<\/mark> \u2013 things would be way easier.<\/p>\n<p>I\u2019ll cover databases and infrastructure in the next parts.<\/p>\n<h2 id=\"nodejs\" id=\"nodejs\" id=\"nodejs\">OK, I\u2019ve just installed Node.js. What is it?<a href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#nodejs\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Node.js enables you to write servers in JavaScript. It\u2019s a JavaScript engine similar to the one Google Chrome has. You pass it a JS file, and the engine runs it:<\/p>\n<pre><code class=\"javascript\">\/\/ index.js\r\nconsole.log('42');\r\n<\/code><\/pre>\n<pre><code class=\"bash\"># Shell\r\n$ node .\/index.js\r\n42\r\n<\/code><\/pre>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'><a href='https:\/\/nodejs.org\/api\/net.html#net_net_createserver_options_connectionlistener'><code>createServer()<\/code> docs<\/a><\/div>\n<div class='annotated-element__content'>\n<p>To launch a real server, you\u2019ll need to call a specific method provided by Node.js (e.g, <code>createServer()<\/code> from the <code>net<\/code> module). In practice, a few people do this \u2013 almost everyone uses high-level wrappers.<\/p>\n<\/div>\n<\/div>\n<h2 id=\"callbacks\" id=\"callbacks\" id=\"callbacks\">I\u2019ve heard a bit about Node.js and callbacks. What\u2019s the deal with them?<a href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#callbacks\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'>Callback is a function that you pass into other function. It\u2019s called when a specific action completes. <a href='https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/Callback_function'>MDN docs<\/a><\/div>\n<div class='annotated-element__content'>\n<p>The primary thing you need to know about Node.js is that it performs all long actions (like reading data from a database) asynchronously \u2013 using callbacks. This means that to make a DB request, you don\u2019t do this:<\/p>\n<pre><code class=\"js\">const data = sql.query('SELECT name from users');\r\nconsole.log(data);\r\n<\/code><\/pre>\n<p>but do this instead:<\/p>\n<pre><code class=\"js\">sql.query('SELECT name from users', (error, data) =&gt; {\r\n  console.log(data);\r\n});\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'>Related: <a href='https:\/\/nodesource.com\/blog\/why-asynchronous\/'>Why Asynchronous?<\/a> \u00b7 <a href='https:\/\/nodesource.com\/blog\/understanding-the-nodejs-event-loop\/'>Understanding Node.js Event Loop<\/a><\/div>\n<div class='annotated-element__content'>\n<p>Under the hood, Node.js sends a request to the database and immediately continues executing the code. And when the request completes, Node.js calls the callback and passes the data to it. This helps to write servers that handle lots of requests at the same time.<\/p>\n<\/div>\n<\/div>\n<h2 id=\"no-callbacks\" id=\"no-callbacks\" id=\"no-callbacks\">Can I write code without callbacks?<a href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#no-callbacks\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Yes. If you don\u2019t like passing functions into other functions, there\u2019re a couple of alternatives:<\/p>\n<ul>\n<li>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'><a href='https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Promise'>What a promise is<\/a><\/div>\n<div class='annotated-element__content'>\n<p><b>Option A:<\/b> use promises instead of callbacks. You\u2019ll still have to pass functions around \u2013 but you\u2019ll write code without excessive nesting which often happens with callbacks:<\/p>\n<\/div>\n<\/div>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'>Use <a href='https:\/\/nodejs.org\/api\/util.html#util_util_promisify_original'><code>util.promisify<\/code><\/a> to adapt native callback-based APIs to promises<\/div>\n<div class='annotated-element__content'>\n<pre><code class=\"js\">\/\/ With callbacks\r\nconst fs = require('fs');\r\n\r\nfs.readFile('.\/text.txt', (err, data) => {\r\n  console.log(data);\r\n});\r\n\r\n\/\/ With promises\r\nconst fs = require('fs');\r\nconst util = require('util');\r\nconst readFile = util.promisify(fs.readFile);\r\n\r\nreadFile('.\/text.txt')\r\n  .then((data) => {\r\n    console.log(data);\r\n  })\r\n  .catch((err) => {\r\n    \/\/ ...\r\n  });\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/li>\n<li>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'><a href='https:\/\/hackernoon.com\/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9'>What <code>async\/await<\/code> is<\/a><\/div>\n<div class='annotated-element__content'>\n<p><b>Option B:<\/b> use <code>async\/await<\/code> with promise APIs. This lets you write code that looks synchronous:<\/p>\n<\/div>\n<\/div>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'><code>async\/await<\/code> is available with Node.js 7.6+.<\/div>\n<div class='annotated-element__content'>\n<pre><code class=\"js\">\/\/ With callbacks\r\nconst fs = require('fs');\r\n\r\nfs.readFile('.\/text.txt', (err, data) => {\r\n  console.log(data);\r\n});\r\n\r\n\/\/ With async\/await\r\nconst fs = require('fs');\r\nconst util = require('util');\r\nconst readFile = util.promisify(fs.readFile);\r\n\r\ntry {\r\n  const data = await readFile('.\/text.txt')\r\n  console.log(data);\r\n} catch (err) {\r\n  \/\/ ...\r\n};\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<p>Many native Node.js APIs (like <a href=\"https:\/\/nodejs.org\/api\/fs.html#fs_fs_readfile_path_options_callback\"><code>fs.readFile<\/code><\/a>) also have synchronous alternatives (like <a href=\"https:\/\/nodejs.org\/api\/fs.html#fs_fs_readfilesync_path_options\"><code>fs.readFileSync<\/code><\/a>):<\/p>\n<pre><code class=\"js\">const fs = require('fs');\r\nconst data = fs.readFileSync('.\/text.txt');\r\n<\/code><\/pre>\n<p>However, avoid using them on real servers \u2013 or the server would die just from a few simultaneous clients. (These APIs are useful in console scripts though.)<\/p>\n<h2 id=\"server\" id=\"server\" id=\"server\">OK, how do I create a server?<a href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#server\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Use <a href=\"https:\/\/github.com\/expressjs\/express\">Express<\/a>:<\/p>\n<pre><code class=\"javascript\">const express = require('express');\r\nconst app = express();\r\n\r\n\/\/ \u2193 Define a REST request\r\napp.get('\/api\/user', (req, res) => {\r\n  res.json({ name: 'Jason Bourne' });\r\n});\r\n\r\n\/\/ \u2193 Ask the server to return statis files\r\n\/\/ from the `public` dir (if the \/api\/user route didn\u2019t match)\r\napp.use('*', express.static('public'));\r\n\r\napp.listen(3000, () => {\r\n  console.log('Server is listening on port 3000')\r\n});\r\n<\/code><\/pre>\n<p>Express is useful for building static servers and REST APIs.<\/p>\n<h2 id=\"real-app\" id=\"real-app\" id=\"real-app\">How do I build something real?<a href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#real-app\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>In a real app, apart from an HTTP server, you\u2019ll need to implement a few more things. Here\u2019re the common solutions for them:<\/p>\n<ul>\n<li><b>Authorization:<\/b> <a href=\"https:\/\/github.com\/jaredhanson\/passport\">Passport.js<\/a>. Passport.js works with login-password pairs, social networks, OAuth and lots of other login strategies. A SaaS solution like <a href=\"https:\/\/auth0.com\/\">Auth0<\/a> is also an option<\/li>\n<li><b>Validating requests:<\/b> <a href=\"https:\/\/github.com\/ctavan\/express-validator\">express-validator<\/a>. express-validator normalizes and validates REST data you recieve from the clients<\/li>\n<li><b>Sending emails:<\/b> <a href=\"https:\/\/nodemailer.com\/transports\/\">Nodemailer<\/a>. Nodemailer works with SMTP; it also has simplified settings for AWS Simple Email Service<\/li>\n<li><b>Password hashing:<\/b> <a href=\"https:\/\/www.npmjs.com\/package\/bcrypt\">bcrypt<\/a>. Important: learn <a href=\"https:\/\/crackstation.net\/hashing-security.htm\">how to store and hash passwords properly<\/a><\/li>\n<li><b>Logging:<\/b> <a href=\"https:\/\/www.npmjs.com\/package\/loglevel\">loglevel<\/a>, <a href=\"https:\/\/www.npmjs.com\/package\/debug\">debug<\/a>, or <a href=\"https:\/\/www.npmjs.com\/package\/winston\">winston<\/a>. I haven\u2019t found a perfectly satisfying solution<\/li>\n<li><b>Running the app in production:<\/b> <a href=\"https:\/\/www.npmjs.com\/package\/pm2\">PM2<\/a>. PM2 restarts an app in case of crashes, deploys a new version without a downtime, distributes the load to multiple instances and allows to deploy remotely<\/li>\n<\/ul>\n<p>That\u2019s it! The next part of the guide will introduce you into databases (specifically, into MySQL).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few months ago, I had to build a full-stack app having only front-end experience. This is an overview of backend tools and practices if you discover yourself in the same situation. I\u2019m a front-end dev, but I need to write a full-stack app. What to do?# To write an app, you\u2019ll have to figure &hellip; <a href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Backend for front-end devs: Part 1, Node.js&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[21,20],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Backend for front-end devs: Part 1, Node.js - Ivan Akulov\u2019s blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Backend for front-end devs: Part 1, Node.js\" \/>\n<meta property=\"og:description\" content=\"An overview of Node.js and popular libraries\" \/>\n<meta property=\"og:url\" content=\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/\" \/>\n<meta property=\"og:site_name\" content=\"Ivan Akulov\u2019s blog\" \/>\n<meta property=\"article:publisher\" content=\"http:\/\/facebook.com\/iamakulov.page\" \/>\n<meta property=\"article:published_time\" content=\"2018-03-25T13:55:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-03-25T14:47:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1500\" \/>\n\t<meta property=\"og:image:height\" content=\"787\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Ivan Akulov\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Backend for front-end devs: Part 1, Node.js\" \/>\n<meta name=\"twitter:description\" content=\"An overview of Node.js and popular libraries\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-40-23.png\" \/>\n<meta name=\"twitter:creator\" content=\"@iamakulov\" \/>\n<meta name=\"twitter:site\" content=\"@iamakulov\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ivan Akulov\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/\",\"url\":\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/\",\"name\":\"Backend for front-end devs: Part 1, Node.js - Ivan Akulov\u2019s blog\",\"isPartOf\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png\",\"datePublished\":\"2018-03-25T13:55:44+00:00\",\"dateModified\":\"2018-03-25T14:47:51+00:00\",\"author\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81\"},\"breadcrumb\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#primaryimage\",\"url\":\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png\",\"contentUrl\":\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png\",\"width\":1500,\"height\":787},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/iamakulov.com\/notes\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Backend for front-end devs: Part 1, Node.js\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/iamakulov.com\/notes\/#website\",\"url\":\"https:\/\/iamakulov.com\/notes\/\",\"name\":\"Ivan Akulov\u2019s blog\",\"description\":\"Ivan Akulov writes about his front-end experience, React, webpack, and performance optimizations.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/iamakulov.com\/notes\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81\",\"name\":\"Ivan Akulov\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g\",\"caption\":\"Ivan Akulov\"},\"description\":\"I'm a software engineer specializing in web performance, JavaScript, and React. I\u2019m also a Google Developer Expert. I work at Framer.\",\"sameAs\":[\"http:\/\/iamakulov.com\",\"https:\/\/x.com\/iamakulov\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Backend for front-end devs: Part 1, Node.js - Ivan Akulov\u2019s blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/","og_locale":"en_US","og_type":"article","og_title":"Backend for front-end devs: Part 1, Node.js","og_description":"An overview of Node.js and popular libraries","og_url":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/","og_site_name":"Ivan Akulov\u2019s blog","article_publisher":"http:\/\/facebook.com\/iamakulov.page","article_published_time":"2018-03-25T13:55:44+00:00","article_modified_time":"2018-03-25T14:47:51+00:00","og_image":[{"width":1500,"height":787,"url":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png","type":"image\/png"}],"author":"Ivan Akulov","twitter_card":"summary_large_image","twitter_title":"Backend for front-end devs: Part 1, Node.js","twitter_description":"An overview of Node.js and popular libraries","twitter_image":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-40-23.png","twitter_creator":"@iamakulov","twitter_site":"@iamakulov","twitter_misc":{"Written by":"Ivan Akulov","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/","url":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/","name":"Backend for front-end devs: Part 1, Node.js - Ivan Akulov\u2019s blog","isPartOf":{"@id":"https:\/\/iamakulov.com\/notes\/#website"},"primaryImageOfPage":{"@id":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#primaryimage"},"image":{"@id":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#primaryimage"},"thumbnailUrl":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png","datePublished":"2018-03-25T13:55:44+00:00","dateModified":"2018-03-25T14:47:51+00:00","author":{"@id":"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81"},"breadcrumb":{"@id":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/iamakulov.com\/notes\/backend-nodejs\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#primaryimage","url":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png","contentUrl":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2018\/03\/ApplicationFrameHost_2018-03-25_16-39-46.png","width":1500,"height":787},{"@type":"BreadcrumbList","@id":"https:\/\/iamakulov.com\/notes\/backend-nodejs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/iamakulov.com\/notes\/"},{"@type":"ListItem","position":2,"name":"Backend for front-end devs: Part 1, Node.js"}]},{"@type":"WebSite","@id":"https:\/\/iamakulov.com\/notes\/#website","url":"https:\/\/iamakulov.com\/notes\/","name":"Ivan Akulov\u2019s blog","description":"Ivan Akulov writes about his front-end experience, React, webpack, and performance optimizations.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/iamakulov.com\/notes\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81","name":"Ivan Akulov","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g","caption":"Ivan Akulov"},"description":"I'm a software engineer specializing in web performance, JavaScript, and React. I\u2019m also a Google Developer Expert. I work at Framer.","sameAs":["http:\/\/iamakulov.com","https:\/\/x.com\/iamakulov"]}]}},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/928"}],"collection":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/comments?post=928"}],"version-history":[{"count":63,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/928\/revisions"}],"predecessor-version":[{"id":1061,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/928\/revisions\/1061"}],"wp:attachment":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/media?parent=928"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/categories?post=928"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/tags?post=928"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}