Table of Contents for
Node.js 8 the Right Way

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Node.js 8 the Right Way by Jim Wilson Published by Pragmatic Bookshelf, 2018
  1. Title Page
  2. Node.js 8 the Right Way
  3. Node.js 8 the Right Way
  4. Node.js 8 the Right Way
  5. Node.js 8 the Right Way
  6.  Acknowledgments
  7.  Preface
  8. Why Node.js the Right Way?
  9. What’s in This Book
  10. What This Book Is Not
  11. Code Examples and Conventions
  12. Online Resources
  13. Part I. Getting Up to Speed on Node.js 8
  14. 1. Getting Started
  15. Thinking Beyond the web
  16. Node.js’s Niche
  17. How Node.js Applications Work
  18. Aspects of Node.js Development
  19. Installing Node.js
  20. 2. Wrangling the File System
  21. Programming for the Node.js Event Loop
  22. Spawning a Child Process
  23. Capturing Data from an EventEmitter
  24. Reading and Writing Files Asynchronously
  25. The Two Phases of a Node.js Program
  26. Wrapping Up
  27. 3. Networking with Sockets
  28. Listening for Socket Connections
  29. Implementing a Messaging Protocol
  30. Creating Socket Client Connections
  31. Testing Network Application Functionality
  32. Extending Core Classes in Custom Modules
  33. Developing Unit Tests with Mocha
  34. Wrapping Up
  35. 4. Connecting Robust Microservices
  36. Installing ØMQ
  37. Publishing and Subscribing to Messages
  38. Responding to Requests
  39. Routing and Dealing Messages
  40. Clustering Node.js Processes
  41. Pushing and Pulling Messages
  42. Wrapping Up
  43. Node.js 8 the Right Way
  44. Part II. Working with Data
  45. 5. Transforming Data and Testing Continuously
  46. Procuring External Data
  47. Behavior-Driven Development with Mocha and Chai
  48. Extracting Data from XML with Cheerio
  49. Processing Data Files Sequentially
  50. Debugging Tests with Chrome DevTools
  51. Wrapping Up
  52. 6. Commanding Databases
  53. Introducing Elasticsearch
  54. Creating a Command-Line Program in Node.js with Commander
  55. Using request to Fetch JSON over HTTP
  56. Shaping JSON with jq
  57. Inserting Elasticsearch Documents in Bulk
  58. Implementing an Elasticsearch Query Command
  59. Wrapping Up
  60. Node.js 8 the Right Way
  61. Part III. Creating an Application from the Ground Up
  62. 7. Developing RESTful Web Services
  63. Advantages of Express
  64. Serving APIs with Express
  65. Writing Modular Express Services
  66. Keeping Services Running with nodemon
  67. Adding Search APIs
  68. Simplifying Code Flows with Promises
  69. Manipulating Documents RESTfully
  70. Emulating Synchronous Style with async and await
  71. Providing an Async Handler Function to Express
  72. Wrapping Up
  73. 8. Creating a Beautiful User Experience
  74. Getting Started with webpack
  75. Generating Your First webpack Bundle
  76. Sprucing Up Your UI with Bootstrap
  77. Bringing in Bootstrap JavaScript and jQuery
  78. Transpiling with TypeScript
  79. Templating HTML with Handlebars
  80. Implementing hashChange Navigation
  81. Listing Objects in a View
  82. Saving Data with a Form
  83. Wrapping Up
  84. 9. Fortifying Your Application
  85. Setting Up the Initial Project
  86. Managing User Sessions in Express
  87. Adding Authentication UI Elements
  88. Setting Up Passport
  89. Authenticating with Facebook, Twitter, and Google
  90. Composing an Express Router
  91. Bringing in the Book Bundle UI
  92. Serving in Production
  93. Wrapping Up
  94. Node.js 8 the Right Way
  95. 10. BONUS: Developing Flows with Node-RED
  96. Setting Up Node-RED
  97. Securing Node-RED
  98. Developing a Node-RED Flow
  99. Creating HTTP APIs with Node-RED
  100. Handling Errors in Node-RED Flows
  101. Wrapping Up
  102. A1. Setting Up Angular
  103. A2. Setting Up React
  104. Node.js 8 the Right Way

