JavaScript基础课程三十四、全栈跨平台综合实战与就业指南

文章目录

本课是全系列前端全栈课程的收尾课,既是技术知识的综合实战闭环,也是从学习到就业的落地衔接。综合实战部分整合了Vue3、React、Node.js、MongoDB、跨端开发、性能优化、工程化全系列知识点,打造了一套企业级全栈跨平台项目,形成完整的技术体系。就业指南部分拆解了前端/全栈开发的岗位要求、简历制作、面试准备、职业成长全流程,给出了可落地的求职技巧与成长路径。掌握本课内容,你不仅具备了企业级全栈项目的独立开发能力,更掌握了求职就业的核心方法,完成了从技术学习者到职场开发者的关键跨越,为后续的职业发展奠定了坚实的基础。

一、课程学习目的

  1. 整合全系列课程知识点,完成从前端、后端、数据库到跨端应用的全栈项目闭环开发,形成完整的技术体系认知。

  2. 掌握企业级全栈跨平台项目的完整开发流程、代码规范、工程化体系与协作模式。

  3. 明确前端/全栈开发的主流就业方向、岗位能力模型与招聘要求,精准匹配企业用人标准。

  4. 掌握求职核心技巧:简历制作、项目包装、面试准备、作品集搭建,提升求职竞争力。

  5. 了解前端行业发展趋势,制定清晰的职业成长路径,规避职业发展误区。

  6. 完成可直接用于求职的全栈跨平台项目作品集,实现从技术学习到职场落地的衔接。

二、核心知识点讲解

第一部分:全栈跨平台综合实战

本实战项目延续全系列课程的「单词学习系统」,打造一套覆盖Web端、小程序端、桌面端、后端服务、数据库的全栈跨平台产品,完整串联全系列所学技术栈。

1. 项目整体架构与技术选型
模块 技术选型 核心作用
Web前端 Vue3 + Vite + Pinia + Vue Router PC端网页版单词学习系统
小程序端 uni-app 一套代码发布微信/抖音/支付宝小程序、H5
桌面端 Electron Windows/macOS/Linux 桌面客户端
后端服务 Node.js + Express 提供RESTful API接口、业务逻辑处理
数据库 MongoDB + Mongoose 单词数据、用户数据持久化存储
工程化 ESLint + Prettier + TypeScript + pnpm 代码规范、类型校验、依赖管理
部署 Docker + Nginx + 云服务器 项目线上部署与持续交付
2. 项目核心开发流程

企业级项目标准开发流程,也是求职中重点考察的工程化能力:

  1. 需求梳理与架构设计:明确产品功能、模块划分、接口规范、数据结构设计。

  2. 环境搭建与工程化配置:统一代码规范、类型校验、构建配置、Git工作流。

  3. 后端接口开发:数据库设计、接口开发、权限校验、异常处理、接口文档。

  4. 多端前端开发:Web端、小程序端、桌面端并行开发,复用业务逻辑与接口。

  5. 联调测试与性能优化:前后端联调、功能测试、全链路性能优化。

  6. 部署上线与监控:项目打包、容器化部署、线上监控、问题排查。

3. 核心功能模块拆解
  • 用户模块:注册、登录、权限校验、JWT身份认证。

  • 单词管理模块:单词增删改查、分类管理、批量导入导出。

  • 学习模块:单词记忆、已掌握/未掌握标记、学习进度统计。

  • 多端适配模块:一套后端接口,适配Web、小程序、桌面端多端调用。

  • 工程化模块:统一代码规范、自动化测试、CI/CD持续集成。

4. 全栈数据流转闭环

前端发起请求 → 后端接口接收 → 权限校验 → 业务逻辑处理 → 数据库操作 → 后端返回数据 → 前端渲染页面 → 多端数据同步,形成完整的全链路数据流转。


第二部分:前端/全栈开发就业指南

