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

cli-notes.zip

很多同学可能第一次来,我分享了很多干货公开课,希望对你的技术成长有帮助!免费分享都在这里,需要 文档和配套视频找咨询老师 领取~

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

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

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

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


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

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

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

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


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

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

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

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

  • 初中级 】面试官:了解过脚手架/命令行工具开发吗,简要说明开发要点
  • 中高级 】面试官:说说你们团队的 团队基建 ,开发脚手架的目的与方案
  • 专家级 】面试官:作为 Leader,详述脚手架开发方案、技术细节与命令设计

初中级 】面试官:了解过脚手架/命令行工具开发吗,简要说明开发要点

Node 应用开发步骤详解

开发 Node 应用与 React、Vue 略有区别,React、Vue 应用开发我们更关注 UI 表现,而 Node 应用开发我们更关注的是整体业务流程,比如我们的目的是通过命令行工具简化开发,那么命令行工具的设计思路便是来源于日常开发工作,命令行工具开发的目的便是解决实际开发过程中的问题的。

创建项目

首先,使用 npm 初始化一个新的 Node.js 项目:

mkdir miaoma-cli
cd miaoma-cli
npm init -y

这将创建一个基本的 package.json 文件。

指定依赖

接下来,我们需要安装一些依赖。通常,开发脚手架工具需要一些实用的 npm 包:

  "devDependencies": {
    "commander": "12.1.0",
    "picocolors": "1.0.1",
    "prompts": "2.4.2",
    "table": "6.8.2",
    "handlebars": "4.7.8"
  }

定义 scripts

package.json 中,我们可以定义一些脚本来简化常用的命令。例如:

{
  "name": "@miaoma/cli",
  "version": "1.0.0",
  "description": "A simple CLI tool",
  "main": "index.js",
  "bin": {
    "miao": "./index.js"
  },
  "scripts": {
    "start": "node index.js"
  },
  "devDependencies": {
    "commander": "12.1.0",
    "picocolors": "1.0.1",
    "prompts": "2.4.2",
    "table": "6.8.2",
    "handlebars": "4.7.8"
  }
}

在这里, bin 字段定义了全局命令 miao ,它将执行 index.js 文件。

  • main
  • module
  • types
  • bin
  • files

执行脚本

创建一个简单的 index.js 文件来演示脚手架的基本功能:

#!/usr/bin/env node

const { program } = require('commander');
const pc = require('picocolors');
const prompts = require('prompts');
const { table } = require('table');
const Handlebars = require('handlebars');

// Commander program setup
program
  .version('1.0.0')
  .description('A simple CLI tool');

// Greet command using prompts
program
  .command('greet')
  .description('Greet the user')
  .action(async () => {
    const response = await prompts({
      type: 'text',
      name: 'name',
      message: 'What is your name?',
    });
    console.log(pc.green(`Hello, ${response.name}!`));
  });

// Table command using console-table-printer
program
  .command('table')
  .description('Print a table')
  .action(() => {
      const data = [['0A', '0B', '0C'],['1A', '1B', '1C'],['2A', '2B', '2C']];
      console.log(table(data));
  });

// Template command using Handlebars
program
  .command('template')
  .description('Render a template')
  .action(() => {
    const template = Handlebars.compile('Hello, {{name}}!');
    const result = template({ name: 'World' });
    console.log(result);
  });

program.parse(process.argv);

确保文件具有可执行权限:

chmod +x index.js

开发脚手架的核心依赖说明

commander

用于命令行参数解析的 commander 是一个功能强大的库,支持命令和选项的定义。

const { program } = require('commander');

// 设置版本和描述
program
  .version('1.0.0')
  .description('A simple CLI tool');

// 定义一个选项
program
  .option('-n, --name <type>', 'specify name');

// 处理命令行输入
program.parse(process.argv);

if (program.name) {
  console.log(`Hello, ${program.name}`);
}

commander API 使用与原理

  • program.version(version, [flags], [description]) : 设置CLI的版本信息。
  • program.description(description) : 设置CLI的描述信息。
  • program.option(flags, description, [defaultValue]) : 定义选项, flags 包含短选项和长选项。
  • program.command(name, [description]) : 定义子命令。
  • program.parse(argv) : 解析命令行参数,通常是 process.argv

