Table of content:
- Praise for The Complete Developer
- Title Page
- Copyright
- Dedication
- About the Author and Technical Reviewer
- Acknowledgments
-
Introduction
- Who Should Read This Book?
- What’s in This Book?
-
The Parts of a Full-Stack Application
- The Frontend
- The Middleware
- The Backend
- A Brief History of JavaScript and Full-Stack Development
- Setting Up
-
Part I: The Technology Stack
-
1. Node.JS
- Installing Node.js
- Working with npm
-
The package.json File
- Required Fields
- Dependencies
- Development Dependencies
- The package-lock.json File
-
Creating a Project
- Initializing a New Module or Project
- Installing the Dependencies
- Installing the Development Dependencies
- Auditing the package.json File
- Cleaning Up the node_modules Folder
- Updating All Packages
- Removing a Dependency
- Installing a Dependency
- Using npx to Execute a Script Only Once
-
Exercise 1: Build a “Hello World” Express.js Server
- Setting Up
- Writing the Server Code
- Summary
-
2. Modern Javascript
-
ES.Next Modules
- Using Named and Default Exports
- Importing Modules
-
Declaring Variables
- Hoisted Variables
- Scope-Abiding Variables
- Constant-Like Data
-
Arrow Functions
- Writing Arrow Functions
- Understanding Lexical Scope
- Exploring Practical Use Cases
- Creating Strings
-
Asynchronous Scripts
- Avoiding Traditional Callbacks
- Using Promises
- Simplifying Asynchronous Scripts
- Looping Through an Array
- Dispersing Arrays and Objects
-
Exercise 2: Extend Express.js with Modern JavaScript
- Editing the package.json File
- Writing an ES.Next Module with Asynchronous Code
- Adding the Modules to the Server
- Summary
-
ES.Next Modules
-
3. Typescript
- Benefits of TypeScript
-
Setting Up TypeScript
- Installation in Node.js
- The tsconfig.json File
- Dynamic Feedback with TypeScript
-
Type Annotations
- Declaring a Variable
- Declaring a Return Value
- Declaring a Function’s Parameters
-
Built-in Types
- Primitive JavaScript Types
- The union Type
- The array Type
- The object Type
- The tuple Type
- The any Type
- The void Type
-
Custom Types and Interfaces
- Defining Custom Types
- Defining Interfaces
- Using Type Declaration Files
-
Exercise 3: Extend Express.js with TypeScript
- Setting Up
- Creating the tsconfig.json File
- Defining Custom Types
- Adding Type Annotations to the routes.ts File
- Adding Type Annotations to the index.ts File
- Transpiling and Running the Code
- Summary
-
4. React
- The Role of React
- Setting Up React
-
The JavaScript Syntax Extension
- An Example JSX Expression
- The ReactDOM Package
-
Organizing Code into Components
- Writing Class Components
- Providing Reusable Behavior with Hooks
-
Working with Built-in Hooks
- Managing the Internal State with useState
- Handling Side Effects with useEffect
- Sharing Global Data with useContext and Context Providers
-
Exercise 4: Create a Reactive User Interface for the Express.js Server
- Adding React to the Server
- Creating the Endpoint for the Static HTML File
- Running the Server
- Summary
-
5. Next.JS
-
Setting Up Next.js
- Project Structure
- Development Scripts
-
Routing the Application
- Simple Page Routes
- Nested Page Routes
- API Routes
- Dynamic URLs
-
Styling the Application
- Global Styles
- Component Styles
-
Built-in Next.js Components
- The next/head Component
- The next/link Component
- The next/image Component
-
Pre-rendering and Publishing
- Server-Side Rendering
- Static Site Generation
- Incremental Static Regeneration
- Client-Side Rendering
- Static HTML Exporting
-
Exercise 5: Refactor Express.js and React to Next.js
- Storing Custom Interfaces and Types
- Creating the API Routes
- Creating the Page Routes
- Running the Application
- Summary
-
Setting Up Next.js
-
6. Rest and Graphql APIs
-
REST APIs
- The URL
- The Specification
- State and Authentication
- HTTP Methods
-
Working with REST
- Reading Data
- Updating Data
-
GraphQL APIs
- The Schema
- The Resolvers
-
Comparing GraphQL to REST
- Over-Fetching
- Under-Fetching
-
Exercise 6: Add a GraphQL API to Next.js
- Creating the Schema
- Adding Data
- Implementing Resolvers
- Creating the API Route
- Using the Apollo Sandbox
- Summary
-
REST APIs
-
7. Mongodb and Mongoose
- How Apps Use Databases and Object-Relational Mappers
- Relational and Non-Relational Databases
- Setting Up MongoDB and Mongoose
-
Defining a Mongoose Model
- The Interface
- The Schema
- The Model
- The Database-Connection Middleware
-
Querying the Database
- Creating a Document
- Reading a Document
- Updating a Document
- Deleting a Document
- Creating an End-to-End Query
-
Exercise 7: Connect the GraphQL API to the Database
- Connecting to the Database
- Adding Services to GraphQL Resolvers
- Summary
-
8. Testing With the Jest Framework
- Test-Driven Development and Unit Testing
- Using Jest
- Creating an Example Module to Test
-
Anatomy of a Test Case
- Arrange
- Act
- Assert
-
Using TDD
- Refactoring Code
- Evaluating Test Coverage
-
Replacing Dependencies with Fakes, Stubs, and Mocks
- Creating a Module with Dependencies
- Creating a Doubles Folder
- Using a Stub
- Using a Fake
- Using a Mock
-
Additional Types of Tests
- Functional Tests
- Integration Tests
- End-to-End Tests
- Snapshot Tests
-
Exercise 8: Add Test Cases to the Weather App
- Testing the Middleware with Spies
- Creating Mocks to Test the Services
- Performing an End-to-End Test of the REST API
- Evaluating the User Interface with a Snapshot Test
- Summary
-
9. Authorization With OAuth
-
How OAuth Works
- Authentication vs. Authorization
- The Role of OAuth
- Grant Types
- Bearer Tokens
- The Authorization Code Flow
-
Creating a JWT Token
- The Header
- The Payload
- The Signature
-
Exercise 9: Access a Protected Resource
- Setting Up the Client
- Logging In to Receive the Authorization Grant
- Using the Authorization Grant to Get the Access Token
- Using the Access Token to Get the Protected Resource
- Summary
-
How OAuth Works
-
10. Containerization With Docker
- The Containerization Architecture
- Installing Docker
-
Creating a Docker Container
- Writing the Dockerfile
- Building the Docker Image
- Serving the Application from the Docker Container
- Locating the Exposed Docker Port
- Interacting with the Container
-
Creating Microservices with Docker Compose
- Writing the docker-compose.yml File
- Running the Containers
- Rerunning the Tests
- Interacting with Docker Compose
- Summary
-
1. Node.JS
-
Part II: The Full-Stack Application
-
11. Setting Up the Docker Environment
- The Food Finder Application
-
Building the Local Environment with Docker
- The Backend Container
- The Frontend Container
- Summary
-
12. Building the Middleware
- Configuring Next.js to Use Absolute Imports
-
Connecting Mongoose
- Writing the Database Connection
- Fixing the TypeScript Warning
-
The Mongoose Model
- Creating the Schema
- Creating the Location Model
-
The Model’s Services
- Creating the Location Service’s Custom Types
- Creating the Location Services
- Testing the Services
- Summary
-
13. Building the Graphql API
- Setting Up
-
The Schemas
- The Custom Types and Directives
- The Query Schema
- The Mutation Schema
- Merging the Typedefs into the Final Schema
- The GraphQL Resolvers
- Adding the API Endpoint to Next.js
- Summary
-
14. Building the Frontend
- Overview of the User Interface
-
The Start Page
- The List Item
- The Locations List
- The Page
-
The Global Layout Components
- The Logo
- The Header
- The Layout
-
The Location Details Page
- The Component
- The Page
- Summary
-
15. Adding OAuth
-
Adding OAuth with next-auth
- Creating a GitHub OAuth App
- Adding the Client Credentials
- Installing next-auth
- Creating the Authentication Callback
- Sharing the Session Across Pages and Components
- The Generic Button Component
- The AuthElement Component
- Adding the AuthElement Component to the Header
- The Wish List Next.js Page
- Adding the Button to the Location Detail Component
- Securing the GraphQL Mutations
- Summary
-
Adding OAuth with next-auth
-
16. Running Automated Tests in Docker
- Adding Jest to the Project
- Setting Up Docker
- Writing Snapshot Tests for the Header Element
- Summary
- A. Typescript Compiler Options
-
B. The Next.JS App Directory
-
Server Components vs. Client Components
- Server Components
- Client Components
-
Rendering Components
- Fetching Data
- Static Rendering
- Dynamic Rendering
-
Exploring the Project Structure
- Updating the CSS
- Defining a Layout
- Adding the Content and Route
- Catching Errors
- Showing an Optional Loading Interface
- Adding a Server Component That Fetches Remote Data
- Completing the Application with the Navigation
- Replacing API Routes with Route Handlers
-
Server Components vs. Client Components
-
C. Common Matchers
- Built-in Matchers
- The JEST-DOM Matchers
-
11. Setting Up the Docker Environment
- Index