⚠️温馨提示: 文档中包含【1个】暂不支持的区域,请通过搜索关键字【暂不支持的文档区域】进行后续处理

lowcode-2-notes.zip

过往分享了很多进阶知识与架构内容, 课程文档列表 见文末,配套对应 课程文档和配套视频回放找咨询老师 领取~ 希望对你的技术成长有帮助!

  • 初中级 】你们低代码平台的物料是怎么管理的,远程物料是怎么加载的,请详细说明核心流程与方案
  • 中高级 】看你简历上写自研低代码远程物料管理基座与页面编排渲染引擎,说说核心实现及详细技术点
  • 专家级 】作为 Leader,说说设计低代码平台物料体系与编排引擎的核心思路、方案与成果

初中级 】你们低代码平台的物料是怎么管理的,远程物料是怎么加载的,请详细说明核心流程与方案

核心理念

低代码平台的物料管理采用 插件化机制 ,该机制使得开发者可以灵活扩展物料功能,同时保持核心逻辑稳定,避免对主体代码的频繁改动。

核心思想:

  • 物料解耦 :核心系统(底座)专注于管理物料的加载和注册,物料资源以插件的形式提供,可以动态加载和扩展。
  • 插件化设计 :物料功能作为插件,通过接口约定与核心系统通信,支持本地和远程动态加载。

插件化管理物料的核心设计

程序主体:物料管理系统

核心系统( BlockSuite 类)负责管理所有物料(插件),提供物料的注册、查询和加载功能。

示例代码:

class BlockSuite {
  private blocks = baseBlocks; // 基础物料集合
  constructor() {}
  // 获取物料映射(type -> material)
  getBlocksMap() {
    return Object.fromEntries(this.blocks.map((block) => [block.type, block]));
  }
  // 获取物料列表
  getBlocks() {
    return this.blocks;
  }
  // 注册新物料
  addBlock(block: any) {
    this.blocks.push(block);
  }
  // 判断某种类型的物料是否存在
  hasBlock(type: BlockType) {
    return !!this.getBlocksMap()[type];
  }
}

插件接口声明

插件的设计遵循统一的接口声明,定义了物料的基本属性(如类型、资源)。

interface Block {
  type: string;      // 物料类型
  material: any;     // 物料资源
}

插件实现

插件以独立模块的形式存在,可以是本地文件或远程资源,例如:

  • 本地物料QuoteBlock.vueButtonBlock.vue
  • 远程物料 :从远程市场加载的动态模块

注册本地物料:

const baseBlocks = [
  { type: 'quote', material: QuoteBlock },
  { type: 'heroTitle', material: HeroTitleBlock },
  { type: 'button', material: ButtonBlock },
];

动态注册新物料:

blockSuite.addBlock({
  type: 'notes',
  material: NotesBlock,
});

支持远程物料的加载机制

方案与流程

远程物料资源的管理与配置

远程物料通常以模块化的形式存在,可以通过 HTTP 请求从物料市场加载。

const remoteMaterialConfig = [
  { type: 'chart', url: 'https://cdn.example.com/materials/ChartBlock.js' },
  { type: 'image', url: 'https://cdn.example.com/materials/ImageBlock.js' },
];

动态加载远程物料

通过 import()fetch 加载远程物料资源:

async function loadRemoteBlock(url: string) {
  const module = await import(/* @vite-ignore */ url);
  return module.default;
}
async function registerRemoteBlocks(remoteMaterials: Array<any>) {
  for (const material of remoteMaterials) {
    const materialResource = await loadRemoteBlock(material.url);
    blockSuite.addBlock({
      type: material.type,
      material: materialResource,
    });
  }
}
// 加载并注册远程物料
registerRemoteBlocks(remoteMaterialConfig);

核心流程

  1. 基础物料初始化

    • 加载本地物料资源( baseBlocks )。
    • 将本地物料注册到 BlockSuite 类。
  2. 远程物料动态加载

    • 从远程市场获取物料配置( remoteMaterialConfig )。
    • 使用 import() 加载物料资源。
    • 调用 BlockSuite.addBlock() 注册到系统中。
  3. 物料的消费

    • 系统通过 BlockSuite.getBlocksMap()BlockSuite.getBlocks() 提供物料查询接口。
    • Vue 组件通过全局 blocksMap 访问所有已注册的物料。

示例:

const blocksMap = blockSuite.getBlocksMap();
app.provide(blocksMapSymbol, blocksMap);
app.config.globalProperties.$blocksMap = blocksMap;

物料插件化的优点

  1. 高扩展性 :新增物料无需修改底座代码,只需注册插件。
  2. 灵活加载 :支持本地与远程物料的无缝加载。
  3. 解耦性强 :物料与核心逻辑分离,维护成本低。
  4. 动态化 :支持按需加载,减少初始加载时间。

实际应用场景

  • 物料市场 :低代码平台的用户可以从市场中挑选需要的物料(组件)并动态加载。
  • 动态表单 :表单控件作为物料插件化,通过配置加载不同的控件。
  • 动态布局 :根据用户需求,动态加载页面布局物料。

中高级 】看你简历上写自研低代码远程物料管理基座与页面编排渲染引擎,说说核心实现及详细技术点

远程物料基座(构建、发布、加载)

构建远程物料的基本要求

远程物料需要满足以下条件:

  1. 模块化 :支持按需加载,使用 ESMUMD 格式输出。
  2. 兼容性 :适配不同的运行环境(浏览器或 Node.js)。
  3. 独立性 :每个物料可以独立构建,不依赖于其他插件。
  4. 优化体积 :构建时去除无关依赖,保持轻量化。

使用 tsup 打包远程物料

配置 tsup

tsup 是一个现代化的构建工具,支持 TypeScript 和多种打包格式。我们可以为每个远程物料单独创建配置文件,生成独立的构建产物。

安装依赖:

npm install tsup typescript --save-dev

创建 tsup.config.ts 文件:

import { defineConfig } from 'tsup';
export default defineConfig({
  entry: ['src/index.ts'],        // 入口文件
  format: ['esm'],                // 输出为 ESM 格式
  outDir: 'dist',                 // 输出目录
  clean: true,                    // 构建时清理旧的产物
  dts: true,                      // 生成 TypeScript 类型声明
  minify: true,                   // 压缩代码
  splitting: false,               // 不进行代码分割,确保产物是单个文件
  sourcemap: false,               // 是否生成 sourcemap
  external: ['vue'],              // 外部依赖,不打包到最终产物中
});

构建物料插件

ButtonBlock 物料为例,假设其代码位于 src/ButtonBlock.vue

  1. 创建 src/index.ts
