Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端工程化阅读摘要 #19

Open
UNDERCOVERj opened this issue Dec 23, 2018 · 0 comments
Open

前端工程化阅读摘要 #19

UNDERCOVERj opened this issue Dec 23, 2018 · 0 comments

Comments

@UNDERCOVERj
Copy link
Owner

UNDERCOVERj commented Dec 23, 2018

[TOC]

工程技术元素

浅谈前端集成解决方案

  1. 开发规范

目录规范,编码规范,commit规范

  1. 模块化开发

    1. 针对js、css以功能或业务为单元组织代码
    2. js方面解决独立作用域、依赖管理、api暴露、按需加载与执行、安全合并等问题
    3. css方面解决依赖管理、组件内部样式管理等问题
    4. 避免命名冲突
    5. 便于依赖管理
    6. 利于性能优化
      1. 按需加载
      2. 合并文件
    7. 提高可维护性
      1. 模块化
    8. 代码复用
  2. 组件化开发

在模块化基础上分拆页面成可复用的组件

  1. 组件仓库

将组件放到一个公共的地方,供团队共享

  1. 性能优化

工程问题和统计问题

  1. 项目部署

    静态资源缓存、cdn、非覆盖式发布等问题。可配置化、操作简化

    1. 指定配置策略,并且支持针对特定环境分别配置
    2. 实现部署行为,以SFTP协议为连接协议
      1. 建立ssh连接
      2. 遍历本地待部署目录
      3. 一次上传待部署文件
    3. 开发命令行接口
    4. 搭建可供严格审查、队列控制以及执行部署行为的部署平台
  2. 开发流程

本地开发调试、视觉效果走查确认、前后端联调、提测、上线等环节

  1. 开发工具

    1. 构建与优化工具
    2. 开发-调试-部署等流程工具
    3. 组件库获取、提交等相关工具
    4. 运营、文档、配置发布等平台工具
  2. 自动化测试

  3. 资源定位

    1. CDN
    2. 绝对路径

将 工程路径 转换为 部署路径, 把相对路径变成绝对路径并且加上md5戳和域名

css处理

  1. 使用css预编译弥补css弱编程能力,比如变量、运算、集成、模块化等
  2. 使用PostCss针对浏览器的需求,比如autoprefix
    , 自动css scprites等

工程设计步骤

前端开发体系建设日记

  1. 设计开发概念,定义开发资源的分类(模块化/非模块化)
  2. 设计开发目录,降低开发、维护成本(开发规范)
  3. 根据运维和业务要求,设计部署规范(部署规范)
  4. 设计工具,完成开发目录和部署目录的转换(开发-部署转换)
  5. 设计模块化框架,兼顾性能优化(开发框架)
  6. 扩展工具,支持开发框架的构建需求(框架构建需求)
  7. 流程整合(开发、测试、联调、上线等流程接入)

seajs会需要load完一个或是一层,分析以后才创建接下来的script请求,速度会慢很多。再者,资源依赖表的好处在于可以为加载与执行的组合提供无穷可能,包括了bigPipe,首屏加载,滚动加载这样的需求,在知道了依赖关系以后,这些特定情况就可以用js编码来完成。

前端语言缺乏三种能力

  1. 资源定位的能力:使用开发路径进行资源定位,项目发布后转换成部署路径
  2. 依赖声明的能力:声明一个资源依赖另一个资源的能力
  3. 资源嵌入的能力:把一个资源的编译内容嵌入到另一个文件中

代码发布

一般是公司内撘一个ci系统,比如jenkins,然后在上面安装运维提供的部署脚本,然后配置gitlab(通常不用github,防止泄密)的webhook,一有提交就发请求到jenkins上,jenkins拉取代码,调用fis构建,然后把产出的代码通过运维脚本推送到测试或者生产环境。大致的流程是:

  1. 内网搭建gitlab/svn
  2. 内网搭建ci系统(jenkins)
  3. 在ci系统所在机器上安装fis、运维推送脚本
  4. 配置gitlab的webhook,一有提交就发请求给jenkins
  5. jenkins中创建job,填写gitlab中的url,填写hook脚本

运行效果:

  1. 开发人员提交代码,gitlab触发webhook,推送信息到jenkins
  2. jenkins根据推送的信息执行对应的job
  3. job中的脚本clone对应的分支,调用构建工具对代码进行构建
  4. 使用运维脚本将构建完成的结果推送到测试/生产服务器。

流程:【提交代码】→【自动部署】,【自动部署】包括了【构建】+【代码推送】

关于map.json回滚

其实每次发布,都可以把构建好的代码生成一份tar包存到代码库里,生产/测试/开发环境可以自由切换任意版本的包。服务端的包自然携带了map.json,切换哪个就代表了回滚哪个。静态资源不用回滚,丢在静态资源服务器就好了

模块规范

CommonJS

  1. 只使用js静态模块化规范,适合node,不适合浏览器环境
  2. 同步阻塞时加载,无法实现按需异步加载

AMD/CMD

  1. 处理js意外的资源
  2. 无须编译即可运行
  3. 按需异步加载,并行加载
  4. 插件系统

缺点:

  1. 应用场景单一,无法跨环境
  2. 构建工具不统一
  3. 模块可复用性低,不同规范
  4. 未来不可期

ES6 Module

  1. 循环加载时,属于加载时执行,一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
  2. 动态引用,输出的是值的引用,值改变,引用也改变,即原来模块中的值改变则该加载的值也改变
  3. 满足按需加载、babel

CMD 模块定义规范