Transpiling with TypeScript

At this point, the basic framework of the application is in place and we’re ready to start developing the application functionality. Since browsers often lag behind Node.js in terms of support for the latest JavaScript features, we need a way to convert modern JavaScript into a common dialect that browsers will understand.

The practice of compiling source code from one programming language into another (or from one language version to another version) is called transpiling. There is a rich tradition of transpiling in the JavaScript community—both from other languages into JavaScript and JavaScript-to-JavaScript. Today, two of the most popular JavaScript transpilers are Babel and TypeScript.

Babel transpiles code written using the latest ECMAScript techniques (like those we’ve been using throughout this book),[74] into a dialect of ECMAScript that’s widely available in browsers. Babel can be used in conjunction with Flow, an analysis tool by Facebook, which performs type inference and type checking.[75] In many cases, Flow can infer the type of a variable and inform you of subtle code errors before they become runtime issues. If that’s not enough, you can also provide specific type information about your variables that Flow will enforce.

TypeScript, by Microsoft, is a superset of JavaScript that includes typings.[76] The TypeScript toolchain performs transpiling down into common ECMAScript, as well as static type inference and checking on your source code. Like Flow, in many cases TypeScript can infer variable types, and you can also provide specific types through a rich type system.

For our immediate purpose, either Babel or TypeScript would be fine. Both are relatively easy to integrate with webpack, and both can transpile the latest ECMAScript down to a version understood by browsers. I’ve chosen to use TypeScript in this book for a couple of reasons.

First, since TypeScript performs type inference and checking in addition to transpiling, you get a layer of protection for free. With Babel, we’d have to add Flow to get the same benefit.

Second, TypeScript has a large and growing repository of community-contributed typings called DefinitelyTyped.[77] This repository is directly available through npm as a collection of packages that begin with the prefix @types/. For example, the Bootstrap typings are available as @types/bootstrap.

I think momentum is on TypeScript’s side, but time will tell. In either case, the code that you’ll be writing throughout the rest of this chapter is compatible with both TypeScript and Babel/Flow.

To use TypeScript in your project, start by installing it with npm.

 $ ​​npm​​ ​​install​​ ​​--save-dev​​ ​​--save-exact​​ ​​typescript@2.5.3

You’ll also need the ts-loader plugin for webpack.

 $ ​​npm​​ ​​install​​ ​​--save-dev​​ ​​--save-exact​​ ​​ts-loader@2.3.7

To transpile TypeScript into JavaScript, you’ll need a tsconfig.json to configure your project. Open your text editor and enter the following:

 {
 "compilerOptions"​: {
 "outDir"​: ​"./dist/"​,
 "sourceMap"​: ​true​,
 "module"​: ​"CommonJS"​,
 "target"​: ​"ES5"​,
 "lib"​: [​"DOM"​, ​"ES2015.Promise"​, ​"ES5"​],
 "allowJs"​: ​true​,
 "alwaysStrict"​: ​true
  }
 }

Via the tsconfig.json, TypeScript allows you to fine-tune the compilation through many compiler options.[78] Here’s a quick rundown of the ones we’re using.

  • outDir—Directory where TypeScript should emit transpiled js files. These files won’t actually appear here when using the ts-loader and webpack dev server.

  • sourceMap—Whether to generate a source map along with the transpiled output. We’ll explore this in more detail later.

  • module—Which module system to use to represent transpiled dependencies. CommonJS is the module system used by Node.js, characterized by the require function for pulling in dependent modules.

  • target—Which version of ECMAScript to target for transpiled output. ECMAScript version 5 has wide support among modern browsers.

  • lib—Collection of built-in typings that TypeScript should be aware of. In our case, we’ll employ features of the DOM and presume that the user’s browser has support for Promises.

  • allowJs—Whether to permit TypeScript to compile js source files as well as ts.

  • alwaysStrict—Whether to always interpret code in strict mode and emit ’use strict’; in generated files. This lets us omit the use strict clause from the tops of ts files.

