Log In
Or create an account -> 
Imperial Library
  • Home
  • About
  • News
  • Upload
  • Forum
  • Help
  • Login/SignUp

Index
Title Page Copyright and Credits
Building Enterprise JavaScript Applications
Dedication Packt Upsell
Why subscribe? PacktPub.com
Contributors
About the author About the reviewer Packt is searching for authors like you
Preface
Who this book is for What this book covers
Section 1 – Theory and practice Section 2 – Developing our backend API Section 3 – Developing our frontend UI Section 4 – Infrastructure and automation Section 5 – Important JavaScript concepts and syntax What is not covered
To get the most out of this book
Download the example code files Conventions used
Get in touch
Reviews
The Importance of Good Code
Technical debt
What is technical debt? Causes of technical debt
The debt spiral
Consequences of technical debt
Technical debt leads to low morale
Consequences of low morale
Repaying technical debt through refactoring Preventing technical debt
Informing the decision makers
The triple constraint The fallacy of the triple constraint
Refuse to develop Don't be a hero Defining processes
Test-Driven Development
Understanding the TDD process
Fixing bugs
Benefits of TDD
Avoiding manual tests Tests as specification Tests as documentation Short development cycles
Difficulties with TDD adoption When not to use TDD
Summary
The State of JavaScript
Evolution of the web application
Just-in-time (JIT) compilers Single page applications (SPAs) Isomorphic JavaScript applications
Benefits of Node.js
Context switching
Switching between projects Switching between languages The business perspective
Shared code
Summary
Managing Version History with Git
Setting up Git
Creating a new repository Configuring Git
Configuring a user
Learning the basics
Committing to history
Understanding file states in Git
The three tracked states
Staging our changes Quick recap
Branching and merging
Git branches Branching models
The Driessen model
Creating a development branch Creating feature branches
Naming sub-branches
Merging branches Examining more realistic examples
Keeping the dev Branch Bug-Free Keeping our history clean
Keeping our history clean with git rebase Using merge and rebase together
Releasing code
Semantic versioning Creating a release branch Tagging releases
Hotfixes Working with others
Creating a remote repository Pulling and pushing
Cloning a repository
Conducting peer review through pull requests
Summary
Setting Up Development Tools
What is Node.js?
Terminology
Modules
The dawn of modules The birth of Node.js modules
Adoption of the CommonJS standard
Fulfilling the encapsulation requirement
Standardizing module formats
Installing Node
Using nvm to install Node Documenting Node versions
Starting projects with npm Using yarn instead of npm
Package version locking Offline cache Speed Installing yarn Getting familiar with the yarn CLI npm and yarn, together
Creating an HTTP server
Our HTTP server in detail
Transpiling ES6 with Babel
Babel is a transpiler...and more! Different faces of Babel
@babel/cli @babel/register
Using @babel/register for tests
@babel/node @babel/core @babel/polyfill
Adding Babel CLI and polyfill Using Babel CLI to transpile our code
Plugins and presets
The env preset
Separating source and distribution code
Importing the Babel polyfill
Consolidating commands with npm scripts
Ensuring cross-platform compatibility
Automating development using nodemon Linting with ESLint
Installing ESLint Linting our code Adding lint script to package.json Installing the ESLint extension Adding pre-commit hooks
Committing our code into Git
Using .gitignore to ignore files
Summary
Writing End-to-End Tests
Understanding different types of test
Structuring our test suite with the testing pyramid When implementing a new feature, write your E2E tests first
Following a TDD workflow
Gathering business requirements Formalizing requirements through documentation Refining requirements into specification
Writing tests as specification
Test-driven development Writing manual tests
Exploratory testing
Maintenance
Gathering requirements Setting Up E2E tests with Cucumber
Features, scenarios, and steps
Gherkin keywords Specifying our feature Writing our first scenario
Laying out our step definitions Running our scenarios
Implementing step definitions
Calling our endpoint Asserting results Using a debugger for Node.js debugging
Using Chrome DevTools Using ndb Using the Visual Studio Code debugger
Retaining line numbers
Examining the req object Making work-in-progress (WIP) commits
Asserting the correct response status code
You ain't gonna need it (YAGNI)
Asserting the correct response payload Asserting the correct response payload content Refactoring
Isolating contexts for each scenario Making failure more informative Removing hardcoded values
Validating data type
Refactoring our tests
Using scenario outlines Combining duplicate step definitions
Refactoring our application
Choosing a framework
Migrating our API to Express
(Re)defining routes Using body-parser middleware
Run E2E test
Moving common logic into middleware Validating our payload
Checking for required fields Checking property type Checking the payload property's format Refactoring our step definitions
Testing the success scenario Summary
Storing Data in Elasticsearch
Introduction to Elasticsearch
Elasticsearch versus other distributed document store
Installing Java and Elasticsearch
Installing Java Installing and starting Elasticsearch
Understanding key concepts in Elasticsearch
Elasticsearch is a JSON document store
Document vs. relationship data storage
Understanding indices, types, documents, and versions
Querying Elasticsearch from E2E tests Indexing documents to Elasticsearch Cleaning up after our tests
Deleting our test user Improving our testing experience Running tests in a test database Separating development and testing servers Making a standalone E2E test script
The shebang interpreter directive Ensuring Elasticsearch is running Running the test API server in the background  Checking our API server is ready
Checking API status using netstat/ss
Cleaning up the background process Running our tests
Summary
Modularizing Our Code
Modularizing our code
Modularizing our middleware Modularizing our request handlers The single responsibility principle Decoupling our validation logic
Creating the ValidationError interface Modularizing our validation logic
Creating engines
Adding a user profile
Writing a specification as a test Schema-based validation Types of schema Picking an object schema and validation library
Interoperability Expressiveness
Creating our profile schema
Rejecting additional properties
Dynamic mapping in Elasticsearch
Adding specificity to a sub-schema Adding a title and description Specifying a meta-schema Specifying a unique ID
Creating a schema for the Create User request payload Picking a JSON Schema validation library Validating against JSON Schema with Ajv Generating validation error messages Generalizing functions Updating the npm build script Testing the success scenario Resetting our test index
Summary
Writing Unit/Integration Tests
Picking a testing framework
Installing Mocha
Structuring our test files Writing our first unit test
Describing the expected behavior Overriding ESLint for test files
Understanding arrow functions in Mocha Specifying ESLint environments
Running our unit tests Running unit tests as an npm script
Completing our first unit test suite Unit testing ValidationError Unit testing middleware
Asserting deep equality Asserting function calls with spies Simulating behavior with stubs Testing all middleware functions
Unit testing the request handler
Stubbing create Dependency injection Monkey patching Dependency injection versus monkey patching
Modularity Readability Reliance on third-party tools
Following the dependency injection pattern Promises and Mocha
Dealing with rejected promises Completing the unit tests
Unit testing our engine Integration testing our engine Adding test coverage
Reading a test coverage report Improving test coverage Code coverage versus test quality You don't have to test everything, all the time Unifying test coverage Ignoring files
Finishing up Summary
Designing Our API
What it means to be RESTful
What is REST? What REST is not Should my API be RESTful?
Designing our API
Consistent
Common consistency
Sending the correct HTTP status code Using HTTP methods Using ISO formats
Local consistency
Naming convention Consistent data exchange format Error response payload
Transversal consistency Domain consistency Perennial consistency
Breaking changes in APIs Future-proofing your URL Future-proofing your data structure Versioning
Intuitive
URLs for humans Favor verbosity and explicitness
Keep It Simple Stupid (KISS)
Completing our API Summary
Deploying Our Application on a VPS
Obtaining an IP address
Managed DNS
Setting up a Virtual Private Server (VPS)
Creating a VPS instance
Choosing an image Choosing a size Picking a data center region Selecting additional options Naming your server
Connecting to the VPS Setting up user accounts
Creating a new user Adding a user to the sudo group
Setting up public key authentication
Checking for existing SSH key(s) Creating an SSH key Adding the SSH key to the remote server
Using ssh-copy-id
Providing extra security
Disable password-based authentication Disable root login Firewall
Configuring the time zone
Running our API Keeping our API alive with PM2
Killing a process Keeping PM2 alive
Running our API on port 80
Privileged ports Possible solutions
Running as root
De-escalating privileges
Setting capabilities Using authbind Using iptables Using reverse proxy
What's a proxy? What's a reverse proxy?
Setting up NGINX
Configuring NGINX
Understanding NGINX's configuration file Configuring the HTTP module Splitting nginx.conf into multiple files
From IP to domain
Buying a domain Understanding DNS Updating the domain nameserver Building our zone file
NS records A and AAAA Start of Authority (SOA)
Updating NGINX
Summary
Continuous Integration
Continuous Integration (CI)
Picking a CI server
Integrating with Travis CI
Configuring Travis CI
Specifying the language Setting up databases Setting environment variables Activating our project
Examining Travis CI results
Continuous Integration with Jenkins
Introduction to Jenkins
Freestyle projects Pipeline
Setting up a new Jenkins server
Creating the jenkins user Configuring time Installing Java Installing Jenkins Installing NGINX as a reverse proxy Configuring the firewall Updating our DNS records Configuring Jenkins
Composing a Jenkinsfile
The Pipeline DSL syntax Declarative versus scripted pipelines The declarative pipeline The scripted pipeline Setting up the environment Installing Docker
Integration with GitHub
Providing access to the repository
The Personal Access (OAuth) Token
Using the GitHub plugin Setting up GitHub service hooks manually Creating a new folder Creating a new pipeline Running the first build
Summary
Security – Authentication and Authorization
What is Authentication? Introduction to password-based authentication
Hashing passwords
Cryptographic hash functions Picking a cryptographic hashing algorithm
Hash stretching Hash stretching algorithms
Preventing brute-force attacks against a single user
Protecting against brute-force attacks
Reverse lookup table attacks
Protecting against reverse lookup table attacks
Implementing password-base authentication
Updating existing E2E tests
Generating a random digest
Picking a bcrypt library Using the bcryptjs library
Validating a digest
Updating an existing implementation Retrieving the salt
Implementing the Retrieve Salt endpoint
Implementing a Retrieve Salt engine
Generating a salt for non-existent users
Writing E2E tests Implementation
Login
Writing tests Implementing Login
Keeping users authenticated
JSON web tokens (JWTs)
Anatomy of a JWT Header Payload and claims
Registered claim names Public claim names Private claim names Example claim
Signature
Asymmetric signature generation Symmetric signature generation Picking an algorithm
A note on encryption Terminology and summary
Responding with a token
Adding E2E Tests Implementation
Multiline environment variables Generating the token
Attaching the token
HTTP cookies
Cross-Site Scripting (XSS) Cross-Site Request Forgery (XSRF)
HTTP headers
The Authorization header
Writing tests
Features and scenarios Implementation step definitions
Verifying the digest in the request
Next steps
Preventing man-in-the-middle (MITM) attacks Encrypting digests
Block cipher
Exploring the Secure Remote Password (SRP) protocol
Summary
Documenting Our API
Overview of OpenAPI and Swagger
Picking an API specification language Swagger vs OpenAPI Swagger Toolchain
Swagger Editor Swagger UI Swagger Inspector Swagger codegen
Defining an API specification with OpenAPI
Learning YAML An overview of the root fields Specifying the GET /salt endpoint
Specifying parameters Specifying responses
Specifying the Create User endpoint
Specifying the request body
Defining common components Specifying the Retrieve User endpoint Specifying the Replace Profile endpoint Specifying the rest of the endpoints
Generating documentation with Swagger UI
Adding the Swagger UI to our repository Using our specification in the Swagger UI
Exposing swagger.yaml from our API Enabling CORS
Same-origin policy Cross-Origin Resource Sharing (CORS)
Final touches
Replacing the specification URL Removing the header
Deployment Summary
Creating UI with React
Picking a front-end framework/library
Vanilla JavaScript vs. frameworks Choosing a framework/library
Popularity/community Features
Virtual DOM JSX Post-React
Flexibility Performance Cross-platform
Hybrid applications with Ionic Native UI with React Native and Weex
Learning curve Conclusion
Getting started with React
What is React?
Components Virtual DOM
How Virtual DOM improves performance
React is declarative React summary
Starting a new repository Adding some boilerplate Creating our first component JSX
Transpiling JSX
Defining React components
Functional and class components Pure components
Maintaining the state and listening for events
Handling events setState and immutability Rendering the state
Submitting forms
Uncontrolled form elements
Resolving CORS issues Disabling the Button component
Controlled form elements
Modularizing React
Client-side modules
Module bundling
Browserify Webpack Rollup Parcel
Asynchronous module loading
AMD and Require.js Universal Module Definition SystemJS and the Loader specification jspm
Module bundler versus module loader
HTTP/2
Webpack
Modularizing our components Entry/output Loaders Plugins
Copying files
Final steps
Summary
E2E Testing in React
Testing strategies
Automated UI testing Unit testing
Logical units Component units
Browser testing
Writing E2E tests with Gherkin, Cucumber, and Selenium
Adding test script Specifying a feature Adding IDs to elements Selenium WebDriver API Using Selenium WebDriver Headless browsers Browser drivers Setup and teardown Implementing step definitions
Navigating to a page Typing into input Asserting a result
Running the tests Adding multiple testing browsers Running our backend API
Dynamic string substitution with Webpack Serving the API from a submodule Defining the happy scenario Generating random data Making step definitions more generic Clicking Waiting Render components based on state
Routing with React Router
Basics
Router Route matching Supporting the History API Navigation
TDD
Login
Writing tests Implementing Login
Over to you Summary
Managing States with Redux
State management tools
Redux MobX Redux versus MobX
Converting to Redux
Creating the store Lifting the state up Dispatching actions Updating the state with the Reducer Connecting with React Redux Wrapping with the Provider component Connecting to the Redux store
mapStateToProps mapDispatchToProps
Decoupling Redux from components
Summary
Migrating to Docker
Problems with manual deployment Introduction to Docker
What are containers? Workflow How does Docker solve our issues?
Mechanics of Docker
What is a Docker container?
Control groups Namespaces LXC and Docker Virtual Machines Containers versus Virtual Machines
What is a Docker image?
Images are layered Running a container Setting up the Docker Toolchain Adding the Docker package repository
Installing Docker
Docker Engine, Daemon, and Client Running Elasticsearch on Docker  Running a container
Understanding the docker run option
Identifying a container by name  Setting environment variables Running as daemon Network port mapping
0.0.0.0
Updating our test script Dockerizing our backend API Overview of a Dockerfile
Writing our Dockerfile
Picking a base image Copying project files Building our application Specifying the executable
Building our image
Running our image Persisting data
Following best practices
Shell versus exec forms
Allowing Unix signaling Running as a non-root user Taking advantage of the cache Caveats
Using a lighter image Removing obsolete files Multi-stage builds Security
Summary
Robust Infrastructure with Kubernetes
High availability
Measuring availability Following the industry standard Eliminating single points of failure (SPOF) Load balancing versus failover Load balancing
DNS load balancing Layer 4/7 load balancers
Layer 4 load balancers Layer 7 load balancing
High reliability
Testing for reliability
High throughput High scalability Clusters and microservices
Microservices Clusters
Cluster management
Cluster-level tools
Discovery service Scheduler Global configuration store Provisioning tools
Picking a cluster management tool Control Planes and components
Master components
kube-apiserver kube-control-manager
Node components
Container runtime kubelet kube-proxy
Kubernetes objects
The four basic objects High-level objects Controllers
Setting up the local development environment
Checking hardware requirements Cleaning our environment Disabling swap memory Installing kubectl Installing Minikube Installing a Hypervisor or Docker Machine
Creating our cluster
Setting environment variables for the local cluster Running minikube start Updating the context Resetting the cluster
Creating our first Pod
Running Pods with kubelet Running Pods with kubectl run
Understanding high-level Kubernetes objects Declarative over imperative
Deleting deployment Creating a deployment manifest
A note on labels
Running pods declaratively with kubectl apply Kubernetes Object management hierarchy
Configuring Elasticsearch cluster
Networking for distributed databases Configuring Elasticsearch's Zen discovery
Attaching hostnames to Pods Working with StatefulSets
Ordinal index
Working with services
Linking StatefulSet to a service Updating Zen Discovery configuration
Validating Zen Discovery
Deploying on cloud provider
Creating a new remote cluster
Switching contexts
Configuring nodes for Elasticsearch
Running commands on multiple servers
Using pssh Using init containers
Running the Elasticsearch service
Validating Zen Discovery on the remote cluster
Persisting data
Introducing Kubernetes Volumes
Defining Volumes Problems with manually-managed Volumes
Introducing PersistentVolume (PV)
Consuming PVs with PersistentVolumeClaim (PVC) Deleting a PersistentVolumeClaim Deleting a PersistentVolume Problems with manually provisioning PersistentVolume
Dynamic volume provisioning with StorageClass
Defining a StorageClass
Using the csi-digitalocean provisioner
Provisioning PersistentVolume to StatefulSet
Configuring permissions on a bind-mounted directory
Visualizing Kubernetes Objects using the Web UI Dashboard
Launching the Web UI Dashboard locally Launching the Web UI Dashboard on a remote cluster
Deploying the backend API
Publishing our image to Docker Hub Creating a Deployment
Discovering Services using kube-dns/CoreDNS Running Our backend Deployment
Creating a backend Service Exposing services through Ingress
Deploying the NGINX Ingress Controller Deploying the Ingress resource Updating DNS records
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
  • ← Prev
  • Back
  • Next →
  • ← Prev
  • Back
  • Next →

Chief Librarian: Las Zenow <zenow@riseup.net>
Fork the source code from gitlab
.

This is a mirror of the Tor onion service:
http://kx5thpx2olielkihfyo4jgjqfb7zx7wxr3sd4xzt26ochei4m6f7tayd.onion