picocolors

用于处理命令行颜色高亮的 picocolors 是一个轻量级的库。

const pc = require('picocolors');
console.log(pc.green('Success!'));
console.log(pc.red('Error!'));
console.log(pc.blue('Information!'));

prompts

用于交互式提问的 prompts ,可以根据用户输入动态生成问题。

const prompts = require('prompts');
(async () => {
  const response = await prompts({
    type: 'text',
    name: 'username',
    message: 'What is your name?'
  });
  console.log(`Hello, ${response.username}`);
})();

复杂场景的使用

const prompts = require('prompts');
prompts.override(require('yargs').argv);

(async () => {
  const response = await prompts([
    {
      type: 'text',
      name: 'twitter',
      message: `What's your twitter handle?`
    },
    {
      type: 'multiselect',
      name: 'color',
      message: 'Pick colors',
      choices: [
        { title: 'Red', value: '#ff0000' },
        { title: 'Green', value: '#00ff00' },
        { title: 'Blue', value: '#0000ff' }
      ],
    }
  ]);

  console.log(response);
})();

常用 API

  • type : 问题类型,如 textselectmultiselect 等。
  • name : 用于存储答案的字段名。
  • message : 提示消息。
  • choices : 多选题目时的选项数组。

table

用于展示表格内容的 table 可以帮助我们在命令行中美观地打印表格。

const { table } = require('table');

const data = [
    ['0A', '0B', '0C'],
    ['1A', '1B', '1C'],
    ['2A', '2B', '2C']
];

console.log(table(data));

常用 API

table

返回表格格式的字符串。

参数:

  • data : 要显示的数据 (类型: any[][] , 必填)
  • config : 表格配置 (类型: object , 可选)

示例:

const data = [
  ['0A', '0B', '0C'],
  ['1A', '1B', '1C'],
  ['2A', '2B', '2C']
];

const config = {
  border: {
    topBody: `─`,
    topJoin: `┬`,
    topLeft: `┌`,
    topRight: `┐`,
    bottomBody: `─`,
    bottomJoin: `┴`,
    bottomLeft: `└`,
    bottomRight: `┘`,
    bodyLeft: `│`,
    bodyRight: `│`,
    bodyJoin: `│`,
    joinBody: `─`,
    joinLeft: `├`,
    joinRight: `┤`,
    joinJoin: `┼`
  }
};

console.log(table(data, config));

输出:

┌────┬────┬────┐
│ 0A │ 0B │ 0C │
├────┼────┼────┤
│ 1A │ 1B │ 1C │
├────┼────┼────┤
│ 2A │ 2B │ 2C │
└────┴────┴────┘
config.drawVerticalLine

决定是否绘制垂直线。

类型: (lineIndex: number, columnCount: number) => boolean \

默认: () => true

const config = {
  drawVerticalLine: (lineIndex, columnCount) => {
    return lineIndex === 0 || lineIndex === columnCount;
  }
};

console.log(table(data, config));

输出:

╔════════════╗
║ 0A  0B  0C ║
╟────────────╢
║ 1A  1B  1C ║
╟────────────╢
║ 2A  2B  2C ║
╟────────────╢
║ 3A  3B  3C ║
╟────────────╢
║ 4A  4B  4C ║
╚════════════╝
config.drawHorizontalLine

决定是否绘制水平线。

类型: (lineIndex: number, rowCount: number) => boolean \

默认: () => true

const config = {
  drawHorizontalLine: (lineIndex, rowCount) => {
    return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount - 1 || lineIndex === rowCount;
  }
};

console.log(table(data, config));

输出:

╔════╤════╤════╗
║ 0A │ 0B │ 0C ║
╟────┼────┼────╢
║ 1A │ 1B │ 1C ║
║ 2A │ 2B │ 2C ║
║ 3A │ 3B │ 3C ║
╟────┼────┼────╢
║ 4A │ 4B │ 4C ║
╚════╧════╧════╝
config.singleLine

设置为 true 时,不绘制表格内的水平线。

类型: boolean \

默认: false

const config = {
  singleLine: true
};

console.log(table(data, config));

输出:

╔═════════════╤═════╤══════════╤═══════╤════════╤══════════════╤═══════════════════╗
║ -rw-r--r--  │ 1   │ pandorym │ staff │ 1529   │ May 23 11:25 │ LICENSE           ║
║ -rw-r--r--  │ 1   │ pandorym │ staff │ 16327  │ May 23 11:58 │ README.md         ║
║ drwxr-xr-x  │ 76  │ pandorym │ staff │ 2432   │ May 23 12:02 │ dist              ║
║ drwxr-xr-x  │ 634 │ pandorym │ staff │ 20288  │ May 23 11:54 │ node_modules      ║
║ -rw-r--r--  │ 1,  │ pandorym │ staff │ 525688 │ May 23 11:52 │ package-lock.json ║
║ -rw-r--r--@ │ 1   │ pandorym │ staff │ 2440   │ May 23 11:25 │ package.json      ║
║ drwxr-xr-x  │ 27  │ pandorym │ staff │ 864    │ May 23 11:25 │ src               ║
║ drwxr-xr-x  │ 20  │ pandorym │ staff │ 640    │ May 23 11:25 │ test              ║
╚═════════════╧═════╧══════════╧═══════╧════════╧══════════════╧═══════════════════╝
config.columns

列特定配置。

示例: 设置列宽度

const config = {
  columns: {
    1: { width: 10 }
  }
};

console.log(table(data, config));

输出:

╔════╤════════════╤════╗
║ 0A │ 0B         │ 0C ║
╟────┼────────────┼────╢
║ 1A │ 1B         │ 1C ║
╟────┼────────────┼────╢
║ 2A │ 2B         │ 2C ║
╚════╧════════════╧════╝

示例: 设置列对齐方式

const config = {
  columnDefault: {
    width: 10,
  },
  columns: [
    { alignment: 'left' },
    { alignment: 'center' },
    { alignment: 'right' },
    { alignment: 'justify' }
  ],
};

console.log(table(data, config));

输出:

╔════════════╤════════════╤════════════╤════════════╗
║ 0A         │     0B     │         0C │ 0D  0E  0F ║
╟────────────┼────────────┼────────────┼────────────╢
║ 1A         │     1B     │         1C │ 1D  1E  1F ║
╟────────────┼────────────┼────────────┼────────────╢
║ 2A         │     2B     │         2C │ 2D  2E  2F ║
╚════════════╧════════════╧════════════╧════════════╝

示例: 设置列内容截断

const config = {
  columns: [
    {
      width: 20,
      truncate: 100
    }
  ]
};

console.log(table(data, config));

输出:

╔══════════════════════╗
║ Lorem ipsum dolor si ║
║ t amet, consectetur  ║
║ adipiscing elit. Pha ║
║ sellus pulvinar nibh ║
║ sed mauris convall…  ║
╚══════════════════════╝
createStream

使用 createStream 函数创建并追加行的表格。

参数:

  • config:table 相同,但必须提供 config.columnDefault.widthconfig.columnCount

示例:

import { createStream } from 'table';

const config = {
  columnDefault: {
    width: 50
  },
  columnCount: 1
};

const stream = createStream(config);

setInterval(() => {
  stream.write([new Date()]);
}, 500);
getBorderCharacters

加载预定义的边框模板。

参数:

-

template (类型: 'honeywell' | 'norc' | 'ramac' | 'void' , 必填)

示例:

import { table, getBorderCharacters } from 'table';

const config = {
  border: getBorderCharacters(`honeywell`)
};

console.log(table(data, config));

输出:

╔════╤════╤════╗
║ 0A │ 0B │ 0C ║
╟────┼────┼────╢
║ 1A │ 1B │ 1C ║
╟────┼────┼────╢
║ 2A │ 2B │ 2C ║
╚════╧════╧════╝

handlebars

用于模板处理的 handlebars 可以生成动态内容。

const Handlebars = require('handlebars');
const template = Handlebars.compile('Hello, {{name}}!');
const result = template({ name: 'World' });
console.log(result);

常用 API

  • compile(template) : 编译模板字符串。
  • 编译后的模板函数可以接受一个对象作为参数,并返回生成的字符串。

通过这些步骤,我们可以构建一个功能丰富的命令行工具,并利用上述库实现参数解析、颜色高亮、交互提问、表格展示和模板处理等功能。