import { defineAsyncComponent } from 'vue';
import ButtonBlock from './ButtonBlock.vue';
export default {
  name: 'ButtonBlock',
  type: 'button',
  material: defineAsyncComponent(() => Promise.resolve(ButtonBlock)), // 异步加载组件
};
  1. 执行打包:
npx tsup
  1. 构建结果:

    • dist/index.js : 构建后的物料主文件(ESM 格式)。
    • dist/index.d.ts : TypeScript 类型声明文件。

远程物料的目录结构示例

远程物料的目录通常按照模块化原则组织:

remote-materials/
├── ButtonBlock/
│   ├── src/
│   │   ├── ButtonBlock.vue
│   │   └── index.ts
│   ├── dist/
│   │   ├── index.js          # 构建后的 JS 文件
│   │   ├── index.d.ts        # 类型声明文件
│   │   └── style.css         # 可能的样式文件
├── ChartBlock/
│   ├── src/
│   │   ├── ChartBlock.vue
│   │   └── index.ts
│   ├── dist/
│   │   └── index.js
│   │   └── index.d.ts

加载远程物料的动态实现

动态加载物料

通过 HTTP 请求加载远程物料的 JS 文件,并将其注册到 BlockSuite 中。

示例代码:

async function loadRemoteMaterial(url: string) {
  // 动态加载 ESM 模块
  const module = await import(/* @vite-ignore */ url);
  return module.default;
}
async function registerRemoteMaterials(remoteConfigs: Array<{ type: string; url: string }>) {
  for (const config of remoteConfigs) {
    const material = await loadRemoteMaterial(config.url);
    blockSuite.addBlock({
      type: config.type,
      material: material.material, // 动态注册物料
    });
  }
}
// 示例远程配置
const remoteMaterialConfig = [
  { type: 'button', url: 'https://cdn.example.com/ButtonBlock/index.js' },
  { type: 'chart', url: 'https://cdn.example.com/ChartBlock/index.js' },
];
// 加载远程物料
registerRemoteMaterials(remoteMaterialConfig);

异步组件渲染

Vue 中通过 defineAsyncComponent 渲染异步加载的物料:

import { defineAsyncComponent } from 'vue';
export default {
  components: {
    AsyncButtonBlock: defineAsyncComponent(() => import('https://cdn.example.com/ButtonBlock/index.js')),
  },
};

核心流程总结

构建流程

  1. 使用 tsup 为每个物料模块生成独立的构建产物(ESM 格式)。

  2. 输出文件包括:

    • 主模块文件: index.js
    • 类型声明文件: index.d.ts
    • 样式文件(如需): style.css

加载流程

  1. 获取远程物料的配置(包含 typeurl )。
  2. 使用 import() 动态加载物料模块。
  3. 调用 BlockSuite.addBlock() 注册物料。
  4. 在 Vue 中通过异步组件渲染物料。

优化与扩展

缓存优化

  • 使用 localStorageIndexedDB 缓存已加载的物料,减少重复加载。
  • 示例:
async function loadWithCache(url: string) {
  const cache = sessionStorage.getItem(url);
  if (cache) {
    return JSON.parse(cache);
  }
  const module = await import(/* @vite-ignore */ url);
  sessionStorage.setItem(url, JSON.stringify(module.default));
  return module.default;
}

CDN 加速

  • 将远程物料部署到 CDN,提高加载速度。
  • 示例配置:
{
  "baseUrl": "https://cdn.example.com/materials/"
}

版本管理

  • 为远程物料添加版本控制,避免兼容性问题。
  • 示例 URL: https://cdn.example.com/ButtonBlock/v1.0.0/index.js

布局引擎

布局引擎是低代码平台中的核心,用于构建应用界面的 UI 布局。不同的布局引擎设计直接影响开发者的灵活性和用户体验。常见的布局方式包括 Flexbox、Block、Grid 和 Canvas ,每种方案都有其适用场景。

引擎分类

Flex 布局

  • 特点 : Flexbox(弹性盒模型)是响应式布局的核心选择,能够很好地适配动态宽高和方向排列需求。

  • 应用场景 : 适合内容随窗口大小调整的动态界面。

  • 实现方式 :

    1. 定义容器的 flex 属性:支持水平或垂直排列。
    2. 子组件通过 orderflex-grow 实现动态空间分配。
    3. 提供交互式配置面板,开发者无需直接写 CSS,系统根据操作生成。
  • 优劣势 :

    • 优势:灵活、易用,适合响应式场景。
    • 劣势:在复杂布局中,子元素相互依赖可能造成维护困难。

Block 布局

  • 特点 : 类似传统 HTML/CSS 的 block 元素方式,按顺序垂直排列。

  • 应用场景 : 简单表单或线性排列的页面。

  • 实现方式 :

    • 提供拖拽控件,用于生成层叠的 DOM 元素。
    • 支持嵌套子块,构建父子关系树。
  • 优劣势 :

    • 优势:实现简单,学习曲线低。
    • 劣势:不适合复杂布局,不够灵活。

Grid 布局

  • 特点 : 基于 CSS Grid 的两维布局方式,通过行列的划分实现复杂页面结构。

  • 应用场景 : 大量控件排列的复杂后台管理系统。

  • 实现方式 :

    1. 用户可拖拽控件到网格中,动态调整行列比例。
    2. 后端保存网格配置,渲染时通过 grid-template 属性重建。
  • 优劣势 :

    • 优势:强大的二维布局能力,适合复杂页面。
    • 劣势:初学者上手较难。

Canvas 布局

  • 特点 : 自由画布,支持绝对定位。

  • 应用场景 : 设计工具或需要高度自定义的页面。

  • 实现方式 :

    • 使用 HTML5 Canvas 或类似的引擎(如 Konva.js)进行绘制。
    • 鼠标拖拽生成坐标,绑定组件样式。
  • 优劣势 :

    • 优势:自由度高,能满足个性化需求。
    • 劣势:控件间的对齐、响应式支持需手动处理,开发成本高。

Flex 布局引擎核心实现

/*
 *   Copyright (c) 2024 妙码学院 @Heyi
 *   All rights reserved.
 *   妙码学院官方出品,作者 @Heyi,供学员学习使用,可用作练习,可用作美化简历,不可开源。
 */

export type AreaType = {
    id: string
    containerId: string
    position: 'left' | 'right' | 'top' | 'bottom'
    width: number
    height: number
    left: number
    // right: number;
    top: number
    // bottom: number;
    subAreas?: AreaType[]
}

let isDragging = false

let dragId = ''

// engine
let currentOverlay: HTMLDivElement | null = null

let start = { x: 0, y: 0, top: 0, left: 0 }
let delta = { x: 0, y: 0 }

let indicator: HTMLElement | null

let insertPayload: {
    nodeId: string
    parentId: string
    position?: AreaType['position']
} | null = null

