Soon Wang's Blog

website·Indexed 29 days ago

https://soonwang.me/

Technical articles and deep dives focusing on Vue reactivity (v3.5, v3.6), Vue 2 template compiler architecture, vue-tsc source code analysis, TypeScript engineering practices, and AI performance optimizations such as Prompt Caching in Agent Harnesses.

Tokens
20.1K
Snippets
65
Records
100
Agent score
50%

What's inside Soon Wang

  1. Overview of the Vue 2 Template Generator

    The Generator is the final stage of the Vue 2 template compilation process (following the Parser and Optimizer). Its primary purpose is to transform the optimized AST into executable JavaScript code, specifically a render function. This render function uses Vue runtime helper methods to create or update the DOM based on the component's data state.

    Common runtime helper methods generated include:

    • _c: Corresponds to createElement for creating virtual DOM nodes.
    • _l: Used for rendering lists (v-for).
    • _v: Used for creating text nodes.
    • _s: Used for converting values to strings.
    • _e: Used to create an empty comment node (typically for the 'else' case of a v-if).
  2. Overview of Alien Signals in Vue 3.6

    Vue 3.6 introduces Alien Signals to optimize the reactivity system. It utilizes a doubly-linked list structure for subscribers and implements a 'push-pull-push' propagation cycle to maximize performance:

    1. Push: When a signal changes, it pushes Dirty or PendingComputed flags to downstream subscribers.
    2. Pull: When a computed value is read, it pulls from upstream dependencies to check if a re-calculation is necessary.
    3. Push (Again): If a value is updated during the pull phase, a Dirty flag is pushed again to shallow subscribers.
  3. Overview of Vue 2 Template Optimizer

    The Optimizer is the second stage of the Vue 2 template compilation process. It takes the AST produced by the Parser and identifies static nodes—elements that do not change based on data. By marking these nodes, Vue can skip virtual DOM diffing for them during the runtime patch phase, significantly improving rendering performance.
  4. Understand Vue 3.5 reactivity architecture changes

    Vue 3.5 refactored its reactivity system based on principles from Preact Signals to improve performance and memory efficiency. Key architectural changes include:

    • Doubly-Linked List Structure: Instead of a direct many-to-many relationship between Subscribers (Sub) and Dependencies (Dep), Vue 3.5 introduces an intermediate link node. This decouples dependencies from subscribers.
    • Version Counting: Implemented to solve the equality problem more efficiently than simple dirty flags.
    • Lazy Computed Logic: Computed properties now utilize lazy subscription and automatic unsubscription to minimize the number of active dependencies.
  5. Understand the Vue 2 Template Compilation Pipeline

    The Vue 2 template compiler transforms a template string into a render function through three distinct stages:

    1. Parser: Converts the template string into an Abstract Syntax Tree (AST).
    2. Transformer (Optimizer): Transforms and optimizes the AST to improve rendering efficiency.
    3. Generator (Codegen): Converts the optimized AST into the final JavaScript render function code that the browser executes.
  6. Understand the Vue 2 template compiler Parser architecture

    The Vue 2 template compiler's parsing phase is split into two primary components:

    1. parseHTML: A lexical analyzer (tokenizer) that scans the template string and converts it into a series of tokens. It provides hooks (start, end, chars) to notify the caller when specific HTML elements are encountered.
    2. parse: A syntax analyzer that consumes the tokens and hooks provided by parseHTML to construct the Abstract Syntax Tree (AST).
  7. Vue 2 Compiler Architecture and Entry Point

    The compiler's core logic is located in src/compiler. The createCompiler function acts as a factory that produces a compiler instance. This instance provides two primary methods:

    • compile: Compiles a template string and returns an object containing the ast, the render function code, and staticRenderFns (static render functions used to optimize static nodes).
    • compileToFunctions: Compiles the template and immediately converts the resulting code strings into executable JavaScript functions. This is used when templates are compiled in the browser at runtime rather than during a build step.
    // src/compiler/index.ts
    import { parse } from './parser/index'
    import { optimize } from './optimizer'
    import { generate } from './codegen/index'
    import { createCompilerCreator } from './create-compiler'
    import { CompilerOptions, CompiledResult } from 'types/compiler'
    
    export const createCompiler = createCompilerCreator(function baseCompile(
      template: string,
      options: CompilerOptions
    ): CompiledResult {
    	// 1. Parse: Template -> AST
      const ast = parse(template.trim(), options)
      
    	// 2. Transform/Optimize: AST -> AST
      if (options.optimize !== false) {
        optimize(ast, options)
      }
      
    	// 3. Generate: AST -> Render Function Code
      const code = generate(ast, options)
      
      return {
        ast,
        render: code.render,
        staticRenderFns: code.staticRenderFns
      }
    })
  8. Understand Vue 3.5+ Push-Pull Reactivity Propagation

    Vue 3.5+ employs a hybrid Push-Pull reactivity model to manage updates in computed properties and subscribers.

    1. Push Phase (Dirty Marking): When a dependency changes, Vue performs a depth-first search (DFS) to mark downstream subscribers. Shallow subscribers are marked as Dirty, while deeper nested computed properties are marked as PendingComputed. This avoids immediate re-computation of the entire chain.
    2. Pull Phase (Lazy Evaluation): When a computed value is accessed via a getter, Vue checks its flags. If it is marked Dirty or PendingComputed, it triggers a 'pull' process. If PendingComputed, it recursively checks its own dependencies (pulling upwards) until it finds a Dirty node or confirms no change is needed. If the value actually changes during this process, it triggers a shallowPropagate to notify its immediate subscribers.
  9. Understand SolidJS's non-Virtual DOM architecture

    Unlike React or Vue (pre-3.6), SolidJS does not use a Virtual DOM (VDOM) or a reconciliation/diffing process. Its design philosophy combines fine-grained reactivity with compile-time transformations. Components execute only once to create real DOM nodes; subsequent state updates trigger direct updates to the DOM via reactive bindings, bypassing the need to re-run the component function or diff VNodes.
  10. Understand Reactive Propagation Models (Push, Pull, Push-Pull)

    Reactivity systems use different algorithms to propagate changes from dependencies to subscribers:

    • Push-based (Eager): When a dependency changes, it immediately pushes the new value to downstream subscribers. This is real-time but can lead to redundant calculations.
    • Pull-based (Lazy): Calculations are deferred until the value is actually accessed (e.g., during a render phase). It reduces redundant work by only calculating on demand.
    • Push-pull hybrid: A combination where a change first 'pushes' a notification (like a dirty mark) to subscribers to let them know a dependency has changed, but does not send the value. The subscriber then 'pulls' the actual updated value only when needed.
  11. Understand how vue-tsc integrates with the TypeScript compiler

    vue-tsc enables .vue file support by intercepting the standard tsc execution. It uses a function called runTsc which performs the following steps:

    1. Locates the local typescript/lib/tsc source file.
    2. Overrides fs.readFileSync to dynamically modify the tsc.js source code in memory.
    3. Patches supportedTSExtensions, supportedJSExtensions, and allSupportedExtensions to include .vue.
    4. Proxies the core createProgram method with proxyCreateProgram to inject Volar's language plugins and custom file system logic.
  12. Understand KV Cache and Prompt Caching in Agents

    In Transformer models, the Prefill phase processes all input tokens, and the Decode phase generates new tokens. To avoid redundant calculations during Decode, the model stores intermediate Key (K) and Value (V) states as a KV-cache.

    Prompt Caching leverages Prefix Caching mechanisms: if a new request shares the same prefix as a previous one, the system reuses the existing KV-cache and only performs Prefill for the new incremental tokens. This significantly reduces the Time to First Token (TTFT) and inference costs, which is critical for Agents where input-to-output token ratios can be as high as 294:1.