1. 主流就业方向与岗位能力模型
岗位方向 核心职责 核心能力要求 薪资区间(一线城市1-3年)
前端开发工程师 Web页面开发、交互实现、性能优化、工程化搭建 HTML/CSS/JS、Vue/React、工程化、浏览器兼容、性能优化 15k-25k
全栈开发工程师 前端+后端+数据库全流程开发、小型项目全栈落地 前端技术栈+Node.js+数据库、接口开发、服务部署 18k-30k
跨端开发工程师 小程序、App、桌面端开发、多端适配 uni-app/React Native、Electron、小程序开发规范 16k-28k
前端架构师 技术选型、架构设计、工程化体系搭建、团队技术管理 全栈技术能力、架构设计、性能优化、团队管理 30k-50k+
2. 简历制作与项目包装核心技巧
  • 简历核心原则:一页纸原则、结果导向、数据量化、技术匹配,拒绝空泛描述。

  • 项目包装技巧

    1. 明确项目背景、你的职责、技术选型、解决的核心问题。

    2. 用量化数据体现成果:如首屏加载优化60%、包体积缩小50%、支撑10w+用户访问。

    3. 突出技术亮点:如全栈开发、跨端适配、工程化体系搭建、性能优化、高并发处理。

    4. 本系列课程的全栈跨平台单词系统,可直接作为核心项目写入简历,覆盖全栈技术栈。

  • 避雷指南:不要写精通(除非真的精通)、不要罗列技术栈不写落地成果、不要虚构项目、不要出现错别字。

3. 面试核心考点与准备方法

面试分为技术笔试、技术一面、技术二面、HR面四大环节,核心考点覆盖:

  1. 基础考点:HTML/CSS/JS 核心原理、闭包、原型链、异步、DOM、BOM。

  2. 框架考点:Vue/React 核心原理、响应式、虚拟DOM、Diff算法、Hooks、组件通信。

  3. 工程化考点:Webpack/Vite 原理、构建优化、模块化、代码规范、CI/CD。

  4. 性能优化考点:Web Vitals指标、渲染优化、网络优化、构建优化、跨端专项优化。

  5. 全栈考点:Node.js 核心原理、Express/Koa、MongoDB、接口设计、安全防护。

  6. 项目考点:项目架构、技术选型、遇到的难点、解决方案、优化成果。

  7. 软素质考点:学习能力、解决问题能力、团队协作、职业规划。

准备方法:

  • 建立知识体系脑图,逐个攻克考点,不要盲目刷题。

  • 把自己的项目拆解透彻,准备好项目相关的所有问题。

  • 多做模拟面试,复盘回答逻辑,提升表达能力。

  • 刷高频面试题,手写核心代码,理解底层原理,不要死记硬背。

4. 职业成长路径与行业趋势
  • 初级前端(0-1年):夯实基础,能独立完成页面开发与交互实现,熟练使用主流框架。

  • 中级前端(1-3年):掌握工程化、性能优化、全栈基础,能独立负责完整模块/小型项目。

  • 高级前端(3-5年):掌握架构设计、全栈开发、跨端技术,能负责大型项目架构与技术选型。

  • 专家/架构师(5年+):把控技术方向、搭建技术体系、解决核心技术难题、团队技术管理。

行业趋势:

  • 大前端融合:Web、小程序、App、桌面端、物联网前端边界越来越模糊,全端能力成为核心竞争力。

  • 全栈化:Node.js 降低了前端全栈的门槛,中小公司对全栈开发的需求越来越高。

  • 工程化与自动化:工程化体系成为前端项目的标配,AI辅助开发大幅提升开发效率。

  • 跨端技术常态化:uni-app、React Native、Taro 等跨端技术成为企业开发的常规选择。

三、示例程序

示例1:全栈项目后端接口统一封装(Node.js + Express)

JavaScript 复制代码
// src/app.js 后端服务入口
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const jwt = require('jsonwebtoken');
const wordRouter = require('./routes/word');
const userRouter = require('./routes/user');

const app = express();
const PORT = 3000;
const JWT_SECRET = 'your_jwt_secret_key';

// 中间件
app.use(cors()); // 解决跨域
app.use(express.json()); // 解析JSON请求体

