Web Frontend Architecture: Scaffolding, Project Analysis, and Technology Review

Scaffolding, Project Initialization, and Component Development

EJS Template Engine: Three Usage Patterns

The EJS (Embedded JavaScript) template engine provides flexible ways to generate HTML. Here are three fundamental approaches:

// index.js
const ejs = require('ejs');
const path = require('path');
const fs = require('fs');

const templateString = '<div><%= userData.name %></div>';
const config = {};
const userData1 = { name: "alice" };
const userData2 = { name: "bob" };

// 1. Compile and reuse
const compiledFn = ejs.compile(templateString, config);
const output1 = compiledFn(userData1);
const output2 = compiledFn(userData2);

// 2. Direct rendering
const directOutput = ejs.render(templateString, userData1, config);

// 3. Render from file
// 3.1 Promise-based
ejs.renderFile(path.resolve(__dirname, 'template.html'), userData1, config)
  .then(renderedContent => console.log(renderedContent));

// 3.2 Callback-based with custom options
const callbackData = {
  user: { name: "charlie", nickname: "<div>charlie</div>", copyright: "example" }
};
const callbackConfig = { delimiter: "%" };

// Custom file loader
ejs.fileLoader = function(filePath) {
  const originalContent = fs.readFileSync(filePath).toString();
  return '<div style="color: blue;">Custom Footer: <%= user.copyright %></div>' + originalContent;
};

ejs.renderFile(path.resolve(__dirname, 'template.html'), callbackData, callbackConfig, (err, result) => {
  if (err) console.error(err);
  console.log(result);
});

EJS Tags:

  • <%: Script tag for control flow, no output.
  • <%_: Trims preceding whitespace.
  • <%=: Outputs escaped HTML.
  • <%-: Outputs unescaped data.
  • <%#: Comment tag, ignored.
  • <%%: Outputs literal '<%'.
  • %>: Standard end tag.
  • -%>: Trims following newline.
  • _%>: Trims following whitespace.
// template.html
<% if(userData) { %>
  <% for(let i = 0; i < 5; i++) { %>
    <!-- Display user name -->
    <div><%= userData.name %></div>
    <%- userData.nickname %>
  <% } %>
<% } %>
<!-- Include footer -->
<%- include('./footer.html', { user: userData }) %>

// footer.html
<div>Footer: <%= user.copyright %></div><% -%>

Glob Module: File Pattern Matching

The glob module simplifies finding files matching patterns.

// Install: npm i glob@8
const glob = require('glob');

glob('**/*.js', {
  ignore: ['node_modules/**', 'webpack.config.js']
}, (error, matchedFiles) => {
  if (error) console.error(error);
  console.log('Matched files:', matchedFiles);
});

EJS Source Code Deep Dive: Template Rendering Mechanism

EJS's core execution flow:

  1. new Template: Initializes the template object.
  2. compile: Compiles the template into a function that accepts data for rendering.

Compilation Steps:

  • template → createRegex: Generates regex for template parsing.
  • generateSource → generateFunctionSource → generateFunction: Produces the executable function.

require Module Loading: Understanding Node.js Module System

Usage Scenarios:

  • Load built-in modules: require('fs')
  • Load npm modules: require('ejs')
  • Load local modules: require('./utils')

Supported File Types:

  • .js, .json, .node, .mjs, and other types (treated as JS)

Key Questions:

  • How does CommonJS load main modules?
  • How are built-in modules loaded?
  • How are node_modules modules resolved?
  • Why are non-JS/JSON/node files treated as JS?
  • How is module caching handled?

Module Object Properties:

  • id: Full file path
  • path: Directory of the file
  • exports: Module's exported content
  • parent: Parent module
  • filename: File path
  • loaded: Loading status
  • children: Child modules
  • paths: Module lookup paths

Execution Flow:

  1. Module._load
    • loadNativeModule: For built-in modules
    • new Module: Instantiate module
    • Module._cache[filename] = module: Cache module
  2. module.load(filename)
    • findLongestRegisteredExtension: Determine file extension
    • Module._extensions[extension]: Execute file
  3. module._compile
    • compileFunction: Generate executable function
    • compiledWrapper.call: Execute module code

B2B Project Analysis and Architecture Design

Introduction

This section covers:

  • Project types for overcoming development plateaus
  • Identifying key challenges from requirements
  • Creating technical solutions
  • Technology selection

Key Concepts:

  • Identifying pain points
  • Documenting technical solutions
  • Reusable business component libraries
  • Editor design (mapping UI to data)
  • TypeScript, Vue 3, React

Complex Projects

Business Complexity:

  • Interaction complexity
  • Data structure and state complexity
  • Inter-project dependencies
  • Packaging and performance optimization
  • Third-party integration

Process Complexity:

  • Git workflow
  • Linting tools
  • Unit testing
  • Commit messages
  • PR reviews
  • CI/CD

Requirement Analysis

Project Challenges:

  • Component implementation
  • Cross-project reuse
  • Component extensibility
  • Editor state management
  • Add/remove operations
  • Property-to-form rendering
  • Real-time feedback
  • Plugin architecture

Component Library Solutions:

  • Sharing components across projects
  • Property design strategies
  • Maintaining extensibility

Editer Implementation (Pseudo-code)

Store Structure:

interface EditorStore {
  components: ComponentData[];
  currentElement: string;
}

interface ComponentData {
  props: { [key: string]: any };
  id: string;
  name: string;
}

const components = [
  { id: '1', type: 'l-text', props: { text: 'hello', color: 'green' }},
  { id: '2', type: 'l-text', props: { text: 'world', color: 'purple' }}
];

// Render components
components.map(component => <component.name { ...component.props } />);

const templateComponents = [
  { type: 'l-text', props: { text: 'Template 1', color: 'green' }},
  { type: 'l-text', props: { text: 'Template 2', color: 'purple' }}
];

// Render with wrapper
templateComponents.map(component => <Wrapper><component.name { ...component.props } /></Wrapper>);

// Remove component
components = components.filter(c => c.id !== '1');

Selection Handling:

const textComponentProps = {
  text: 'hello',
  fontFamily: 'Arial',
  color: '#000'
};

const propsMap = {
  text: { component: 'input' },
  fontFamily: { component: 'dropdown' },
  color: { component: 'color-picker' }
};

Object.entries(textComponentProps).map(([key, value]) => {
  const handleChange = (propKey: string, newValue: any, id: string) => {
    const component = store.components.find(c => c.id === id);
    if (component) component.props[propKey] = newValue;
  };
  
  return <propsMap[key].component value={value} onChange={(newValue) => handleChange(key, newValue, '1')} />;
});

Technology Selection

  • TypeScript: Improved code understanding, higher efficiency, fewer errors, good TypeScript compatibility.
  • Vue vs React: Implementation style, data update mechanisms, code reusability.

Language (TypeScript) and Framework (Vue 3)

  • Scaffolding (linding-cli-dev)
  • Testing (jest + vue-test-utils)
  • Build tools (webpack+rollup)
  • CI/CD (travis)
  • UI library (ant-design-vue)
  • State management and routing (vuex, vue-router)
  • Third-party libraries
  • Styling solutions

Frontend Fundamentals Review

TypeScript

Key Concepts:

  • Basic types
  • Interfaces
  • Classes
  • Ganerics
  • Declaration files
  • Type inference
  • Union types
  • Intersection types
  • Type assertions
  • Built-in types
  • Type aliases
  • Keyof and in operators
// Function with properties
interface FunctionWithProps {
  (x: number): number;
  name: string;
}

const fn: FunctionWithProps = (x: number) => x;
fn.name = 'example';

// Interface for classes
interface ClockInterface {
  currentTime: number;
  alert(t: number): void;
}

interface ClockConstructor {
  new (h: number, m: number): void;
  time: number;
}

const Clock: ClockConstructor = class implements ClockInterface {
  static time = 12;
  currentTime = 123;
  
  constructor(h: number, m: number) {
    console.log(h, m);
  }
  
  alert(t: number) {
    console.log(t);
  }
};

// Generic API call
interface CountryData {
  name: string;
  area: number;
  population: number;
}

function apiCall<T>(url: string): Promise<T> {
  return fetch(url).then(resp => resp.json());
}

apiCall<CountryData>('country.json').then(data => {
  console.log(data.name);
  console.log(data.area);
  console.log(data.population);
});

// Partial implementation
interface Person {
  name: string;
  age: number;
}

type PersonPartial = {
  [K in keyof Person]?: Person[K];
};

// Conditional types
type User<T> = T extends { name: string } 
  ? { name: string; age: number } 
  : { age: number };

type User1 = User<{ married: boolean }>;
type User2 = User<{ name: string; married: boolean }>;

// HTTP method type
type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';

declare function fetcher<T = any>(
  url: string, 
  method: HttpMethod, 
  data?: any
): Promise<T>;

declare namespace fetcher {
  const get: <T = any>(url: string) => Promise<T>;
  const post: <T = any>(url: string, data: any) => Promise<T>;
}

Vue 3

New Features:

Why Vue 3?

  • Vue 2 limitations: Lack of abstraction for logic code
  • Poor TypeScript support

Composition API:

  • setup
  • ref
  • reactive (note: loses reactivity on property access)
  • toRefs
  • Lifecycle hooks

Reactive System Deep Dive:

  • Stores effects for future execution
  • Detects object value changes using Proxy
  • Triggers stored effects when values change

Side Effects:

  • Pure functions: Same input → same output, no side effects
  • Side effects: Interactions with external environment
  • watchEffect: Automatically tracks dependencies, can be manually stopped
  • watch: Precise control over effects

Custom Hooks:

  • Group related features
  • Highly reusible

Custom Functions Benefits:

  • Clear parameter and return types
  • Avoid naming conflicts
  • Logic separated from components
  • Generics support
  • Comparison with React implementation

Additional Topics:

  • Teleport
  • Fragment
  • Emits component option
  • Global API changes
  • Syntax sugar: <script setup>, <style vars>

Tags: EJS glob require TypeScript vue3

Posted on Sun, 27 Sep 2026 16:33:14 +0000 by launchcode