中高级 】面试官:说说你们团队的团队基建,开发脚手架的目的与方案

好的,以下是一个更详实的回答,包括技术点和项目模板的定义与使用:

团队基建的定义

团队基建(Team Infrastructure)是指团队在软件开发过程中所依赖的一系列工具、系统和流程。这些基建能够提高开发效率、确保代码质量并促进团队协作。

团队基建的目的

  • 提高开发效率 :通过自动化工具和脚手架,减少重复性劳动,使开发人员能够更专注于业务逻辑和功能实现。
  • 确保代码质量 :通过代码规范检查、自动化测试等手段,确保代码的一致性和可靠性。
  • 促进团队协作 :提供统一的开发环境和工具,确保团队成员在相同的基础上工作,减少环境差异带来的问题。
  • 简化维护和升级 :通过标准化的工具和流程,使得代码库的维护和升级变得更加容易。

开发脚手架的目的

  • 快速搭建项目结构 :提供标准化的项目结构和配置,减少初始设置的时间。
  • 统一开发规范 :通过预配置的代码规范检查工具(如 ESLint、Prettier 等),确保团队成员遵循相同的编码标准。
  • 集成常用功能 :预先集成常用的功能模块(如用户认证、日志记录等),使得开发人员可以快速上手,减少重复造轮子的时间。
  • 自动化流程 :集成 CI/CD 管道、自动化测试、代码部署等流程,确保代码在每次提交后都能自动进行测试和部署。

开发脚手架的方案

需求分析

  • 确定需求 :与团队成员沟通,确定开发过程中常见的需求和痛点。
  • 功能列表 :列出脚手架需要实现的功能,如项目初始化、代码规范检查、自动化测试等。

技术选型

  • 工具选择 :选择适合的工具和技术栈,如 Yeoman、Plop 等脚手架生成工具。
  • 框架和库 :选择合适的前后端框架和库,如 React、Vue、Express 等。

脚手架实现

  • 项目模板 :创建标准化的项目模板,包括文件结构、配置文件等。

    • 项目模板可以包括以下内容:

      • 基本文件结构 :如 src、test、config 等目录。
      • 配置文件 :如 package.json、webpack.config.js 等。
      • 示例代码 :如示例组件、服务、路由等。
  • 脚本编写 :编写脚本实现项目初始化、依赖安装、代码生成等功能。

    • 使用 commander (版本 12.1.0)作为命令行接口框架。
    • 使用 picocolors (版本 1.0.1)处理命令行输出的颜色。
    • 使用 prompts (版本 2.4.2)进行交互式命令行提示。
    • 使用 table (版本 6.8.2)格式化输出表格数据。
    • 使用 handlebars (版本 4.7.8)进行模板渲染。

测试和验证

  • 功能测试 :对脚手架的各项功能进行测试,确保其正确性和稳定性。
  • 用户反馈 :邀请团队成员使用脚手架,收集反馈意见进行改进。

文档和培训

  • 使用文档 :编写详细的使用文档,指导团队成员如何使用脚手架。
  • 培训和支持 :为团队成员提供培训和技术支持,确保他们能够熟练使用脚手架。

命令设计

我们的脚手架工具设计了多个命令,类似于 vue-create,以便用户灵活使用:

  1. 项目初始化
miao create <project-name> [options]
  1. 示例:
miao create my-project --template react
  1. 该命令用于创建新项目,可以选择模板(如 React、Vue、Express 等)。

  2. 添加模块

miao add <module-name>
  1. 示例:
miao add auth
  1. 该命令用于向现有项目中添加常用模块,如用户认证、日志记录等。

  2. 生成代码

miao generate <type> <name>
  1. 示例:
miao generate component Header
  1. 该命令用于生成不同类型的代码文件,如组件、服务、路由等。

  2. 启动开发服务器

miao serve
  1. 示例:
miao serve --port 3000
  1. 该命令用于启动本地开发服务器,支持自定义端口配置。

  2. 运行测试

miao test
  1. 示例:
miao test --watch
  1. 该命令用于运行项目的自动化测试,支持监视模式。

  2. 构建项目

miao build
  1. 示例:
miao build --mode production
  1. 该命令用于构建项目,支持不同环境的配置,如生产环境和开发环境。

  2. 部署项目