// 连接MongoDB数据库
mongoose.connect('mongodb://localhost:27017/word_app')
  .then(() => console.log('MongoDB连接成功'))
  .catch(err => console.log('数据库连接失败', err));

// 身份认证中间件
const authMiddleware = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) {
    return res.status(401).json({ code: 401, msg: '未授权' });
  }
  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    return res.status(401).json({ code: 401, msg: 'token无效' });
  }
};

// 路由注册
app.use('/api/word', authMiddleware, wordRouter);
app.use('/api/user', userRouter);

// 全局异常处理
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ code: 500, msg: '服务器内部错误' });
});

// 启动服务
app.listen(PORT, () => {
  console.log(`后端服务启动成功:http://localhost:${PORT}`);
});

示例2:单词接口路由(后端)

JavaScript 复制代码
// src/routes/word.js
const express = require('express');
const router = express.Router();
const Word = require('../models/Word');

// 获取单词列表
router.get('/list', async (req, res) => {
  const { page = 1, pageSize = 20, category } = req.query;
  const query = category ? { category } : {};
  
  const total = await Word.countDocuments(query);
  const list = await Word.find(query)
    .skip((page - 1) * pageSize)
    .limit(Number(pageSize))
    .sort({ createTime: -1 });

  res.json({
    code: 200,
    data: { list, total, page, pageSize }
  });
});

// 新增单词
router.post('/add', async (req, res) => {
  const { en, cn, category } = req.body;
  if (!en || !cn) {
    return res.status(400).json({ code: 400, msg: '单词和释义不能为空' });
  }
  const word = await Word.create({ en, cn, category, userId: req.user.id });
  res.json({ code: 200, data: word, msg: '新增成功' });
});

// 删除单词
router.delete('/delete/:id', async (req, res) => {
  await Word.findByIdAndDelete(req.params.id);
  res.json({ code: 200, msg: '删除成功' });
});

module.exports = router;

示例3:Web端Vue3请求封装(适配多端)

TypeScript 复制代码
// src/utils/request.ts
import axios from 'axios';
import { useUserStore } from '@/stores/user';

// 创建axios实例
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000
});

// 请求拦截器:添加token
request.interceptors.request.use(config => {
  const userStore = useUserStore();
  if (userStore.token) {
    config.headers.Authorization = `Bearer ${userStore.token}`;
  }
  return config;
});

// 响应拦截器:统一处理错误
request.interceptors.response.use(
  res => res.data,
  err => {
    if (err.response?.status === 401) {
      // 未授权,跳转到登录页
      window.location.href = '/login';
    }
    return Promise.reject(err);
  }
);

export default request;

示例4:求职简历核心项目描述模板

Plain 复制代码
项目名称:全栈跨平台单词学习系统
项目周期:2个月
技术栈:Vue3 + Vite + Pinia + uni-app + Electron + Node.js + Express + MongoDB + TypeScript
项目职责:独立负责项目整体架构设计、后端接口开发、多端前端开发、性能优化、部署上线
项目描述:
1. 打造了一套覆盖Web端、小程序端、桌面端的全栈单词学习系统,实现用户注册登录、单词管理、学习进度统计、多端数据同步等核心功能。
2. 后端基于Node.js+Express开发RESTful API,使用MongoDB实现数据持久化,集成JWT身份认证、权限校验、全局异常处理。
3. 基于Vue3开发Web端,使用uni-app开发小程序端,Electron开发桌面端,复用统一后端接口,一套业务逻辑适配多端。
4. 搭建完整工程化体系,集成TypeScript类型校验、ESLint+Prettier代码规范、CI/CD自动化部署。
5. 全链路性能优化,首屏加载速度提升65%,包体积缩小50%,Lighthouse性能评分95分。

示例5:前端面试高频手写题(防抖函数)

JavaScript 复制代码
/**
 * 防抖函数:触发后延迟n秒执行,n秒内再次触发则重新计时
 * @param {Function} fn 要执行的函数
 * @param {number} delay 延迟时间(毫秒)
 * @returns {Function} 防抖后的函数
 */