let nodeAreas: AreaType[] = []

const areaSize = 12
const areaOffset = areaSize / 2

const generateAreas = () => {
    // 使用层序遍历,将获得的 nodes 处理生成区域,追加到 nodeAreas 中
    // 1. 获取所有 node
    const nodes = document.querySelectorAll('[data-node]')
    const nodesMap = new Map<string, HTMLElement>()
    nodes.forEach(node => {
        const dom = node as HTMLElement
        const nodeId = dom.getAttribute('data-node')
        if (nodeId) {
            nodesMap.set(nodeId, dom)
        }
    })
    // 2. 层级遍历,通过节点上 containerId、direction、nodeId 生成区域
    const queue = [...nodes]
    while (queue.length) {
        const node = queue.shift() as HTMLElement
        const containerId = node.getAttribute('data-container')
        const nodeId = node.getAttribute('data-node')

        const parentContainer = nodesMap.get(containerId as string)
        const parentContainerId = parentContainer?.getAttribute('data-node')
        const parentContainerDirection = parentContainer?.getAttribute('data-direction')

        if (!containerId || !nodeId || !parentContainer || !parentContainerId || nodeId === dragId) {
            continue
        }

        const { left, right, top, bottom } = node.getBoundingClientRect()
        const { width: pWidth, height: pHeight, left: pLeft, top: pTop } = parentContainer.getBoundingClientRect()

        const isRow = parentContainerDirection === 'row'
        // const isFirst = node.getAttribute("data-node-index") === "0";
        const nodeIndex = node.getAttribute('data-node-index')
        const nodeCount = parentContainer.getAttribute('data-node-count')
        const isLast = nodeIndex && nodeCount && Number(nodeIndex) === Number(nodeCount) - 1

        nodeAreas.push({
            id: nodeId,
            containerId: parentContainerId,
            position: isRow ? 'left' : 'top',
            width: isRow ? areaSize : pWidth,
            height: isRow ? pHeight : areaSize,
            left: isRow ? left - areaOffset : pLeft,
            top: isRow ? pTop : top - areaOffset,
        })

        // 如果是最后一个元素,需要额外再生成一个区域
        if (isLast) {
            nodeAreas.push({
                id: nodeId,
                containerId: parentContainerId,
                position: isRow ? 'right' : 'bottom',
                width: isRow ? areaSize : pWidth,
                height: isRow ? pHeight : areaSize,
                left: isRow ? right - areaOffset : pLeft,
                top: isRow ? pTop : bottom - areaOffset,
            })
        }
    }
}

// 创建区域指示,用来调试的
// const createAreaIndicator = () => {
//   nodeAreas.forEach((area) => {
//     const { left, top, width, height } = area;
//     const dom = document.createElement("div");
//     dom.setAttribute("data-area", "true");
//     dom.style.position = "absolute";
//     dom.style.left = `${left}px`;
//     dom.style.top = `${top}px`;
//     dom.style.width = `${width}px`;
//     dom.style.height = `${height}px`;
//     dom.style.backgroundColor = "rgba(0, 0, 0, 0.1)";
//     document.body.appendChild(dom);
//   });
// };

const createIndicator = (hoveredArea: AreaType) => {
    const { left, top, width, height } = hoveredArea

    if (document.querySelector('[data-indicator]')) {
        indicator = document.querySelector('[data-indicator]')
        // indicator?.remove();
    } else {
        indicator = document.createElement('div')
        indicator.setAttribute('data-indicator', 'true')
        // container.appendChild(indicator);
        document.body.appendChild(indicator)
    }

    if (!indicator) {
        return null
    }

    indicator.style.position = 'absolute'
    indicator.style.left = `${left}px`
    indicator.style.top = `${top}px`
    indicator.style.width = `${width}px`
    indicator.style.height = `${height}px`
    indicator.style.backgroundColor = 'rgba(0, 0, 0, 1)'
}

export const init = () => {
    const mouseDownHandler = (event: MouseEvent) => {
        if (event.button !== 0) {
            return
        }
        event.stopPropagation()
        document.body.style.cursor = 'grabbing'
        document.body.style.userSelect = 'none'
        const dom = event.target as HTMLElement
        isDragging = true
        dragId = dom.getAttribute('data-node') as string

        generateAreas()

        console.log('🚀 ~ mouseDownHandler ~ dragId:', nodeAreas)

        // 创建区域指示
        // createAreaIndicator();

        /**
         * start = { x: event.clientX, y: event.clientY }
         */
        const domRect = dom?.getBoundingClientRect()

        if (domRect) {
            start = {
                x: event.clientX,
                y: event.clientY,
                top: domRect.top,
                left: domRect.left,
            }
        }

        const overlay = dom?.cloneNode(true) as HTMLDivElement
        overlay.removeAttribute('data-node')
        overlay.style.pointerEvents = 'none'
        overlay.style.position = 'absolute'
        overlay.style.width = `${domRect?.width + 15}px`
        overlay.style.maxHeight = '200px'
        // overlay.style.left = `${start.left}px`;
        // overlay.style.top = `${start.top}px`;
        overlay.style.left = `${start.x + 8}px`
        overlay.style.top = `${start.y + 12}px`
        overlay.style.borderRadius = '6px'
        overlay.style.border = '1px solid rgba(0, 0, 0, 0.1)'
        // overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.05)'
        overlay.style.padding = '6px'
        document.body.appendChild(overlay)

        currentOverlay = overlay
    }
    const mouseMoveHandler = (event: MouseEvent) => {
        if (isDragging && currentOverlay) {
            // console.log("🚀 ~ mouseMoveHandler ~ event:", event);
            // 清除之前的颜色
            const prevHovered = document.querySelector('[data-hover]') as HTMLElement
            // console.log("🚀 ~ mouseMoveHandler ~ prevHovered:", prevHovered);
            if (prevHovered) {
                prevHovered.removeAttribute('data-hover')
                prevHovered.style.backgroundColor = ''
            }
            // delta = {
            //   x: event.clientX - start.x,
            //   y: event.clientY - start.y,
            // };
            delta = {
                x: event.clientX - start.x,
                y: event.clientY - start.y,
            }
            const { x: deltaX, y: deltaY } = delta
            currentOverlay.style.transform = `translate(${deltaX}px, ${deltaY}px)`

            /**
             * 检测
             */
            // 通过和 nodeAreas 进行比对,判断当前鼠标位置是否在某个区域内
            const hovered = nodeAreas.find(area => {
                const { left, top, width, height } = area
                return event.clientX >= left && event.clientX <= left + width && event.clientY >= top && event.clientY <= top + height
            })

            if (hovered) {
                insertPayload = {
                    nodeId: hovered.id,
                    parentId: hovered.containerId,
                    position: hovered.position,
                }
                createIndicator(hovered)
            } else {
                console.log('🚀 ~ mouseMoveHandler ~ insertPayload:', hovered)
                insertPayload = null
                indicator?.remove()
            }
        }
    }
    const mouseUpHandler = () => {
        if (!isDragging) {
            return
        }
        document.body.style.cursor = ''
        isDragging = false

        console.log('🚀 ~ mouseUpHandler ~ dragId:', dragId)

        console.log('🚀 ~ mouseUpHandler ~ insertPayload:', insertPayload)
        dragId = ''
        insertPayload = null

        nodeAreas = []

        currentOverlay?.remove()
        indicator?.remove()
        // 删除所有区域指示
        const areas = document.querySelectorAll('[data-area]')
        areas.forEach(area => {
            area.remove()
        })
        // 清除
        const prevHovered = document.querySelector('[data-hover]') as HTMLElement
        if (prevHovered) {
            prevHovered.removeAttribute('data-hover')
            prevHovered.style.backgroundColor = ''
        }
    }

    // nodes
    const nodes = document.querySelectorAll('[data-node]')
    // console.log("🚀 ~ nodes:", nodes);
    // 为每个节点添加拖拽事件
    nodes.forEach(node => {
        ;(node as HTMLDivElement).addEventListener('mousedown', mouseDownHandler, false)
    })
    // ref.current?.addEventListener("mousedown", mouseDownHandler, false);
    document.addEventListener('mousemove', mouseMoveHandler, false)
    document.addEventListener('mouseup', mouseUpHandler, false)

    return () => {
        nodes.forEach(node => {
            ;(node as HTMLDivElement).removeEventListener('mousedown', mouseDownHandler, false)
        })
        document.removeEventListener('mousemove', mouseMoveHandler, false)
        document.removeEventListener('mouseup', mouseUpHandler, false)
    }
}