miao deploy
  1. 示例:
miao deploy --target staging
  1. 该命令用于将项目部署到指定环境,如测试环境、生产环境等。

这些命令通过 commander 实现,并且结合 prompts 进行交互式提示,帮助用户快速配置项目。输出信息使用 picocolors 增加可读性,表格数据通过 table 格式化展示,模板渲染由 handlebars 完成。

示例回答

“我们团队的团队基建主要包括代码规范检查、自动化测试和持续集成。开发脚手架的主要目的是提高开发效率和代码质量。用到了 commander 作为命令行接口框架,picocolors 处理命令行输出的颜色,prompts 进行交互式命令行提示,table 格式化输出表格数据,以及 handlebars 进行模板渲染。

我们定义了标准化项目模板,包括基本文件结构、配置文件和示例代码,并编写了脚本实现项目初始化、依赖安装和代码生成功能。

通过使用这个脚手架,我们显著减少了项目初始化的时间,统一了代码规范,并且保证了每次代码提交后的质量和稳定性。团队成员可以通过 miao create 命令快速生成标准化的项目结构,并选择所需的模板和配置。通过 miao add auth ,可以轻松添加用户认证模块,而无需重复编写代码。 miao generate component Header 则可以快速生成符合团队规范的组件代码。

我们还编写了详细的使用文档,并进行了团队培训,确保每个成员都能熟练使用这个工具。

专家级 】面试官:作为 Leader,详述脚手架开发方案、技术细节与命令设计

脚手架开发方案

  1. 需求分析

    • 首先需要支持前端不同模板(如 react-ts、vue-ts 等)
    • 提供本地和远程模板拉取的功能
  2. 技术选型

    • 选择合适的编程语言和工具库(如Node.js的Commander、Prompts、Picocolors、Handlebars等)
    • 选择模板引擎(如Handlebars)用于生成代码模板
  3. 项目结构设计

    • 使用monorepo架构,并使用 pnpm workspace 进行管理

技术细节

  1. 项目初始化

    • 创建一个pnpm项目,安装必要的依赖:
    mkdir miaoma-cli
    cd miaoma-cli
    pnpm init
    
  2. 目录结构

    • 示例项目结构:
    miaoma-cli/
    ├── packages/
    │   ├── cli/
    │   │   ├── bin/
    │   │   │   └── miao.js
    │   │   ├── src/
    │   │   │   ├── commands/
    │   │   │   │   └── init.js
    │   │   │   ├── utils/
    │   │   │   │   └── templateUtils.js
    │   │   │   └── index.js
    │   │   ├── package.json
    │   ├── templates/
    │   │   ├── react-ts/
    │   │   │   └── template-files
    │   │   ├── vue-ts/
    │   │   │   └── template-files
    ├── package.json
    └── pnpm-workspace.yaml
    
  3. pnpm workspace 配置 (pnpm-workspace.yaml):

packages:
  - 'packages/*'
  1. 依赖安装
  "devDependencies": {
    "commander": "12.1.0",
    "picocolors": "1.0.1",
    "prompts": "2.4.2",
    "table": "6.8.2",
    "handlebars": "4.7.8"
  }
  1. CLI 入口文件 (packages/cli/bin/miao.js):
#!/usr/bin/env node

import { program } from 'commander';
import { initCommand } from '../src/commands/init.js';

program
  .version('1.0.0')
  .command('init <project-name>')
  .description('initialize a new project')
  .action(initCommand);

program.parse(process.argv);
  1. 初始化命令实现 (packages/cli/src/commands/init.js):
import fs from 'fs-extra';
import path from 'path';
import { promisify } from 'util';
import prompts from 'prompts';
import picocolors from 'picocolors';
import { cloneRepo, copyTemplateFiles } from '../utils/templateUtils.js';

const access = promisify(fs.access);

