前端工程化理论知识
前端工程化
包管理工具 npm/yarn
前端工程化离不开 npm(node package manager) 或者 Yarn 这些管理工具。npm 或 Yarn 在工程项目中,除了负责依赖的安装和维护以外,还能通过 npm scripts 串联起各个职能部分,让独立的环节自动运转起来。
什么是npm
npm 的安装机制很有意思。Python 的 pip 都是全局安装通过虚拟环境的方式隔离开发环境,但是 npm 的安装机制秉承了不同的设计哲学。
它会优先安装依赖包到当前项目目录,使得不同应用项目的依赖各成体系,同时还减轻了包作者的 API 兼容性压力,但这样做的缺陷也很明显:如果我们的项目 A 和项目 B,都依赖了相同的公共库 C,那么公共库 C 一般都会在项目 A 和项目 B 中,各被安装一次。这就说明,同一个依赖包可能在我们的电脑上进行多次安装。
NPM安装
NPM缓存
对于一个依赖包的同一版本进行本地化缓存,是当代依赖包管理工具的一个常见设计。使用时要先执行以下命令:
NPM cli
NPM私有化部署
npm 并没有被屏蔽,但是下载第三方依赖包的速度依然较缓慢,这严重影响 CI/CD 流程或本地开发效率。部署镜像后,一般可以确保高速、稳定的 npm 服务,而且使发布私有模块更加安全。除此之外,审核机制也可以保障私服上的 npm 模块质量和安全。
使用Nexus搭建一个NPM私服
什么是模块化
自定义命名空间
模块化是一种将系统分离成独立部分的方法,特点:严格定义模块接口、模块间具有透明性。
为什么要模块化?
Web 应用越来越复杂,简单的代码组织方式已经无法满足业务和架构需求,需要通过模块化来组织代码。
模块化价值:建立模块化的标准,从而能够管理模块之间的依赖,从而提升代码的可维护性和复用性(高内聚,低耦合)。
模块化历史
- 无模块时代
- 模块化萌芽时代:立即执行函数IIFE
var moudleA = function(){
var a, b;
return {
message: function(c){
alert(a+b+c)
}
}
}()
(function(window){
// todo sth ...
window.jQuery = window.$ = jQuery;
})(window)
- 现代模块时代
- CommonJS
- RequireJS/SeaJS
- ES6 Module
// CommonJS
var math = require('math');
math.add(2,3); // 5
// RequireJS
require((['math']), function(math) {
math.add(2,3)
}
// ES6 moudle
import
前端工程化是Webpack么?
Webpack是什么
- 前端模块化打包工具
unpkg.com
配置文件加载: cosmiconfig
inquire
当别人使用我们编写的组件时,需要确保 组件是可靠的,单元测试正好可以证明则一点。
Mocha
jest
Vue Test Units
渲染 mount和shallowMount
获取元素get find
表单---触发setValue,特别注意await
事件---触发DOM事件trigger,验证组件的自定义事件emitted
异步请求---结合jest和VTU 一起
高级UserProfile组件测试
mock全局组件
mock第三方模块的实现
让实例中添加真实的Vuex store
单独测试Vue store
TDD 的开发方式:开发ColorPicker组件
先写测试用例,所有用例失败
根据用例写实现代码,让用例通过
根据实际情况进行测试,如果有需要可以进行重构
作业
完成IconSwitch的组件开发,并且为其写测试
- 自己撰写需求
- 可以使用ant-design-vue 提供的一些组件,比如a-tooltip,也可以自研
- 这个组件其实并不能很好的体现单元测试的优越,但是可以较好的练习学习的内容
nyc 是如何做到统计覆盖率的?
查看package.json 看看依赖了什么
Istanbuljs---> 类似于babel 给代码加东西
脚手架加一些有趣的工具
实现一个MD转PNG的工具
开发一个Markdown文档转PNG图片的转换工具
需求
- 形式为CLI程序,可以在命令行中运行的工具
- 通过CLI参数指定需要转换的md文件路径
- 支持相对路径和绝对路径
- 如果没有指定输入,报错
- 如果指定的路径不是文件,报错
- 通过--output参数指定输出png 路径
- 不指定输出文件路径,默认以md文件和所在路径输出
- 例如:./readme.md ---> readme.png
- 允许用户通过配置文件的方式配置Markdown渲染后的HTML结构
- Markdown转换为HTM过后,一般只是HTML片段,需要嵌入一个HTML结构中
- 不指定输出文件路径,默认以md文件和所在路径输出
开发要点
- CLI工具的开发过程
- node.js平台常用的几种路径形式
- Node.js平台常用的APIs
- Node.js在生态价值体现
- NPM 发包& 单元测试
思路& 过程
npm link 是开发阶段使用的
commander
node 交由社区去管理导致 node变得非常乱
main是import走的
CLI应用的基本结构
bin & lib
marked 实现Markdown 转HTML
puetter 实现HTML转图片
cosmiconfig 配置文件加载
自动化测试ava
自动化测试
CLI 入口的作用
github-markdown-css, html2canvas
命令行交互 ora
为什么要做前端基建
对于行业来说:由于计算机硬件成本降低但是性能越来越强大,前端以多种形式呈现,VR/AR、一套代码多端运行,有的甚至把类3A游戏搬到了web端。做好了前端的基础设施才能支撑这个大树
对于个人来说: 自己做了基建可以方便他人更好的写代码,有利于避免自己陷入苦逼的重复搬砖困境
什么是一个好的项目
从0到1 打造应用的基础建设,制订应用的工程方案,实现应用构建和发布流程,设计应用中公共方法和底层架构。
在哪里可以找到好的项目
网上有人说"外包毁简历",但是我认为大厂外包虽然做的是一些支持性的工作但是至少可以了解大厂的研发流程大厂的基建等等信息,大厂的这些基础资源必定是他们踩了很多坑之后才形成的,在能力或背景不允许以正式的身份进入大厂以外包的身份进去学习一下内功也未尝不可
小公司的研发流程等基础设施也不一定有
前端基建在前端开发中的表现
JS包管理工具和原理分析
npm安装机制及企业级部署私服原理
前端工程化离不开npm
如何设计一个万能项目脚手架
命令行工具
npm 前端基石
前端工程化离不开npm, 前端的很多报错很多都与npm 有关。
一起思考下面几道题的答案
- 为什么项目依赖出现问题,删除node_modules 和 lockfiles 后重新install 会出现被系统拒绝提交
- 为什么 有的依赖被安装到了dependencies, 有的却被安装到了 devDependencies?
- 我们间接依赖了相同的库,这个相同的库会被重复安装么?
- 项目中混合使用npm和yarn 会出现什么问题
- 我们是否应该提交 lockfiles 文件到项目仓库呢?
npm是如何管理源代码的
npm 安装
使用脚手架生成前端小工具
实现一个MD转PNG
Puppeteer 是一个Node库,它提供了一整套高级API,通过DevTools协议控制Chromium或chrome, 通过 Puppeteer 提供的 API 直接控制 Chrome,模拟大部分用户操作,进行 UI 测试或者作为爬虫访问页面来收集数据。
Puppetter通常被用来做什么
- 为网页生成页面 PDF 或者截取图片
- 抓取 SPA(单页应用)并生成预渲染内容
- 自动提交表单,进行 UI 测试、键盘输入等
- 创建一个随时更新的自动化测试环境,使用最新的 JavaScript 和浏览器功能直接在最新版本的 Chrome 中执行测试
- 捕获网站的timeline.trace,用来帮助分析性能问题
- 测试浏览器扩展
开发
脚手架
为什么会产生前端脚手架
当你准备开发一个新项目时,在进入到实际业务编码前,会遇到的问题:
- 准备好一个项目的基础开发设施,需要投入大量时间和精力
- 较短时间内配置一个技术栈完整,辅助功能丰富, 兼顾不同环境下构建优化目标代码的项目基础代码,需要开发人员在工程领域长久的知识储备与实战总结
- 不同项目需求和团队情况,需要根据不同的现状使用不同的基础设施
脚手架工具能够提供什么 - 利用脚手架工具,可以经过几个简单的选项快速生成项目的基础代码
- 使用脚手架工具生成的项目模板通常是经过经验丰富的开发者提炼和检验的
- 脚手架工具支持自定义模板,可以根据项目中的实际经验总结,定制一个脚手架模板
脚手架是什么
在软件开发领域,脚手架通过各种工具来生成项目基础代码的技术
代码中通常包含项目开发流程中所需的工作目录内的通用基础设施
通用基础设施 - 需要有
package.json
, 它是npm 依赖管理体系下的基础配置文件 - 选择使用
npm
或yarn
作为包管理器 - 确定项目技术栈,在明确选择后安装相关依赖包并在src 目录中建立入口源码文件
- 选择构建工具,主流选择是webpack, 添加对应的配置文件
- 优化构建流程,针对开发/生产环境的不同特点进行各自优化
- 优化构建流程,针对开发/生产环境的不同特点进行各自优化
- 选择调试和调试辅助工具(xxxLint, jest)
- 添加README.md 并将不需要版本管理的目录写入
.gitignore
常见的脚手架工具
Yeoman : 基于特定生成器来创建项目基础代码,足够开放但缺少技术生态
Create-React-App: Facebook 官方提供的React 开发工具集
Vue Cli: Vue
如何使用脚手架创建自己的项目模板
- 使用Vue CLi创建自定义模板
meta.js/json文件 :描述创建过程中的用户交互信息以及用户选项对于模板文件的过滤等
[template-name]/
READNE.md(for npm)
meta.js for meta.json
template/
调试
浏览器热更新
浏览器热更新指的是本地开发同时打开浏览器进行预览,当文件发生变化时,浏览器自动更新页面内容的技术
- 自动刷新整个页面
- 页面整体无刷新而只更新页面的部分内容
接口调试
编码
工具
构建
构建工具历史
webpack
无包构建
部署
部署
为什么会出现脚手架
前端开发已经不是写几个html,引入css, js 那么简单,现在的前端开发变得很复杂,会用到很多工具,需要记很多的命令,如果用一个新的工具把前端工具做一下封装,前端开发可能更轻松些。
前端研发流程需要用到的工具
- 初始化项目 --->Yeoman
- 运行和调试 --->webpack
- 测试 ---> ava/nyc
- 发布 ---> aws-cli
什么是脚手架
脚手架本质是一个操作系统的客户端,它通过命令行执行。
主流框架脚手架
- Vue: https://cli.vuejs.org/zh/; https://cn.vitejs.dev/
- React: https://zh-hans.reactjs.org/tutorial/tutorial.html#setup-option-2-local-development-environment
- Angular: https://angular.io/guide/setup-local
脚手架本质上是将一部分研发过程 实现自动化,标准化, 数据化
- 自动化: 项目代码拷贝/git操作/发布上线
- 标准化: 项目创建/Gitflow/发布、回滚
- 数据化:研发过程系统化,数据化
个人认为前端的主流三大框架就是提供提了一套完整的工具链
Vue为例 vue create vue-test-app
- 主命令:Vue
- command: create
- param: vue-create-app
脚手架是如何工作的
用户在终端输入vue create vue-test-app - 操作系统在环境变量中找vue
- node_modules/@vue/cli/bin/vue.js 接受参数并进行下一步处理
为什么 命令行 可以运行js文件
#!/usr/bin/env node
console.log("hello,word!")
发布系统
使用无头浏览器与DOM检查
什么是PhantomJS
一个无头浏览器 https://phantomjs.org/--->检查最终结果
https://www.jslint.com/ ---->检查代码风格
PhantomJS
下载安装包
解压安装包并把相关文件复制到node 目录下
规范设计: Commit 信息
为什么需要规范Commit 信息
- 让自己或其他人能够清晰的知道每个commit的变更历史
- 可以基于Commit Message 进行过滤查找
- 基于规范化的Commit Mesage 生成 Change Log
- 可以根据某些类型的Commit Meessage 触发构建或者发布流程
- 确定语义化版本的版本号
Angular 规范
- commit Mesage是语义化的,规范化的,格式固定
如何写出符合Angular 规范的Commit Message - https://github.com/angular/angular/blob/main/CONTRIBUTING.md
<type>[optional scope]: <description>
// 空行
[optional body]
// 空行
[optional footer(s)]
Header: <type>(<scope>): <short summary>
- type:
Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
| 类型 | 类别 | 说明 |
| ------------ | ------------ | ------------ |
| ci | Development | 持续集成或部署相关的改动 |
|docs| Development|文档类的更新包括修改用户文档或者开发文档|
| feat | Production | 新增功能 |
| perf | Production |提高代码性能的变更 |
| fix | Production |Bug修复 |
| style |Development |代码格式类的变更 |
| refactor |Production |其他代码类的变更 |
| test | Development | 新增测试用例或更新现有测试用例 |
|build|Development|其他类型,比如构建流程,依赖管理或者辅助工具的变动|
Body
对本次 commit 的更详细描述, 以动词开头,包括修改动机,和上一版本相比的改动点
Footer: 本次commit导致的后果 - Footer 通常用来说明不兼容的改动和关闭的 Issue 列表
BREAKING CHANGE: <breaking change summary> // 如果当前代码跟上一个版本不兼容,需要在 Footer 部分,以 BREAKING CHANG: 开头,后面跟上不兼容改动的摘要。Footer 的其他部分需要说明变动的描述、变动的理由和迁移方法
// 空行
<breaking change description + migration instructions>
// 空行
// 空行
Fixes #<issue number>
// 关闭的 Bug 需要在 Footer 部分新建一行,并以 Closes 开头列出
如何实现 Commit Message 自动化
Commit Message 规范如果靠文档去约束,就会严重依赖开发者的代码素养,并不能真正保证提交的 commit 是符合规范的。
有什么办法可以自动生成和检查Commit Messsage 规范
脚手架核心流程开发
脚手架需求分析和架构设计
教授架需求分析和架构设计
脚手架模块拆分策略和core模块技术方案
脚手架执行准备过程实现
脚手架命令注册实现(基于commander)
核心流程开发
前端研发痛点分析
- 创建项目/组件时,存在大量重复代码拷贝,快速复用已有沉淀
- 协同开发时,由于git操作不规范,导致分支混乱,操作耗时:允许标准的git操作并集成到脚手架
- 发布上线耗时,而且容易出现各种错误:制定标准的上线流程并集成到脚手架
需求分析 - 通用的研发脚手架
- 通用的项目/组件创建能力
- 模板支持定制,定制后能够发布生效
- 模板支持快速接入,极低的接入成本
- 通用的项目/组件发布能力
- 发布过程自动完成标准的git操作
- 发布成功后自动完成云构建,CDN,域名绑定
- 发布过程支持测试/正式两种模式
脚手架架构设计图
教授整体拆包
lerna 怎么拆包
命令
初始化
发布
清楚缓存
模型层
Command命令
Project项目
Component
core模块技术方案
命令执行流程 - 准备阶段
- 命令注册
- 命令执行
prepare :
拆分原则:
核心模块:core
命令模块: commands
模型模块: models
工具模块: utils

yeoman 内部实现
- 输入
- npm
- 文件模板
文件模板
- node
- readline
- console
Dev 工具 - Server
- build: webpack, babel, vue jsx, postcss
- watch: fsevent
- mock:
http: ws
- client
- debugger: vscode devtool
- source map
脚手架发布模块的整体架构设计和实现原理
前端发布流程, hash 和history 两种路由模式区别
深入理解vue-router实现原理
项目发布流程整体架构设计
脚手架发布流程的git自动化流程设计
脚手架云构建+ 云发布架构设计
sqxy 脚手架 publish模块开发
前端发布页面路由模式讲解
vue-router 两种路由模式详解
history 路由模式服务端配置详解
vue-cli dev 模式下history配置原理
vue-router-next源码核心原理分析
前端发布不在依赖运维同学
脚手架发布流程
Git配置---> Git提交 ---> 云构建+ 云发布
Git在开发中常用的操作
Git协同工作流
如何用脚本的方式 实现 Git协同工作流
为什么需要构建
由于项目复杂现代的前端开发人员通常不会直接写HTML/CSS/JavaScript,而是借助框架比如Vue,但是浏览器只认识HTML/CSS/JavaScript,再加上反爬,性能优化的需求,前端常常会对js文件名,js文件中的变量做一次加密,
为什么需要云构建
- 减少发布过程中的重复劳动
- 避免不同环境间的差异
- 对构建过程进行统一,集中管控
云构建的过程
借助egg实现客户端与服务端通信
参考链接
- egg-socket.io
WebSocket接入流程
2. 添加配置
```
'use strict';
config.io = {
namespace: {
'/': {
connectionMiddleware: [ 'auth' ],
packetMiddleware: [ 'filter' ],
},
'/chat': {
connectionMiddleware: [ 'auth' ],
packetMiddleware: [],
},
},
};
exports.keys = '123';
- 配置plugins.js
// {app_root}/config/plugin.js exports.io = { enable: true, package: 'egg-socket.io', };
- 修改路由配置
//router.js // app.io.of('/') app.io.route('chat',app.io.comtroller.chat.index); // app.io.of('/chat') app.io.of('/chat').route('chat',app.io.controller.chat.index);
- 开发middleware
// app/io/middleware/auth.js 'use strict'; module.exports = () => { return async (ctx, next) => { const say = await ctx.service.user.say(); ctx.socket.emit('res', 'auth!' + say); await next(); console.log('disconnect!'); }; };
- 开发controller
// app/io/controller/chat.js 'use strict'; module.exports = app => { class Controller extends app.Controller { async index() { const message = this.ctx.args[0]; console.log('chat :', message + ' : ' + process.pid); const say = await this.ctx.service.user.say(); this.ctx.socket.emit('res', say); } } return Controller; };
客户端
1.
lerna create cloudbuild models
改名
服务端监听
egg集成redis
config/plugin.js->exports.redis ={
enable:true,package:'egg-redis',};
云构建逻辑
发布系统
服务器
jenkins与yeoman?
devops与运维发布的区别
脚手架发布功能开发
收获什么
- 前端脚手架演进过程和大厂前端物料体系介绍
- 组件复用体系整体架构设计
- 脚手架组件创建+ 发布全流程实现
主要内容 - 大厂前端物料体系介绍
- 前端组件平台架构设计
- 脚手架组件创建流程复习
- 脚手架组件发布流程实现
关键词 - 前端物料
- 前端组件
- 组件发布
学习方法 - 先理解概念,在进行学习:本周和下周共同打造一个组件体系,通过这个体系优化我们的研发流程,所以需要先了解组件的概念,结合之前脚手架创建流程,再进行组件的开发
注意事项 - 本周概念较多,需要逐个理解和进阶
- 可以尝试在实际场景落地,或者优化现有研发流程
前端物料体系 - 为什么会形成前端物料体系?
由于前端项目规模不断增大,代码中不断出现重复或类似代码,因此需要将这些代码抽象和复用,以提高开发效率。在实践过程中不断出现新的物料类型,单纯的组件库已经无法满足代码复用的需求。
前端物料概念对前端开发有什么影响?
在工作中能够更好地以物料库的维度器思考项目的复用问题
前端物料体系和组件库的关系是什么?
组件库是物料体系的一部分,物料体系包括所有可复用的前端代码
前端物料包括哪些
组件、区块、 模板、工程模板、JS库、 CSS库、 代码片段...
前端组件平台架构设计
发布,支持回滚
基于 git tag 和github actions 实现发布上线和回滚
域名cname转发和nginx反向代理
搭建虚拟机,数据库
上线和回滚流程
域名战法和nginx配置
购买和配置云服务器,云数据库
测试环境下要求配置灵活,集成性高,一键部署,数据安全性要求不高,适合用Docker。
线上环境要求稳定,高效,数据安全性要求高,适合独立的数据库服务