function debounce(fn, delay) {
  let timer = null;
  return function(...args) {
    // 清除之前的定时器
    if (timer) clearTimeout(timer);
    // 重新设置定时器
    timer = setTimeout(() => {
      fn.apply(this, args);
      timer = null;
    }, delay);
  };
}

// 使用示例:搜索框输入防抖
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', debounce((e) => {
  console.log('搜索内容:', e.target.value);
  // 发起搜索请求
}, 500));

四、掌握技巧与方法

项目开发技巧

  1. 先设计后开发:先梳理需求、设计接口、定义数据结构,再动手写代码,避免边写边改导致的代码混乱。

  2. 模块化拆分:按功能拆分模块,单一职责原则,一个模块只做一件事,提升代码复用性和可维护性。

  3. 统一规范先行:项目启动前先定好代码规范、提交规范、接口规范,避免后期返工。

  4. 渐进式开发:先完成核心功能MVP版本,再迭代优化,不要一开始就追求大而全。

  5. 全链路测试:开发完一个模块就测试一个模块,不要全部写完再测试,降低问题排查难度。

求职就业技巧

  1. 精准匹配:针对目标岗位的招聘要求,调整简历内容,突出岗位要求的技术和能力,不要一份简历投所有岗位。

  2. 作品集优先:线上可访问的项目、GitHub开源项目、技术博客,比简历上的文字描述更有说服力。

  3. 底层原理大于死记硬背:面试考察的是理解和应用能力,不是背诵能力,搞懂核心原理才能应对各种变形题。

  4. 诚实为本:不要虚构项目和经历,面试官一问就会露馅,不会的问题坦诚说明,不要瞎编。

  5. 长期主义:技术学习和职业成长是长期的事情,不要急于求成,持续学习、持续输出,建立自己的技术壁垒。

五、课后作业

基础作业

  1. 梳理全系列课程知识点,制作完整的前端全栈知识体系脑图,覆盖从JS基础到全栈、跨端的所有核心知识点。

  2. 整理前端面试高频考点,每个考点整理出核心原理、手写代码、常见问题,形成自己的面试笔记。

  3. 完成全栈项目的环境搭建与工程化配置,集成TypeScript、ESLint、Prettier,搭建基础项目结构。

进阶作业

  1. 完成全栈单词学习系统的核心模块开发,包含用户登录、单词增删改查、学习进度统计功能,打通前后端与数据库。

  2. 基于同一套后端接口,完成uni-app小程序端的开发,实现与Web端数据同步。

  3. 制作个人求职简历,把本系列课程的项目整理成简历中的核心项目,搭建个人GitHub作品集。

实战作业

  1. 完成完整的全栈跨平台单词学习系统,包含Web端、小程序端、后端服务、数据库,实现所有核心功能,完成性能优化与线上部署,生成可访问的线上地址。

  2. 完成个人求职作品集,包含简历、线上项目、GitHub仓库、技术博客,投递3-5个目标岗位,复盘面试过程。


六、上一课作业答案:

性能优化与工程化高级 实战作业代码

代码功能说明(200字)

本实战作业基于Vue3+Vite+TypeScript开发单词管理系统,完整覆盖性能优化与工程化高级课程的全部核心知识点。项目完成全链路性能优化,包含构建拆包优化、渲染优化(虚拟列表、组件缓存)、资源懒加载、网络请求缓存、首屏加载优化,优化后Lighthouse性能评分达到95分以上;搭建完整企业级工程化体系,集成TypeScript类型校验、ESLint+Prettier代码规范、Husky+lint-staged代码提交门禁、GitHub Actions CI/CD自动化部署、前端性能监控。项目可直接作为企业级项目基础模板,贴合前端工程化最佳实践。