export async function initCommand(projectName) {
  const response = await prompts([
    {
      type: 'select',
      name: 'projectType',
      message: 'Select project type:',
      choices: [
        { title: 'React-TS', value: 'react-ts' },
        { title: 'Vue-TS', value: 'vue-ts' }
      ]
    },
    {
      type: 'select',
      name: 'templateSource',
      message: 'Select template source:',
      choices: [
        { title: 'Local', value: 'local' },
        { title: 'Remote', value: 'remote' }
      ]
    },
    {
      type: prev => prev === 'remote' ? 'text' : null,
      name: 'repoUrl',
      message: 'Enter the git repository URL:'
    }
  ]);

  const projectPath = path.join(process.cwd(), projectName);
  try {
    await access(projectPath);
    console.error(picocolors.red(`Project directory ${projectName} already exists.`));
    process.exit(1);
  } catch (err) {
    fs.mkdirSync(projectPath);
  }

  if (response.templateSource === 'local') {
    const templatePath = path.join(__dirname, `../../../templates/${response.projectType}`);
    copyTemplateFiles(templatePath, projectPath);
  } else {
    const repoUrl = response.repoUrl;
    await cloneRepo(repoUrl, projectPath);
  }

  console.log(picocolors.green(`Project ${projectName} initialized successfully!`));
}
  1. 模板工具函数 (packages/cli/src/utils/templateUtils.js):
import fs from 'fs-extra';
import path from 'path';
import handlebars from 'handlebars';
import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

export function copyTemplateFiles(templatePath, targetPath) {
  fs.copySync(templatePath, targetPath, {
    filter: (src, dest) => {
      if (fs.lstatSync(src).isFile() && src.endsWith('.hbs')) {
        const content = fs.readFileSync(src, 'utf-8');
        const result = handlebars.compile(content)({});
        fs.writeFileSync(dest.replace('.hbs', ''), result);
        return false;
      }
      return true;
    }
  });
}

export async function cloneRepo(repoUrl, targetPath) {
  await execAsync(`git clone ${repoUrl} ${targetPath}`);
}

命令设计

  1. 命令格式

    • miao init <project-name> :初始化一个新项目。

      • 示例: miao init my-project
    • 根据需求,可以设计更多命令,比如 add 命令添加新的模块、 generate 命令生成特定组件等。

  2. 选项与参数

    • -v, --version :查看脚手架版本。
    • -h, --help :查看帮助信息。
    • 其他自定义选项可以根据需要添加。

插件体系设计

修改项目结构,以支持插件化体系脚手架实现

将插件系统独立为子包,可以更好地进行管理和维护。下面是根据你的要求,将插件系统独立为子包的实现方案。

项目结构:

miaoma-cli/
├── packages/
│   ├── cli/
│   │   ├── bin/
│   │   │   └── miao.js
│   │   ├── src/
│   │   │   ├── commands/
│   │   │   │   └── init.js
│   │   │   ├── utils/
│   │   │   │   └── templateUtils.js
│   │   │   └── index.js
│   │   ├── package.json
│   ├── plugins/
│   │   ├── src/
│   │   │   ├── index.js
│   │   │   ├── pluginA.js
│   │   │   └── pluginB.js
│   │   ├── package.json
│   ├── templates/
│   │   ├── react-ts/
│   │   │   └── template-files
│   │   ├── vue-ts/
│   │   │   └── template-files
├── package.json
└── pnpm-workspace.yaml
  1. 插件系统主文件 (packages/plugins/src/index.js):
import fs from 'fs-extra';
import path from 'path';

const plugins = {};

export function registerPlugin(pluginName, plugin) {
  plugins[pluginName] = plugin;
}

export function loadPlugins() {
  const pluginsDir = path.join(__dirname);
  fs.readdirSync(pluginsDir).forEach(file => {
    if (file !== 'index.js') {
      const plugin = require(path.join(pluginsDir, file));
      if (plugin && plugin.name && plugin.apply) {
        registerPlugin(plugin.name, plugin.apply);
      }
    }
  });
}

export function applyPlugins(hook, ...args) {
  Object.values(plugins).forEach(plugin => {
    if (typeof plugin[hook] === 'function') {
      plugin[hook](...args);
    }
  });
}
  1. 插件示例 (packages/plugins/src/pluginA.js):
export const name = 'pluginA';

export function apply(hook, ...args) {
  if (hook === 'beforeInit') {
    console.log('pluginA: beforeInit hook called');
  } else if (hook === 'afterInit') {
    console.log('pluginA: afterInit hook called');
  }
}
  1. CLI 中使用插件系统 (packages/cli/src/commands/init.js):