Flex 布局引擎的拖拽功能通过以下步骤实现:

拖拽事件绑定与初始化

  • 为每个物料节点( data-node )绑定 mousedownmousemovemouseup 事件。
  • 在拖拽开始时,记录拖拽元素的初始位置及节点信息。

核心代码:

const mouseDownHandler = (event: MouseEvent) => {
    if (event.button !== 0) return; // 只允许左键拖拽
    const dom = event.target as HTMLElement;
    isDragging = true;
    dragId = dom.getAttribute('data-node') as string;
    const domRect = dom?.getBoundingClientRect();
    if (domRect) {
        start = {
            x: event.clientX,
            y: event.clientY,
            top: domRect.top,
            left: domRect.left,
        };
    }
    const overlay = dom.cloneNode(true) as HTMLDivElement;
    overlay.style.position = 'absolute';
    overlay.style.left = 
${start.x}px
;
    overlay.style.top = 
${start.y}px
;
    document.body.appendChild(overlay);
    currentOverlay = overlay;
};

拖拽过程中的节点检测

  • 实时更新拖拽的位置信息( deltaXdeltaY ),通过 transform 属性实现流畅的移动效果。
  • 根据鼠标位置与其他节点区域( nodeAreas )进行碰撞检测,判断是否进入某个可放置区域。

核心代码:

const mouseMoveHandler = (event: MouseEvent) => {
    if (!isDragging || !currentOverlay) return;
    delta = {
        x: event.clientX - start.x,
        y: event.clientY - start.y,
    };
    currentOverlay.style.transform = 
translate(${delta.x}px, ${delta.y}px)
;
    const hovered = nodeAreas.find(area => {
        const { left, top, width, height } = area;
        return (
            event.clientX >= left &&
            event.clientX <= left + width &&
            event.clientY >= top &&
            event.clientY <= top + height
        );
    });
    if (hovered) {
        insertPayload = {
            nodeId: hovered.id,
            parentId: hovered.containerId,
            position: hovered.position,
        };
        createIndicator(hovered);
    } else {
        insertPayload = null;
        indicator?.remove();
    }
};

拖拽完成时的更新

  • 根据 insertPayload 的位置数据更新布局树(或布局模型)。
  • 清除拖拽状态及相关样式。

核心代码:

const mouseUpHandler = () => {
    if (!isDragging) return;
    isDragging = false;
    if (insertPayload) {
        console.log('Inserted at:', insertPayload);
        // 更新布局数据
    }
    currentOverlay?.remove();
    indicator?.remove();
    nodeAreas = [];
    dragId = '';
};

Flex 布局引擎配置实现:引擎数据协议

Flex 布局的核心是布局模型和其协议,定义了容器与子节点的关系以及布局属性。

数据协议设计

Flex 布局的数据协议使用树形结构描述每个节点的布局属性,示例如下:

export type LayoutNode = {
    id: string;               // 节点唯一 ID
    type: string;             // 节点类型(e.g., container, block)
    direction?: 'row' | 'column'; // Flex 布局方向
    style?: {                 // 样式属性
        width?: string;
        height?: string;
        flex?: string;
        justifyContent?: string;
        alignItems?: string;
    };
    children?: LayoutNode[];  // 子节点
};
示例数据:
const layout: LayoutNode = {
    id: 'root',
    type: 'container',
    direction: 'row',
    style: {
        width: '100%',
        height: '100%',
    },
    children: [
        {
            id: 'child-1',
            type: 'block',
            style: {
                flex: '1',
            },
        },
        {
            id: 'child-2',
            type: 'block',
            style: {
                flex: '2',
            },
        },
    ],
};

配置实现

通过 flex 布局协议,提供配置化的布局编辑功能:

  1. 初始化布局

    • 通过协议描述生成 DOM 结构,并渲染到页面上。
  2. 实时更新

    • 在拖拽或调整过程中,动态更新布局数据并同步到 UI。
  3. 保存与加载

    • 支持将布局数据序列化为 JSON 存储,或从 JSON 数据中加载布局。

核心实现代码

  1. 布局渲染
const renderLayout = (node: LayoutNode, parent: HTMLElement) => {
    const element = document.createElement('div');
    element.setAttribute('data-node', node.id);
    element.style.display = 'flex';
    element.style.flexDirection = node.direction || 'row';
    Object.assign(element.style, node.style);
    parent.appendChild(element);
    if (node.children) {
        node.children.forEach(child => renderLayout(child, element));
    }
};
const root = document.getElementById('app');
renderLayout(layout, root);
  1. 布局更新
const updateLayout = (nodeId: string, newStyle: Partial<LayoutNode['style']>) => {
    const node = findNodeById(layout, nodeId); // 根据 ID 查找节点
    if (node) {
        Object.assign(node.style, newStyle);
        renderLayout(layout, document.getElementById('app')); // 重新渲染布局
    }
};

