Large Front-End Documentation

website·Indexed 30 days ago

https://nanjingcaiyong.github.io/

A collection of front-end development notes and guides covering TypeScript advanced types and declaration files, package.json configuration (exports, module, main, browser), and Web Components. Includes practical tutorials on pnpm monorepos, micro-frontends, ESM vs CommonJS, and UI implementation details for sticky components and scroll synchronization.

Tokens
18.1K
Snippets
96
Records
131
Agent score
74%

What's inside Large Front-End

  1. Overview of Web Components technology suite

    Web Components provide a set of native browser APIs to create reusable, encapsulated, and framework-agnostic custom elements. The suite consists of three main technologies:

    1. Custom Elements: JavaScript APIs that allow you to define new HTML tags and their behavior.
    2. Shadow DOM: Provides a way to attach a separate, encapsulated DOM tree to an element. This ensures that the internal DOM and CSS of a component do not conflict with the main document's styles or scripts (style and DOM isolation).
    3. HTML Templates and Slots: The <template> element allows you to define markup that is not rendered immediately but can be cloned and reused. The <slot> element allows components to accept custom content from the user, increasing reusability.
  2. Understand TypeScript's Structural Typing System

    TypeScript uses a structural type system, meaning it compares types based on the actual properties and methods they possess rather than their explicit names. If a type (e.g., Dog) has all the properties required by another type (e.g., Cat), it is considered compatible.
    class Cat { eat() { } }
    class Dog { eat() { } }
    
    function feedCat(cat: Cat) { }
    
    // Works because Dog has the 'eat' method required by Cat
    feedCat(new Dog());
  3. Web Components Core Technology Overview

    Web Components are a set of native browser APIs that allow the creation of encapsulated, reusable components compatible with any framework (Vue, React, Angular). The core suite consists of:

    • Custom Elements: Using customElements.define to create new HTML tags.
    • Shadow DOM: Isolating the component's DOM and styles from the rest of the page.
    • HTML Templates: Using the <template> tag to define markup that is cloned into the component.
    • Slots: Providing placeholders within the Shadow DOM to allow users to inject custom content.
  4. Create and register a Custom Element

    To create a custom element, you must define a class that extends HTMLElement and register it using the customElements.define method.

    Naming Constraints for Custom Tags:

    • Must start with a lowercase letter.
    • Must contain at least one hyphen (-).
    • May contain lowercase letters, hyphens, underscores, periods, and numbers.
    // 1. Define the component class
    class UserCard extends HTMLElement {
      constructor() {
        super();
        const elm = document.createElement('div');
        elm.textContent = 'Hello world';
        this.append(elm);
      }
    }
    
    // 2. Register the component
    customElements.define('user-card', UserCard);

    <!-- 3. Use the custom tag in HTML --> <div> <user-card></user-card> </div>

  5. Generate TypeScript declaration files

    There are two primary ways to provide declaration files for a library:

    1. Automatic Generation: If the library is written in TypeScript, enable the declaration option in tsconfig.json (or via CLI). When running tsc, TypeScript will automatically generate .d.ts files alongside the compiled JavaScript.
    2. Manual Definition: If the library is written in JavaScript, you must manually create .d.ts files to provide type definitions for the library's consumers.
  6. Integrate legacy systems using micro-frontend frameworks

    For legacy systems or diverse technology stacks, open-source micro-frontend frameworks like single-spa or Alibaba's qiankun (built on single-spa) can be used. These frameworks typically manage the integration by:

    • Using lifecycles to mount/unmount sub-system DOM and CSS into the host.
    • Providing built-in JS sandboxing and CSS isolation.
    • Handling inter-system communication.
  7. Configure conditional exports for Monorepo Hot Module Replacement (HMR)

    In a monorepo setup, you can use conditional exports to point to source files during development (for HMR) and compiled files for production. By nesting the development condition inside the import condition, Vite and other compatible tools can resolve the source code directly. To prevent these development paths from being published to npm, use publishConfig.exports to override the rules during the publishing process.
    {
      "type": "module",
      "exports": {
        ".": {
          "import": {
            "development": "./src",
            "default": "./dist/es/index.mjs"
          }
        }
      },
      "publishConfig": {
        "exports": {
          ".": {
            "import": "./dist/es/index.mjs"
          }
        }
      }
    }
  8. Initialize a pnpm monorepo workspace

    To set up a monorepo structure with pnpm, you need to initialize the project and define a workspace configuration file. The pnpm-workspace.yaml file tells pnpm where the sub-packages are located.
    # Create project root and packages directory
    mkdir mono && cd mono
    mkdir packages
    
    # Initialize pnpm project
    pnpm init
    
    # Create workspace configuration
    touch pnpm-workspace.yaml

    pnpm-workspace.yaml content

    packages:

    • 'packages/*'
  9. Install a local workspace package as a dependency in another sub-package

    In a pnpm monorepo, you can install one sub-package into another using the --filter flag. This creates a workspace reference in the package.json of the consuming package, allowing for local development without needing to publish to a registry.
    # Install package1 into package2
    pnpm install package1 --filter package2

    Resulting dependency in package2/package.json

    { "dependencies": { "package1": "workspace:^" } }

  10. Install a workspace package into the monorepo root

    To test or debug a sub-package from the root of the monorepo, use the -w (or --workspace-root) flag to install the local package directory into the root package.json.
    # Install package2 into the root workspace
    pnpm install ./packages/package2 -w
  11. Use abstract classes and abstract methods

    Abstract classes are declared with the abstract keyword and cannot be instantiated. They define a blueprint for subclasses. Members marked abstract must be implemented by any non-abstract subclass. Note that static members cannot be abstract.
    abstract class Male {
      abstract name: string;
      abstract eat (): string;
      abstract get age (): number;
    }
    
    class Men extends Male {
      name: string = 'zhangsan';
      eat(): string { return 'eating'; }
      get age(): number { return 23; }
    }
  12. Implement micro-frontends using iframe and postMessage

    A simple way to integrate sub-systems is by embedding them via <iframe>. This provides strong CSS isolation and JS sandboxing. Communication between the host platform and sub-systems (e.g., passing authentication tokens) is handled via postMessage or URL parameters.

    Advantages:

    • Complete style (CSS) isolation.
    • Each sub-system operates in its own sandbox.
    • Simple bidirectional communication via postMessage.

    Disadvantages:

    • URL synchronization: The browser URL does not sync with the iframe URL, breaking browser history (back/forward buttons) and page refreshes.
    • UI limitations: Modals/overlays are confined within the iframe boundaries.
    • Performance: Slower load times due to browser context reconstruction and resource reloading for each sub-system.
    • Complex data synchronization between parent and child systems.