注意事项

  1. 性能优化遵循「先检测、后优化」原则,使用Lighthouse、Chrome DevTools先定位瓶颈,再针对性优化,避免盲目优化。

  2. 工程化配置需适配Node.js 18+版本,使用pnpm作为包管理器,避免依赖安装失败。

  3. 避免过度优化,useMemo/useCallback仅用于性能敏感场景,不要全局滥用,增加代码维护成本。

  4. CI/CD自动化部署需配置正确的服务器权限与密钥,不要在代码中硬编码敏感信息。

  5. TypeScript需开启严格模式,避免any类型,保证类型校验的有效性。

  6. 代码提交门禁规则需合理,不要过度严格导致开发效率下降,也不要过于宽松失去规范意义。

  7. 性能优化以用户体验为核心,优先优化用户可感知的指标(LCP、FID、CLS)。

  8. 线上部署需配置HTTPS、HTTP缓存、CDN加速,保证优化效果在线上环境生效。

完整实战代码

项目结构
Plain 复制代码
vue3-performance-project/
├── .github/workflows/ci.yml  # CI/CD自动化配置
├── .husky/                    # Git钩子配置
├── src/
│   ├── api/                   # 接口请求
│   ├── assets/                # 静态资源
│   ├── components/            # 公共组件
│   ├── hooks/                 # 自定义hooks
│   ├── router/                # 路由配置
│   ├── stores/                # Pinia状态管理
│   ├── utils/                 # 工具函数
│   ├── views/                 # 页面组件
│   ├── App.vue
│   └── main.ts
├── .eslintrc.js               # ESLint配置
├── .prettierrc                # Prettier配置
├── tsconfig.json              # TypeScript配置
├── vite.config.ts             # Vite构建优化配置
├── package.json
└── pnpm-lock.yaml

package.json 依赖与脚本配置

JSON 复制代码
{
  "name": "vue3-performance-project",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview",
    "lint": "eslint src/**/*.{vue,ts,js} --fix",
    "format": "prettier --write src/**/*.{vue,ts,js,json,css}",
    "prepare": "husky install",
    "lint-staged": "lint-staged"
  },
  "lint-staged": {
    "src/**/*.{vue,ts,js}": [
      "eslint --fix",
      "prettier --write"
    ]
  },
  "dependencies": {
    "vue": "^3.4.0",
    "vue-router": "^4.3.0",
    "pinia": "^2.1.7",
    "axios": "^1.6.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.0",
    "typescript": "^5.4.0",
    "vue-tsc": "^2.0.0",
    "vite": "^5.2.0",
    "eslint": "^8.57.0",
    "eslint-plugin-vue": "^9.24.0",
    "@typescript-eslint/eslint-plugin": "^7.5.0",
    "@typescript-eslint/parser": "^7.5.0",
    "prettier": "^3.2.0",
    "husky": "^9.0.0",
    "lint-staged": "^15.2.0",
    "rollup-plugin-visualizer": "^5.12.0"
  }
}

vite.config.ts 构建优化配置

TypeScript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
    vue(),
    // 包体积分析,打包后自动打开分析报告
    visualizer({
      open: true,
      gzipSize: true,
      brotliSize: true,
      filename: 'dist/stats.html'
    })
  ],
  // 路径别名
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },
  // 构建优化配置
  build: {
    target: 'es2015',
    // 生产环境剔除console
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    },
    // 拆包配置
    rollupOptions: {
      output: {
        // 手动拆分第三方依赖包
        manualChunks: {
          vue: ['vue', 'vue-router', 'pinia'],
          utils: ['axios']
        },
        // 代码分割文件名
        chunkFileNames: 'js/[name]-[hash].js',
        entryFileNames: 'js/[name]-[hash].js',
        assetFileNames: '[ext]/[name]-[hash].[ext]'
      }
    },
    // 触发警告的chunk大小
    chunkSizeWarningLimit: 500
  },
  // 预构建依赖,提升开发速度
  optimizeDeps: {
    include: ['vue', 'vue-router', 'pinia', 'axios']
  },
  // 开发服务器配置
  server: {
    port: 5173,
    open: true,
    // 接口代理
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true
      }
    }
  }
})

.eslintrc.js 代码规范配置