import fs from 'fs-extra';
import path from 'path';
import { promisify } from 'util';
import prompts from 'prompts';
import picocolors from 'picocolors';
import { cloneRepo, copyTemplateFiles } from '../utils/templateUtils.js';
import { loadPlugins, applyPlugins } from '@miaoma/plugins';

const access = promisify(fs.access);

loadPlugins();

export async function initCommand(projectName) {
  applyPlugins('beforeInit', projectName);

  const response = await prompts([
    {
      type: 'select',
      name: 'projectType',
      message: 'Select project type:',
      choices: [
        { title: 'React-TS', value: 'react-ts' },
        { title: 'Vue-TS', value: 'vue-ts' }
      ]
    },
    {
      type: 'select',
      name: 'templateSource',
      message: 'Select template source:',
      choices: [
        { title: 'Local', value: 'local' },
        { title: 'Remote', value: 'remote' }
      ]
    },
    {
      type: prev => prev === 'remote' ? 'text' : null,
      name: 'repoUrl',
      message: 'Enter the git repository URL:'
    }
  ]);

  const projectPath = path.join(process.cwd(), projectName);
  try {
    await access(projectPath);
    console.error(picocolors.red(`Project directory ${projectName} already exists.`));
    process.exit(1);
  } catch (err) {
    fs.mkdirSync(projectPath);
  }

  if (response.templateSource === 'local') {
    const templatePath = path.join(__dirname, `../../../templates/${response.projectType}`);
    copyTemplateFiles(templatePath, projectPath);
  } else {
    const repoUrl = response.repoUrl;
    await cloneRepo(repoUrl, projectPath);
  }

  console.log(picocolors.green(`Project ${projectName} initialized successfully!`));

  applyPlugins('afterInit', projectName);
}
  1. CLI 入口文件 (packages/cli/bin/miao.js):
#!/usr/bin/env node

import { program } from 'commander';
import { initCommand } from '../src/commands/init.js';

program
  .version('1.0.0')
  .command('init <project-name>')
  .description('initialize a new project')
  .action(initCommand);

program.parse(process.argv);
  1. 模板工具函数 (packages/cli/src/utils/templateUtils.js):
import fs from 'fs-extra';
import path from 'path';
import handlebars from 'handlebars';
import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

export function copyTemplateFiles(templatePath, targetPath) {
  fs.copySync(templatePath, targetPath, {
    filter: (src, dest) => {
      if (fs.lstatSync(src).isFile() && src.endsWith('.hbs')) {
        const content = fs.readFileSync(src, 'utf-8');
        const result = handlebars.compile(content)({});
        fs.writeFileSync(dest.replace('.hbs', ''), result);
        return false;
      }
      return true;
    }
  });
}

export async function cloneRepo(repoUrl, targetPath) {
  await execAsync(`git clone ${repoUrl} ${targetPath}`);
}

扩展与优化

  1. 模板管理

    • 支持用户自定义模板,提供下载和更新模板的功能。
    • 使用Git管理模板仓库,用户可以通过命令从远程仓库更新模板。
  2. 错误处理

    • 增加详细的错误处理和提示信息,提升用户体验。
  3. 测试与文档

    • 编写单元测试和集成测试,确保脚手架功能的稳定性。
    • 提供详细的使用文档和示例,帮助用户快速上手。

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

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

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

  • 协同编辑器从零到一架构实现

  • 推动团队基建落地

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

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

  • 低代码平台设计与实现

    • 编排引擎
    • 流程引擎
    • 编辑器
    • 代码执行器与 JavaScript 沙箱
  • 用户行为分析 SDK 及监控可视化整体实现

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

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

简历优化(30K+ 简历样板)

技能描述

  • 熟练掌握 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
  • 协同编辑器(文档类、画板类)wangEditor、CKEditor
  • 团队基建工程(UI 库、图表库、Cli -> 产生产物 npm 包)
  • 3D 可视化数字孪生 bigdata
  • 低代码平台

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

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

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

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

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

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

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

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

不同阶段对前端人的硬性要求

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

1~3年

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

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

3~5年

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

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

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

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

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

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

5年以上

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

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

职业规划指导

评论区选取三位同学互动,其他同学也可以联系咨询老师,文字方式提供辅导解答。

【未知组件reminder】