Andy Walking Documentation
website·Indexed 31 days ago
https://andywalking.twA collection of technical notes and guides by a frontend engineer covering JavaScript, TypeScript, React, Vue, and NestJS. Topics include the JavaScript event loop, TypeScript generics and interfaces, React rendering strategies, Vitest configuration, HTTP/TCP-IP networking, and backend authentication using NestJS and PostgreSQL.
What's inside Andy Walking
- Frontend testing is categorized into four main types based on the scope of verification. The scope increases from the bottom up, with lower-level tests typically being faster and more frequent during early development to ensure quality.
Overview of Pug template engine
Pug (formerly Jade) is a template engine commonly used with Node.js to generate HTML. Its key features include a simplified syntax for defining HTML structures, support for JavaScript expressions, and the ability to control content generation through conditional logic, mixins, and inheritance.Understand the TCP Three-Way Handshake process
The TCP Three-Way Handshake is a process used to establish a reliable connection between two endpoints before data transmission begins. This ensures that both parties are ready and the connection is viable, preventing the loss or hijacking of critical data. In a typical web request flow, the TCP connection is established after the DNS resolves the URL to an IP address and before the HTTP request is sent to the server. Note that not all connections perform a three-way handshake, and for HTTPS connections, this is followed by a TLS handshake.Client: Hello, if you receive this note, please reply. Server: Hi, I have received your note. Client: Great! (Connection established)Implement a refactoring workflow for Vue projects
To optimize a project for readability, maintainability, and performance without breaking existing functionality, follow these sequential steps:
- Map out the architecture and define the function of each layer.
- Update build tools (e.g., migrate from Webpack to Vite).
- Implement tests for critical features using Vitest.
- Refactor code on a per-page basis, documenting the reasoning for each change.
- Convert the codebase to TypeScript.
Understand Synchronous vs Asynchronous execution in JavaScript
JavaScript is a single-threaded language, meaning it executes one line of code at a time in order (Synchronous). Synchronous execution can block the main thread if a task takes a long time (e.g., fetching data from a server). Asynchronous behavior prevents this blocking by allowing the execution environment (Browser or Node.js) to handle time-consuming operations in the background via the Event Loop, allowing the main thread to continue executing other code.console.log("1"); // Executes 1, then 2, then 3 sequentially console.log("2"); console.log("3");JavaScript Event Loop Architecture Components
In a browser environment, the Event Loop relies on several key components to manage code execution:
- Call Stack: A LIFO (Last-In, First-Out) structure that tracks the current function execution.
- Heap: A memory area used for storing variables and objects.
- Callback Queue: A holding area for asynchronous callbacks waiting to be executed.
- Web-API: Browser-provided APIs (like
setTimeoutor DOM events) that handle asynchronous operations outside the main JavaScript thread.
Understand the HTTP Request and Client-Server Model
HTTP (Hypertext Transfer Protocol) is the standard protocol for communication between web clients and servers. It follows a Client-Server model where the interaction is unidirectional: a client (such as a web browser or a tool like Postman) sends an HTTP Request to a server, and the server returns an HTTP Response.Understand React's 'Always Re-render' strategy
React employs an 'always re-render' strategy: when a component's state changes, that component and all of its descendants will re-execute their render functions, regardless of whether the descendants' own state has changed. To avoid the performance cost of updating the actual DOM for every render, React uses a Virtual DOM. It generates a new Virtual DOM tree and uses a diffing algorithm to compare it with the previous version, ensuring that only the parts of the real DOM that actually changed are updated.Apply Generic Constraints using the extends keyword
Generic constraints allow you to limit the types that can be passed as a generic argument. By using theextendskeyword, you can ensure that the passed type possesses specific properties or implements a certain interface.interface IncludeLength { length: number; } function logMessage<T extends IncludeLength>(arg: T): T { console.log(arg.length); return arg; }Remove Vue CLI and Webpack dependencies during Vite migration
When migrating to Vite, remove the following Vue CLI plugins and Webpack-related dependencies from
package.jsonas their functionality is either handled by Vite or requires different plugins:@vue/cli-plugin-babel: Handled by Vite's native ES build.@vue/cli-plugin-eslint: Replace with standard ESLint configurations.@vue/cli-plugin-router: Router setup is manual or handled by standard Vue patterns.@vue/cli-plugin-vuex: Store setup is manual or handled by standard Vue patterns.@vue/cli-service: The core build service replaced by Vite.sass-loader: Webpack's Sass compiler; Vite requires a different approach for Sass.
Run asynchronous tests in parallel
Use.concurrent()to trigger multiple asynchronous tests simultaneously. This can be applied to adescribeblock to make all tests within that suite parallel, or to individualittests.import { describe, it } from 'vitest' describe.concurrent('suite', () => { it('concurrent test 1', async ({ expect }) => { /* ... */ }) it('concurrent test 2', async ({ expect }) => { /* ... */ }) it.concurrent('concurrent test 3', async ({ expect }) => { /* ... */ }) })Mock external modules using vi.mock
To isolate tests from external dependencies (like API calls), usevi.mockto hijack a module and define its behavior. This prevents network instability and side effects on databases during unit testing.import { vi, test, expect } from "vitest" import api from "/service/api" // Hijack the module and define the return value for getApiData vi.mock("/service/api", () => ({ getApiData: vi.fn().mockReturnValue(42) })) test("mock api test", async () => { const data = await api.getApiData() expect(data).toBe(42) })