CMD规范

  1. 一个模块就是一个文件
  2. define Function
  3. define define(factory)
  4. define define(id?, deps?, factory)
  5. typeof define === "function" && define.cmd
  6. require Function
  7. require require(id)
  8. require.async require.async(id, callback?),异步加载模块
  9. require.resolve require.resolve(id),返回模块路径
  10. exports Object
  11. module Object,module 是一个对象,上面存储了与当前模块相关联的一些属性和方法。
  12. module.id String,模块的唯一标识。
  13. module.uri String,根据模块系统的路径解析规则得到的模块绝对路径。
  14. module.dependencies Array,依赖
  15. module.exports Object

注意:

// 错误用法!!!
exports = {
    foo: 'bar',
    doSomething: function() {}
};
// 正确用法

return {
    foo: 'bar',
    doSomething: function() {}
};

module.exports = {
    foo: 'bar',
    doSomething: function() {}
};

// seajs主入口

seajs.use(['./hello.js'], function(result) {
    console.log(result);
})

性能优化

前端工程与性能优化

优化方向 优化手段
请求数量 合并脚本和样式表(combo服务),CSS Sprites,拆分初始化负载,划分主域
请求带宽 开启GZip,精简JavaScript,移除重复脚本,图像优化
缓存利用 使用CDN,使用外部JavaScript和CSS,添加Expires头,减少DNS查找,配置ETag,使AjaX可缓存
页面结构 将样式表放在顶部,将脚本放在底部,尽早刷新文档的输出
代码校验 避免CSS表达式,避免重定向

非覆盖式更新

  1. 上线的a.js不是同名文件覆盖,而是文件名+hash的冗余,所以可以先上线静态资源,再上线html页面,不存在间隙问题;
  2. 遇到问题回滚版本的时候,无需回滚a.js,只须回滚页面即可;
  3. 由于静态资源版本号是文件内容的hash,因此所有静态资源可以开启永久强缓存,只有更新了内容的文件才会缓存失效,缓存利用率大增;

用户体验

  1. 保证内容的快速展现,减少用户等待时间
  2. 保证操作的流畅度
  3. 如果是移动设备,应尽量减少设备的耗电量

工程质量

  1. 单元测试
  2. 集成测试
  3. 客户端监控系统

工程开发效率

  1. 目录结构组织
  2. mock服务
  3. 动态构建:热更新、热替换

Livereload的原理:在浏览器和服务端之间创建websocket连接,服务器端在执行完动态编译后发送reload事件至浏览器,浏览器接收事件后刷新整个网页。

HMR: 以局部刷新代替整体刷新,webpack向构建输出的文件中注入了一项额外的功能模块--HMR Runtime。同时在服务端也注入了HMR Server。

  1. 修改源文件并保存,webpack监听到FileSystem Event事件并处罚重新构建
  2. 构建完成后,webpack将构建变动信息传递给HMR Server
  3. HMR Server通过WebSocket发送push信息告知HMRRUntime需要更新客户端模块,HMR Runtime随后通过HTTP获取待更新模块的内容详情
  4. 最终,HMR Runtime将更新的模块进行替换,在此过程中浏览器不会进行刷新b

工程化工具

  1. 工作流管理工具:Grunt、Gulp
  2. 构建工具:webpack、rollup
  3. 整体解决方案:fis、WeFlow

构建功能规划

  1. ES规范的转译
  2. CSS预编译器支持
  3. PostCss处理hack后缀
  4. 自动创建CSS Sprites图
  5. 图片压缩
  6. 小体积图片base64内嵌
  7. javascript模块化规范支持

环境区分

增量更新与缓存

  1. 构建出文件hash指纹
  2. 构建更新html文件对其他静态资源的引用url

http缓存策略

强缓存:先看过期没有,过期再看内容
协商缓存:直接看内容

  1. Expires和max-age

Cache-control:

  • no-cache:协商缓存
  • no-store:不缓存
  • public:无限期缓存
  • private:用户缓存、中间缓存器无效。例如html可缓存,cdn不可缓存
  • max-age:有效时长
  1. Etag和If-none-match

请求用If-none-match,响应用Etag

在no-cache或者max-age、expires过期后

覆盖更新

  1. 建立在浏览器启用强制缓存策略的情况下
  2. 往url后添加请求参数,让浏览器更新资源

缺陷:

  1. 保证html和静态资源同步更新
  2. 不利于版本回滚

增量更新

问题:

  1. 同步模块修改对异步文件和主文件hash指纹的影响
  2. 异步模块修改对主文件hash指纹的影响

结论:

  1. 同步模块的修改影响主模块的hash,不影响异步文件
  2. 异步模块的修改,影响异步文件的hash也影响主文件的hash
  3. CSS作为独立的文件,那么其修改不影响主文件,但是用ExtractTextPlugin,其相当于一个同步模块。使用contenthash(ExtractTextPlugin提供),则其修改不会对主文件js造成影响

webhook与自动构建

webhook是一种用于在服务器之间进行实时通信的策略,源服务器通过监听某种事件(git的push事件),在事件发生后发送http请求至目标服务器

持续集成、持续交付、持续部署

工作流 概念 目标群体
持续集成 强调开发人员提交代码后立即进行构建、单元测试。以确定新代码和原有代码能否正确的集成在一起 开发人员
持续交付 将集成后的代码部署到类生产环境,测试通过后,可以手动部署到生产环境 测试环境和测试人员
持续部署 在持续交付的基础上自动化部署到生产环境 生产环境和真实用户
@UNDERCOVERj UNDERCOVERj changed the title 前端工程化进阶 前端工程化阅读摘要 Dec 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant