Frontend Development 20 min read

Design and Implementation of a Custom Frontend Build and Deployment Platform (Yunzhang)

This article explains why a dedicated frontend build platform is needed, describes its core capabilities such as automated build, pluggable pipelines, audit‑based release, and external plugin exposure, and details the Docker‑in‑Docker architecture, process‑pool design, and sample Node.js code for a scalable CI/CD solution.

政采云技术
政采云技术
政采云技术
Design and Implementation of a Custom Frontend Build and Deployment Platform (Yunzhang)

Introduction

The article originates from the ZooTeam frontend blog and discusses the motivation for building a self‑owned frontend build and deployment platform called "Yunzhang" despite existing solutions like Jenkins, Docker, and GitHub Actions.

Problems with Existing Solutions

Eslint checks can be skipped by developers, leading to inconsistent code quality.

npm version upgrades may cause incompatibility errors after deployment.

Adding custom features is difficult because the platform depends on external operations teams.

Yunzhang aims to solve these issues.

Yunzhang Capabilities

Build and Deployment

Supports multiple frontend project types (Pampas, React, Vue, Uniapp). The workflow updates code, installs dependencies, bundles the project, creates a Docker image, uploads static assets to a CDN, and finally deploys the image via Kubernetes.

Pluggable Build Pipeline

Provides open APIs so frontend developers can add custom plugins. The pipeline can enforce Eslint/Tslint checks, npm version validation, and post‑build resource injection (e.g., analytics, error monitoring).

Audit Release Process

After testing in a pre‑release environment, developers submit a release request. Approvers receive the request via DingTalk and can approve or reject it. Once approved, developers can deploy the release themselves, and a Merge Request is automatically created for code archiving.

External Capability Exposure

A VS Code extension is provided, allowing developers to trigger builds, update mini‑programs, and perform route lookups directly from the editor, reducing context switching.

Yunzhang Architecture

The platform runs both client and server inside Docker containers (Docker‑in‑Docker). Each build runs in an isolated process pool instance; progress is tracked via Redis, and metadata is stored in MySQL. Deployment is performed by invoking Kubernetes APIs.

Frontend Build from 0 to 1

The article presents a step‑by‑step design of the core modules, starting with a build record table, then describing a pipeline implementation using a pipeline array of tasks (code update, dependency install, checks, pack, resource injection, Docker image build).

async run() {
  const app = this.app;
  const processData = {};
  const pipeline = [{
    handler: context => app.fetchUpdate(context), // Git update
    name: 'codeUpdate',
    progress: 10
  }, {
    handler: context => app.installDependency(context), // npm install
    name: 'dependency',
    progress: 30
  }, {
    handler: context => app.check(context), // lint, version check
    name: 'check',
    progress: 40
  }, {
    handler: context => app.pack(context), // npm run build
    name: 'pack',
    progress: 70
  }, {
    handler: context => app.injectScript(context), // post‑build injection
    name: 'injectRes',
    progress: 80
  }, {
    handler: context => app.buildImage(context), // Docker image build & push
    name: 'buildImage',
    progress: 90
  }];
  for (let i = 0; i < pipeline.length; i++) {
    const task = pipeline[i];
    const [err, response] = await to(this.execProcess({ ...task, step: i }));
    if (response) {
      processData[task.name] = response;
    }
  }
  return Promise.resolve(processData);
}

Node's child_process module is used to run shell commands such as git clone and npm run build . Example code for executing commands and handling output is provided.

import { spawn } from 'child_process';
function execCmd(cmd: string, options = {}) {
  const [shell, ...args] = cmd.split(' ').filter(Boolean);
  const child = spawn(shell, args, options);
  // handle stdout, stderr, exit, error events ...
}

A process pool implementation (ProcessPool.ts) manages multiple concurrent build workers, using a task queue, idle/working pools, and Redis for progress caching. Sample code shows initialization, forking workers, handling messages, and graceful shutdown.

export default class ProcessPool extends EventEmitter {
  private jobQueue: TaskQueue;
  private depth: number;
  private workerPath: string;
  private workPool: Map
;
  private idlePool: Array
= [];
  constructor(options = {}) {
    super();
    this.jobQueue = new TaskQueue('fap_pack_task_queue');
    this.depth = options.depth || cpus().length;
    this.workerPath = options.workerPath;
    this.init();
  }
  // init, forkProcess, run, getFreeProcess, etc.
}

Build.ts demonstrates how to configure the pool, listen for log, finish, and fail messages, and add new build tasks.

const packQueue = new ProcessPool({ workerPath: path.join(__dirname, '../../task/func/worker'), depth: 3 });
packQueue.process(path.join(__dirname, '../../task/func/server-build'));
await packQueue.add({ ...appAttrs });

Future Directions

Plans include more stable and faster builds, richer CI/CD flows (automatic archiving, branch merging, multi‑environment updates), distributed local builds to reduce server load, and group‑based batch releases.

Conclusion

Having an in‑house build and release platform gives frontend teams full control over features, quality checks, and deployment speed, and the accompanying VS Code plugin further streamlines development tasks.

frontendDockerBuild AutomationCI/CDKubernetesnodejsprocess pool
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.