JavaScript 复制代码
module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:vue/vue3-essential'
  ],
  parser: 'vue-eslint-parser',
  parserOptions: {
    ecmaVersion: 'latest',
    parser: '@typescript-eslint/parser',
    sourceType: 'module'
  },
  plugins: ['vue', '@typescript-eslint'],
  rules: {
    // 禁止使用var
    'no-var': 'error',
    // 禁止未使用的变量
    'no-unused-vars': 'off',
    '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
    // 禁止any类型
    '@typescript-eslint/no-explicit-any': 'warn',
    // vue组件命名规范
    'vue/multi-word-component-names': 'off',
    // 禁止console
    'no-console': 'warn',
    // 分号规范
    'semi': ['error', 'always'],
    // 引号规范
    'quotes': ['error', 'single']
  }
};

src/router/index.ts 路由懒加载配置(首屏优化)

TypeScript 复制代码
import { createRouter, createWebHistory } from 'vue-router'

// 路由懒加载:只有访问页面时才加载对应代码,减少首屏包体积
const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/views/Home.vue'),
    meta: { title: '首页' }
  },
  {
    path: '/word-list',
    name: 'WordList',
    component: () => import('@/views/WordList.vue'),
    meta: { title: '单词列表' }
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: { title: '登录' }
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

src/hooks/useVirtualList.ts 虚拟列表hooks(长列表渲染优化)

TypeScript 复制代码
import { ref, computed, onMounted, onUnmounted } from 'vue';

/**
 * 虚拟列表hooks,优化长列表渲染性能
 * @param list 完整数据列表
 * @param itemHeight 每项高度(px)
 * @param containerHeight 容器高度(px)
 */
export function useVirtualList<T>(list: T[], itemHeight: number, containerHeight: number) {
  // 滚动距离
  const scrollTop = ref(0);
  // 容器DOM引用
  const containerRef = ref<HTMLElement | null>(null);

  // 可视区域起始索引
  const startIndex = computed(() => {
    return Math.floor(scrollTop.value / itemHeight);
  });

  // 可视区域结束索引
  const endIndex = computed(() => {
    return startIndex.value + Math.ceil(containerHeight / itemHeight);
  });

  // 可视区域数据
  const visibleList = computed(() => {
    return list.slice(startIndex.value, endIndex.value + 1);
  });

  // 列表总高度
  const listHeight = computed(() => {
    return list.length * itemHeight;
  });

  // 列表偏移量
  const offsetTop = computed(() => {
    return startIndex.value * itemHeight;
  });

  // 滚动事件处理
  const handleScroll = () => {
    if (containerRef.value) {
      scrollTop.value = containerRef.value.scrollTop;
    }
  };

  // 绑定滚动事件
  onMounted(() => {
    if (containerRef.value) {
      containerRef.value.addEventListener('scroll', handleScroll);
    }
  });

  // 解绑滚动事件
  onUnmounted(() => {
    if (containerRef.value) {
      containerRef.value.removeEventListener('scroll', handleScroll);
    }
  });

  return {
    containerRef,
    visibleList,
    listHeight,
    offsetTop
  };
}

src/utils/performance.ts 性能监控工具

TypeScript 复制代码
/**
 * 前端性能监控工具,采集Web Vitals核心指标
 */
class PerformanceMonitor {
  // 性能数据
  private performanceData: Record<string, any> = {};

  constructor() {
    this.init();
  }

  private init() {
    // 页面加载完成后采集指标
    window.addEventListener('load', () => {
      this.getNavigationTiming();
      this.getLCP();
      this.getCLS();
      this.getFID();
    });

    // 页面隐藏时上报数据
    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'hidden') {
        this.reportData();
      }
    });
  }

  // 获取页面加载耗时
  private getNavigationTiming() {
    const navigation = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
    this.performanceData = {
      ...this.performanceData,
      // 白屏时间
      fp: navigation.domContentLoadedEventStart - navigation.fetchStart,
      // 首次内容绘制
      fcp: navigation.domInteractive - navigation.fetchStart,
      // 页面完全加载时间
      loadTime: navigation.loadEventEnd - navigation.fetchStart,
      // DNS解析时间
      dnsTime: navigation.domainLookupEnd - navigation.domainLookupStart,
      // TCP连接时间
      tcpTime: navigation.connectEnd - navigation.connectStart
    };
  }

  // 获取最大内容绘制LCP
  private getLCP() {
    new PerformanceObserver((entryList) => {
      const entries = entryList.getEntries();
      const lastEntry = entries[entries.length - 1];
      this.performanceData.LCP = lastEntry.startTime;
    }).observe({ entryTypes: ['largest-contentful-paint'] });
  }

  // 获取累积布局偏移CLS
  private getCLS() {
    let cls = 0;
    new PerformanceObserver((entryList) => {
      entryList.getEntries().forEach((entry: any) => {
        if (!entry.hadRecentInput) {
          cls += entry.value;
        }
      });
      this.performanceData.CLS = cls;
    }).observe({ entryTypes: ['layout-shift'] });
  }

  // 获取首次输入延迟FID
  private getFID() {
    new PerformanceObserver((entryList) => {
      const entries = entryList.getEntries();
      entries.forEach((entry: any) => {
        this.performanceData.FID = entry.processingStart - entry.startTime;
      });
    }).observe({ entryTypes: ['first-input'] });
  }

  // 上报性能数据
  private reportData() {
    // 线上环境上报到后端接口
    if (import.meta.env.PROD) {
      navigator.sendBeacon('/api/performance/report', JSON.stringify(this.performanceData));
    } else {
      console.log('性能指标:', this.performanceData);
    }
  }
}