After you save this file, it’s time to update your webpack.config.js. To start, open that file and update the entry to point to ./app/index.ts.

 entry: ​'./app/index.ts'​,

In addition to switching from a js file to a ts file, let’s also create a subdirectory to organize the front-end code files. It is a webpack convention to call this directory app. We’ll create the app directory and index.ts in a bit, but first let’s finish updating the webpack config.

Down in the module.rules section of your webpack.config.js file, add a rule to the top of the list to associate the ts with TypeScript via the ts-loader plugin. Your module.rules section should now look like this:

 module: {
  rules: [{
  test: ​/​​\.​​ts$/​,
  loader: ​'ts-loader'​,
  },{
  test: ​/​​\.​​css$/​,
  use: [ ​'style-loader'​, ​'css-loader'​ ]
  },{
  test: ​/​​\.(​​png|woff|woff2|eot|ttf|svg​​)​​$/​,
  loader: ​'url-loader?limit=100000'​,
  }],
 },

Good—now it’s time to create the app directory.

 $ ​​mkdir​​ ​​app

Rather than have all of the application code lumped into one file, let’s split out the HTML parts into a separate file called templates.ts. Open your text editor and enter the following:

 export​ ​const​ main = ​`
  <div class="container">
  <h1>B4 - Book Bundler</h1>
  <div class="b4-alerts"></div>
  <div class="b4-main"></div>
  </div>
 `​;
 
 export​ ​const​ welcome = ​`
  <div class="jumbotron">
  <h1>Welcome!</h1>
  <p>B4 is an application for creating book bundles.</p>
  </div>
 `​;
 
 export​ ​const​ alert = ​`
  <div class="alert alert-success alert-dismissible fade in" role="alert">
  <button class="close" data-dismiss="alert" aria-label="Close">
  <span aria-hidden="true">&times;</span>
  </button>
  <strong>Success!</strong> Bootstrap is working.
  </div>
 `​;

The multiline strings of HTML you see here are all copied directly from the entry.js from earlier. But rather than assigning them to the innerHTML properties of DOM elements, we’re making them available through the ES6 module keyword export. This is similar to setting module.exports like you’ve done in previous examples in this book.

Once you save this file, start a new file in your editor for the index.ts file. Enter the following to get it started.

 import​ ​'../node_modules/bootstrap/dist/css/bootstrap.min.css'​;
 import​ ​'bootstrap'​;
 import​ * ​as​ templates ​from​ ​'./templates.ts'​;
 
 document.body.innerHTML = templates.main;
 
 const​ mainElement = document.body.querySelector(​'.b4-main'​);
 const​ alertsElement = document.body.querySelector(​'.b4-alerts'​);
 
 mainElement.innerHTML = templates.welcome;
 alertsElement.innerHTML = templates.alert;

At the outset of this file, we import the same bootstrap.css and bootstrap module as before. Note the subtle difference in the path to bootstrap.css. Now that we’re down one subdirectory in app, the path to bootstrap.css starts with ../node_modules/ instead of ./node_modules/.

Next, we import all of the exported members from templates.ts into a local variable called templates. These will be used to populate the innerHTML elements in the page.

As before, in entry.js we start by populating the document.body with the main structural HTML. After that, we grab references to the mainElement and the alertsElement in which we’ll render page content and notifications, respectively.

Lastly, we fill in the main content element with the HTML from templates.welcome, and the alerts element with the HTML from templates.alert. This produces the same behavior as the entry.js from earlier, and represents a good test to ensure that all of the TypeScript and webpack configuration is working.

After saving this file, restart your webpack dev server, then confirm that the page at localhost:60800 looks the same as before and the close button on the alert works as expected. If so, great!

Next, we’ll add HTML templating to the project. This will afford dynamically generating HTML, rather than relying on only static strings.