专家级 】作为 Leader,说说设计低代码平台物料体系与编排引擎的核心思路、方案与成果

低代码平台的 物料体系编排引擎 是平台的核心组成部分,其设计目标是支持灵活、高效的页面布局编排,提供良好的开发者体验和用户体验。

核心思路

  1. 物料体系设计

    • 物料以独立、模块化的方式存在,可动态加载与扩展。
    • 提供灵活的布局能力(如 flex 布局),支持不同的容器与子组件。
    • 使用标准化数据协议,支持物料的动态注册、拖拽、渲染及配置。
  2. 编排引擎设计

    • 基于拖拽的交互模型,实现所见即所得的页面设计。
    • 引入 flex 布局引擎,支持复杂布局的自动化排列。
    • 提供布局数据的实时更新与保存能力,便于回显与编辑。

方案设计

Flex 布局引擎配置实现

Flex 布局引擎的拖拽功能通过以下步骤实现:

拖拽事件绑定与初始化

  • 为每个物料节点( data-node )绑定 mousedownmousemovemouseup 事件。
  • 在拖拽开始时,记录拖拽元素的初始位置及节点信息。

核心代码:

const mouseDownHandler = (event: MouseEvent) => {
    if (event.button !== 0) return; // 只允许左键拖拽
    const dom = event.target as HTMLElement;
    isDragging = true;
    dragId = dom.getAttribute('data-node') as string;
    const domRect = dom?.getBoundingClientRect();
    if (domRect) {
        start = {
            x: event.clientX,
            y: event.clientY,
            top: domRect.top,
            left: domRect.left,
        };
    }
    const overlay = dom.cloneNode(true) as HTMLDivElement;
    overlay.style.position = 'absolute';
    overlay.style.left = 
${start.x}px
;
    overlay.style.top = 
${start.y}px
;
    document.body.appendChild(overlay);
    currentOverlay = overlay;
};

拖拽过程中的节点检测

  • 实时更新拖拽的位置信息( deltaXdeltaY ),通过 transform 属性实现流畅的移动效果。
  • 根据鼠标位置与其他节点区域( nodeAreas )进行碰撞检测,判断是否进入某个可放置区域。

核心代码:

const mouseMoveHandler = (event: MouseEvent) => {
    if (!isDragging || !currentOverlay) return;
    delta = {
        x: event.clientX - start.x,
        y: event.clientY - start.y,
    };
    currentOverlay.style.transform = 
translate(${delta.x}px, ${delta.y}px)
;
    const hovered = nodeAreas.find(area => {
        const { left, top, width, height } = area;
        return (
            event.clientX >= left &&
            event.clientX <= left + width &&
            event.clientY >= top &&
            event.clientY <= top + height
        );
    });
    if (hovered) {
        insertPayload = {
            nodeId: hovered.id,
            parentId: hovered.containerId,
            position: hovered.position,
        };
        createIndicator(hovered);
    } else {
        insertPayload = null;
        indicator?.remove();
    }
};

拖拽完成时的更新

  • 根据 insertPayload 的位置数据更新布局树(或布局模型)。
  • 清除拖拽状态及相关样式。

核心代码:

const mouseUpHandler = () => {
    if (!isDragging) return;
    isDragging = false;
    if (insertPayload) {
        console.log('Inserted at:', insertPayload);
        // 更新布局数据
    }
    currentOverlay?.remove();
    indicator?.remove();
    nodeAreas = [];
    dragId = '';
};

Flex 布局引擎配置实现:引擎数据协议

Flex 布局的核心是布局模型和其协议,定义了容器与子节点的关系以及布局属性。

数据协议设计

Flex 布局的数据协议使用树形结构描述每个节点的布局属性,示例如下:

export type LayoutNode = {
    id: string;               // 节点唯一 ID
    type: string;             // 节点类型(e.g., container, block)
    direction?: 'row' | 'column'; // Flex 布局方向
    style?: {                 // 样式属性
        width?: string;
        height?: string;
        flex?: string;
        justifyContent?: string;
        alignItems?: string;
    };
    children?: LayoutNode[];  // 子节点
};
示例数据:
const layout: LayoutNode = {
    id: 'root',
    type: 'container',
    direction: 'row',
    style: {
        width: '100%',
        height: '100%',
    },
    children: [
        {
            id: 'child-1',
            type: 'block',
            style: {
                flex: '1',
            },
        },
        {
            id: 'child-2',
            type: 'block',
            style: {
                flex: '2',
            },
        },
    ],
};

配置实现

通过 flex 布局协议,提供配置化的布局编辑功能:

  1. 初始化布局

    • 通过协议描述生成 DOM 结构,并渲染到页面上。
  2. 实时更新

    • 在拖拽或调整过程中,动态更新布局数据并同步到 UI。
  3. 保存与加载

    • 支持将布局数据序列化为 JSON 存储,或从 JSON 数据中加载布局。

核心实现代码

  1. 布局渲染
const renderLayout = (node: LayoutNode, parent: HTMLElement) => {
    const element = document.createElement('div');
    element.setAttribute('data-node', node.id);
    element.style.display = 'flex';
    element.style.flexDirection = node.direction || 'row';
    Object.assign(element.style, node.style);
    parent.appendChild(element);
    if (node.children) {
        node.children.forEach(child => renderLayout(child, element));
    }
};
const root = document.getElementById('app');
renderLayout(layout, root);
  1. 布局更新
const updateLayout = (nodeId: string, newStyle: Partial<LayoutNode['style']>) => {
    const node = findNodeById(layout, nodeId); // 根据 ID 查找节点
    if (node) {
        Object.assign(node.style, newStyle);
        renderLayout(layout, document.getElementById('app')); // 重新渲染布局
    }
};

成果总结

  1. 拖拽布局

    • 实现了基于 flex 的拖拽交互,支持子节点的动态插入与排列。
    • 提供实时区域指示器,提升用户操作体验。
  2. 灵活的布局协议

    • 定义了标准化的数据协议,支持复杂布局的描述与动态配置。
  3. 高扩展性

    • 支持任意新增物料组件,并通过统一协议参与布局编排。
  4. 实时更新与保存

    • 支持布局数据的动态更新和持久化存储,适用于低代码平台的页面搭建需求。

专家简历优化指南(目标 35K+ )