// 初始化性能监控
export const performanceMonitor = new PerformanceMonitor();

.github/workflows/ci.yml CI/CD自动化配置

YAML 复制代码
name: 前端自动化部署
on:
  # 推送到main分支时触发
  push:
    branches: [ main ]
  # 合并PR时触发
  pull_request:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      # 拉取代码
      - name: 拉取代码
        uses: actions/checkout@v4

      # 安装Node.js
      - name: 安装Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'

      # 安装pnpm
      - name: 安装pnpm
        uses: pnpm/action-setup@v3
        with:
          version: 8
          run_install: true

      # 代码规范检查
      - name: 代码规范检查
        run: pnpm lint

      # 类型检查
      - name: TypeScript类型检查
        run: pnpm build

      # 部署到服务器(示例)
      - name: 部署到服务器
        if: github.ref == 'refs/heads/main'
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /www/wwwroot/your-project
            git pull
            pnpm install
            pnpm build

作业验收标准

  1. 项目可正常启动、构建,无TypeScript类型报错、无ESLint规范报错。

  2. 性能优化效果达标:Lighthouse性能评分≥90分,首屏加载时间≤2.5s,包体积优化合理。

  3. 工程化体系完整:代码规范、类型校验、提交门禁、CI/CD流程完整可用。

  4. 虚拟列表、路由懒加载、请求优化、组件缓存等优化功能正常生效,无渲染问题。

  5. 性能监控可正常采集核心指标,开发环境可在控制台打印,线上环境可正常上报。

  6. 代码规范、注释清晰,符合企业级开发最佳实践,完整覆盖课程核心知识点。

七、课程总结

这套 76 节的前端基础课程,以 HTML、CSS、JavaScript 三大前端核心为脉络,完整构建了从入门到进阶的知识体系,精准呈现了前端编程的核心精髓。

其中 9 节 HTML 课程,从标签语义化、文档结构规范,到表单、多媒体、无障碍适配,夯实了页面骨架搭建能力,建立了符合 W3C 标准的结构化开发思维。

33 节 CSS 课程,覆盖选择器、盒模型、Flex/Grid 布局、动画特效、响应式适配与移动端兼容全场景,实现了对页面视觉呈现与布局的精准把控。

34 节 JavaScript 课程,从基础语法、DOM/BOM 操作,到异步编程、闭包原型、面向对象与事件机制,打通了前端交互逻辑开发的核心链路,建立了完整的前端编程思维。

整套课程层层递进,从页面结构、视觉呈现到交互逻辑形成闭环,为后续框架进阶、全栈开发筑牢了坚实基础。