核心技能

  • 熟练掌握 HTML、CSS、JavaScript、Typescript 以及 OOP、FP、 AOP 等设计思想

  • 掌握样式体系构建与落地,对 css 预编译、css in js、module css 以及 utility-first CSS 有深入研究,并从零改良过样式体系以支持 SSR、SSG

  • 熟悉 React、Vue 相关技术栈,熟悉 React、Vue 及相关技术框架的实现原理

  • 掌握构建工具 Webpack、Vite 等,掌握编译工具 Babel,并深入理解其原理,并参与 Rspack 构建

  • 丰富的数据可视化经验,熟悉 Canvas、svg 开发范式,理解 Echarts、Antv 原理,能根据业务需求基于 d3、zrender 开发自定义渲染引擎

  • 丰富的跨端开发经验,熟练使用 Taro、Flutter、React-Native 开发跨端应用,对构建 hybird App 有丰富经验,深入理解跨端开发编译原理

  • 基于 Node.js 开发脚手架、打包构建优化工具及中间件服务

  • 掌握常用设计模式、算法与安全知识,追求开发高质量、高可维护性代码,追求极致产品体验

  • 团队管理经验,并在项目架构设计与性能优化方面具有丰富经验

  • 算法与编程技术

    • 精通各种算法题的分类及解决方法,包括排序与查找、数据结构、动态规划、贪心算法、回溯算法、分治算法、图论算法、数学算法等。
    • 重点掌握动态规划的基本概念、解题步骤和经典题目。
  • 3D 数字孪生平台开发经验

    • 熟练使用 WebGL 和 WebAssembly 技术,开发高效的 3D 渲染引擎。
    • 精通正射影像和倾斜摄影技术,具备 Tile 和模型(包括白膜和精模)的处理经验,能够使用 Blender 进行模型制作。
    • 熟悉材质、光效和粒子系统的实现与优化。
  • 全面性能优化能力

    • 具备打包构建优化经验,熟练使用 Webpack 进行模块打包,掌握 chunk、treeshaking、happypack、cache-loader 等优化技巧,并使用 Webpack Module Federation 进行模块联邦管理。
    • 精通资源优化,能够有效进行图片、字体压缩,管理请求队列,并通过 OSS 和 CDN 提升资源加载速度。
    • 具有应用性能优化经验,包括数据结构优化和应用模块更新。
    • 深入了解缓存机制,熟悉强缓存(Expiration、Cache-Control)、协商缓存(Etag)和策略缓存(Service-Worker)的配置与管理。

项目重难点

这个环节至关重要,很多同学不重视,简历随便写一写就开始投递了,结果投出去几百份可能一家公司面试都没有,结果就在怀疑前端行情出问题了

STAR 法则:

  • 遇到了什么问题 question,需求
  • 怎么评估解决方案,方案对比,方案落地 react 状态管理(redux、mobx、jotai、recoil)Vue3 -> Pinia
  • 具体方案落地
  • 结果反思,细节优化思考

反面案例:

技术栈:Java、Vue2、echarts、WEui、BaiduMap、JavaScript 、HTTP数据库:MySQL管理工具:SVN

责任描述:

1)产品前端研发负责人,主要负责整体样式沟通,样式调配实现;门户、管理平台、移动端、智端、可视化等前端内容实现;

2)实现组织管理、人员管理、党员关系转接、待办通知、绩效考核(复杂功能算法实现)、发展党员(25个流程)、可视化等主体功能,兼容性优化、适配1920*1080屏幕以及响应式布局实现;

3)相关功能开发,包含前后端、数据库;

4)门户框架搭建、门户整体设计、后端接口、门户前端 UI 实现等;

5)微信小程序框架搭建、小程序页面设计及开发、知识图谱技术预演;

6 )项目经理工作辅助,包含需求沟通、UI设计沟通、交付材料项目经历整理、前端代码质量管理、部分功能设计。

项目经历深度优化

工作内容和成果

  • 架构设计 】参与智慧管理平台整体架构设计、技术选型与方案评审,担任全栈开发,完成相关核心模块
  • 企微开发 】对接企业微信生态,基于企微 SDK 完成平台支付、消息推送、机器人等功能开发
  • 可视化 】主导完成平台可视化渲染引擎(可视化图表的组件,数据协议)设计与开发,基于 echarts (svgRenderer、canvasRenderer 一千万行数据的表格渲染【不能使用 虚拟滚动 】 canvas table,chunk)封装业务图表库,服务于平台可视化场景
  • 地图开发 】使用百度地图 SDK,封装业务地图渲染器(MapRenderer),包含:地图撒点、地区数据下钻等功能
  • 小程序与App 】基于 uniapp 实现智慧党建用户端多端开发落地,产物编译为 H5、微信小程序两端应用
  • 团队基建 】推进团队业务组件库、图表库与基础库沉淀,完成 10+ 个业务组件沉淀,以此提升了团队协同开发效率
  • 优化 】设计产品响应式系统,基于 media query 设计响应式端点规则,适配不同端应用的展示
  • 自研 OA 打通 】...

以 STAR 法则梳理

【技术栈】

  • Java、Vue2、ECharts、WEui、BaiduMap、JavaScript、HTTP
  • 数据库 :MySQL
  • 管理工具 :SVN

【产品前端研发负责人】

  • 情境 (Situation) :担任产品前端研发负责人,负责门户、管理平台、移动端、智端、可视化等前端内容的实现。
  • 任务 (Task) :主要任务是与设计团队沟通,调配和实现整体样式,确保产品界面的一致性和用户体验。
  • 行动 (Action) :我协调设计与开发团队,定期召开样式沟通会,亲自进行样式的调配与实现,并负责不同平台和设备的前端内容开发。
  • 结果 (Result) :成功实现了多个平台的前端开发工作,提升了产品的用户体验和一致性,获得了团队和用户的高度评价。

【实现复杂功能及优化】

  • 情境 (Situation) :项目需要实现复杂功能算法和大规模功能模块,包括组织管理、人员管理、党员关系转接、待办通知、绩效考核、发展党员(25个流程)和可视化功能。
  • 任务 (Task) :负责上述复杂功能的实现,并优化其兼容性和响应式布局。
  • 行动 (Action) :通过设计和实现复杂算法,确保各模块的功能性;进行兼容性优化,使系统适配1920*1080屏幕和响应式布局。
  • 结果 (Result) :成功实现并优化了所有复杂功能,系统在不同设备和分辨率下均表现良好,提高了用户操作的流畅度和满意度。

【全面功能开发】

  • 情境 (Situation) :需要进行前后端和数据库的全面开发,确保系统各功能模块的无缝集成。
  • 任务 (Task) :开发和实现相关功能,包括前端UI、后端接口和数据库交互。
  • 行动 (Action) :采用Java、Vue2等技术,开发并调试各功能模块,与后端团队密切合作,确保接口的准确性和数据的一致性。
  • 结果 (Result) :成功完成了所有功能模块的开发和集成,系统运行稳定,性能优异,受到了客户的好评。

【微信小程序开发与知识图谱预演】

  • 情境 (Situation) :项目需要开发微信小程序,并进行知识图谱技术的预演。
  • 任务 (Task) :负责小程序框架的搭建、页面设计及开发,同时进行知识图谱的技术预演。
  • 行动 (Action) :使用WEui、JavaScript等技术,设计并开发小程序页面,进行知识图谱的技术预演和验证。
  • 结果 (Result) :成功搭建了微信小程序框架,完成了页面设计和开发工作,知识图谱技术预演顺利,通过了技术验证。

【项目经理工作辅助】

  • 情境 (Situation) :在项目中辅助项目经理,确保项目需求沟通顺畅,UI设计协调到位,交付材料齐全,前端代码质量高。
  • 任务 (Task) :辅助项目经理进行需求沟通、UI设计沟通、交付材料整理、前端代码质量管理以及部分功能设计。
  • 行动 (Action) :积极参与需求和UI设计的沟通,整理和管理项目交付材料,进行代码审查和质量管理,并参与功能设计。
  • 结果 (Result) :成功辅助项目经理完成了项目的各项工作,提高了项目的开发效率和交付质量,确保了项目的顺利进行。

高级项目实战提升简历看点

你可能不具备这些项目的实战经验,很多同学写了很多年管理系统,简单增删改查项目,如果不跳出这个圈子,很难在薪资上有非常大的突破!

  • 大厂 UI 组件库(Vue3)整体设计与开发实践(monorepo 架构)

  • 大厂业务 Hooks 库(React 18)整体设计与开发实践(从零到一的架构、规范流程)

  • 企业级脚手架工具开发实践

  • 企业级文档编辑器飞书文档开发实践

  • 前端性能、异常与行为监控

  • 3D 可视化数字孪生低代码实战 💥

    • 基于 cesium(arcGis、超图) 方案的 WebGIS 开发实践
    • 基于 openlayer、mapbox 开发
    • 基于 WebGL 3D 可视化开发实践

冲刺年包 50W+ 薪资长线规划

冲刺核心要素

  1. 全面的技术储备

    1. 框架基础

      • Vue 和 React 经验:包括 Vue3 + Typescript 和 React18(Hooks、Concurrent)
      • 掌握框架原理:React 生态库(React-Router、Redux)和 Vue 生态库原理
    2. 工程化能力

      • 构建工具:Webpack、Vite、Rspack、ESBuild、swc
      • CI/CD 自动化:自动化构建和自动化部署
    3. 基建能力

      • Node.js、命令行工具开发(Cli)
      • UI 库、图表库、工具库开发
    4. 业务领域经验

      • 管理系统和图表类应用
      • 可视化、编辑器、云表格、低代码平台、SaaS 产品、数字孪生、三维可视化
  2. 项目经验

    • 参与过至少两个大型项目,并主导过一个复杂项目
    1. 管理系统:包括项目搭建、技术方案选择、技术栈构建、CI/CD 流程
    2. 其他领域项目:如可视化、编辑器、云表格、低代码平台、SaaS 产品、数字孪生、三维可视化
  3. 面试表现

    1. 个人介绍

      • 准备个人介绍草稿,涵盖基本信息、技术栈和项目重难点
    2. STAR 法则

      • 问题描述:阐述遇到的问题或需求
      • 解决方案评估:方案对比与选择(如 React 状态管理:redux、mobx、jotai、recoil,Vue3 使用 Pinia)
      • 方案实施:具体的实施步骤
      • 反思与优化:项目反思及优化建议
    3. 面试准备

      • 重点复习知识点:如 v8 内存管理、Promise A+ 规范、事件循环、this、面向对象编程原型
      • 技术储备:结合项目经验展示技术在项目中的应用
  4. 学历提升

    1. 现有学历:大专
    2. 未来计划:尽快取得本科证书(不需要注明具体年限)
    3. 学历背景:民办学校
    4. 内推建议:应对学历和工作经历问题,通过内推提升机会

自身短板与补益

  • 项目简单,管理后台一做就是大半年,天天 CRUD

    • 看开源项目(react-hook-form ts 类型、hook 处理、状态管理、架构 Provider,keyPath)
    • 找一些不错的项目练手
    • 拿好的项目,学习完放在简历里, 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
    • 1.自研:15K, 2.外包:20K ,这个火坑, 灰(供需决定)
  • 技术栈掌握不深不广,只会用 Vue2 (Vue3 + Typescript),React18(React stack reconciler)

  • 架构、方案设计没碰过

    • React,create-react-app、umi,没有真正从零到一去设计初始化过一个项目
    • Vue,Vue CLI,Vite/Webpack。Vue2 CLI 创出来项目 1. webpack、2.vite
  • 没有专精的技能或业务

    • 自驱 (假定自己是 Leader),项目的赢利点、商业价值【 可视化、编辑器、白板、团队基建、AI产品
    • 与生俱来有些东西,好奇心、自驱力、清晰规划
    • 我:管理平台,HPE(官网、后台管理),云表格(维格表、飞书云表格)、云编辑器(CKEditor 老【html string】)(语雀、【石墨文档】)

妙码学院——全程陪跑、督学、真·企业级全栈项目、内推

⚠️ 暂不支持的文档区域,【文档小组件】

  • 跨端开发 Taro(Taro 编译器 compiler、运行时 runtime)、uniapp
  • 协同编辑器(文档类、画板类)
  • 团队基建工程(UI 库、图表库、Cli -> 产生产物 npm 包)
  • 3D 可视化数字孪生 bigdata
  • 低代码平台

课程体系 2.0 升级,除了基础知识夯实,融入了更多项目实战内容,包含:

  • 企业级脚手架工具开发实践

  • 企业级文档编辑器飞书文档开发实践

  • 大厂 UI 组件库(Vue3)整体设计与开发实践

  • 大厂业务 Hooks 库(React 18)整体设计与开发实践

  • 埋点与数据监控平台实战

  • 3D 可视化数字孪生实战 💥

    • 基于 cesium 方案的 WebGIS 开发实践
    • 基于 WebGL 3D 可视化开发实践

妙码学院全网独家项目实战矩阵

所有项目实战,均完全 从零到一手写纯原创 ,项目架构与编码规范真一线大厂级。

  • 微前端在分拆原子应用场景下的落地与实践

  • 类飞书文档协同编辑器从零到一架构实现

  • 推动团队基建落地

    • React UI 库
    • Vue Composition API 库
    • 企业级脚手架
  • 数字孪生平台整体架构设计

  • 企业级无代码可视化平台实践(Vue3)

  • 低代码平台设计与实现

    • 编排引擎
    • 流程引擎
    • 编辑器
    • 代码执行器与 JavaScript 沙箱
  • 用户行为分析 SDK 及监控可视化平台架构设计与实现

  • 可视化渲染引擎设计与实现

  • 基于 RAG / Agent 前端 AI 应用流程编排平台

前端阶段性能力与冲刺目标

以下是对您提供的内容进行权威和专业化改写的建议:

1~3 年

在此阶段,重点在于评估个人的基础知识和热情。对前端基础、计算机原理、网络通信和算法等领域的要求较高。由于在此阶段难以评估业务深度,因此更多关注基础知识的掌握程度。

  • 关键在于通过学术教育或网络资源加强基础知识;
  • 在简历中以多种方式展示对前端的热情,展现个人潜力;
  • 积极探索前沿技术,关注国内外技术动态;
  • 尝试开发小型项目或参与社区开源项目;
  • 建立技术博客,以输出促进知识吸收。

3~5 年

此阶段通常是向成为独立工程师发展的关键时期,避免重复使用有限的经验。

  • 关注社区中关于进阶的资料和路线,强化基础知识;

  • 深入掌握常用框架的高级用法,探索其原理;

  • 在业务开发中不仅完成功能,还需考虑项目结构设计、封装基础工具、设计和开发基础组件;

  • 思考提高团队效率的方法,例如:

    • 集成代码检验和风格统一插件(如 eslint、stylelint、prettier、spellcheck);
    • 从工程化角度提高本地开发效率,优化webpack构建,探索esbuild、vite等工具;
    • 对于多项目开发,整理差异和统一部分,建立内部脚手架以减少重复工作;
    • 尝试搭建CI/CD平台,维护公司内部的通用npm包;
    • 培养软技能,如沟通协作,协调各角色共同推进目标。

5年+

进入此阶段,可能朝技术专家或管理方向发展。期望您能够独立负责高复杂度项目,突破关键技术难题。

  • 负责技术调研,关注行业趋势,选择最优技术方案,具备决策能力;
  • 拥有丰富的技术经验和技术储备,能够解决遇到的困难,并有自己的方法论;
  • 协助或主导业务目标制定,合理推动项目达成预期效果;
  • 是否具有团队领导经验,能够协调跨团队项目,处理团队成员情绪问题,解决技能分布不平衡等问题;
  • 打造技术氛围,促进团队共同成长。

近期进阶公开课合辑

过往分享了很多进阶知识与架构内容,课程文档列表如下,配套对应 课程文档和配套视频回放找咨询老师 领取~ 希望对你的技术成长有帮助!

【飞书文档】企业级低代码平台核心需求与方案设计,字节前端专家带你精研产品业务与工程架构 低代码业务核心必看


【飞书文档】vite、rollup、tsup、tsc 打包构建工具详解,字节前端专家带你深入多业务构建方案

【飞书文档】基于 pnpm monorepo 大厂项目工程化设计,字节架构师传授多场景项目架构要诀

【飞书文档】前端单测、集成测试与端到端测试方案全面解析,字节大佬分享字节系产品分场景测试最佳实践

【飞书文档】css、cssinjs、tailwindcss 核心用法与进阶,字节系产品样式方案评审与最佳实践

【飞书文档】Typescript 进阶与高分技巧,字节面试官细数常问面试题与优秀开源项目最佳实践

【飞书文档】Docker 入门与服务编排进阶,字节前端专家带你光速掌握 CI/CD 运维技能


【飞书文档】ESLint 前端编码规范化与原理剖析,特邀字节大佬分享团队代码质量把控细节

【飞书文档】Notion 与飞书文档协同方案精析,字节前端专家传授百万年薪架构师级项目重难点 飞书文档编辑器原理续,进阶

【飞书文档】Ant Design 组件库架构设计与开发实践,高级前端专家带你掌握基建面试技巧 组件库与团队基建面试必看

【飞书文档】Taro、Tauri 多端开发实践与原理剖析,《Taro 多端开发权威指南》作者带你悟透多端框架原理 多端开发涨薪必学


【飞书文档】Nest 服务端开发与原理深度剖析,《NestJS 实战》作者带你领略框架设计之美 全栈进阶,企业级框架

【飞书文档】Babel 与编译原理详解,字节高级前端专家带你从零实现飞书表格公式执行器

【飞书文档】服务端渲染(SSR)与前后端同构技术原理揭秘,字节前端专家带你光速进阶全栈 进阶必学


【飞书文档】大数据可视化引擎与数字孪生平台设计浅析,字节架构师:一起来剖析 DataWind 数据洞察平台架构之道

【飞书文档】飞书文档协同编辑器技术揭秘,特邀字节架构师分享富文本编辑器方案细节

【飞书文档】前端性能与异常监控平台全链路设计与实践,字节架构师:掌握这整套拿个 40K+ 不在话下吧

【飞书文档】字节面试专场——中厂在职学员冲击大厂 30K+,看看面试官如何评价 大厂模拟面试,问得很深慎看

【飞书文档】冲击中大厂筹备与涨薪突击最优方案,特邀字节面试官带你体验大厂面试全流程


【飞书文档】Webpack 原理深度解读与面试专项突击,字节面试官带你手撕难缠打包构建面试原理题 工程化与构建原理深入

【飞书文档】脚手架/CLI 工具原理与开发实践,特邀字节前端专家带你体悟大厂团队基建与研发工作流 团队基建必看

【飞书文档】Vite 构建过程与源码深度剖析,你怎么也想不到一线大厂工程化构建面试会问这么深!

【飞书文档】Vue3 源码深度剖析,字节面试官教你轻松拿捏高级前端专家面试框架原理题

【飞书文档】React18 源码深度剖析,字节面试官教你轻松拿捏高级前端专家面试框架原理题

【飞书文档】前端破局 AI 应用开发,特邀字节大佬分享字节系 AI 场景落地应用与 AI 引擎编排流程 探索前端新方向同学福音


【飞书文档】高级前端专家如何做性能优化?特邀字节大佬细数飞书应用优化细节(二)【内部培训版】

【飞书文档】小小微前端,轻松拿捏,特邀字节大佬开讲微前端架构与源码剖析【内部培训版】 35K+ 同学必看

【飞书文档】高级前端专家如何做项目架构与工程化设计? 特邀字节大佬细数字节开源项目架构细节【超详细内培版】

【飞书文档】高级前端专家如何做性能优化?特邀字节大佬细数飞书应用优化细节(一)【超详细内培版】


【飞书文档】面试被算法干吐了?字节大佬带你突破极限,冲击 30K+ 必掌握算法与 WebAssembly 技术 冲刺年包 50W+ 同学必看

【飞书文档】字节大佬带你弯道超车,深入剖析大厂面试真题~

【飞书文档】项目没有难点亮点?字节大佬带你前端项目弯道超车

【飞书文档】备战金九银十,进阶大前端,涨薪全突破! 跳槽涨薪需求同学必看

【未知组件reminder】