本文包含《前端跨界开发指南》、《智能前端技术与实践》及DeepSeek等AI工具的笔记。
AI工具
SCNet人工智能助手(接入DeepSeek,免登录)
百度搜索和微信AI搜索也全面接入了DeepSeek,提供深度搜索服务。
百度AI搜索 - 办公学习一站解决(接入DeepSeek-R1满血版,可联网搜索,免登录)
文心一言
秘塔AI搜索(接入DeepSeek,免登录)
DeepSeek | 深度求索、DeepSeek 官方提示库
从抓包到 Mock,Plug 工具如何让开发更智能-原创 李滨 Goodme前端团队 :该文里探索大模型协助 Mock,文章写的很好。
当前,前端AI已广泛应用于Web性能优化、用户体验提升及个性化推荐等多个方面。前端人工智能的应用实例:智能搜索、虚拟助手、图像识别与处理、低代码/无代码平台升级等。前端AI将为用户带来更加智能化、个性化的Web应用体验。同时,我们也需要关注其面临的挑战并采取相应的应对策略(如:加强算法监管与审核,强化数据安全与隐私保护,推动技术创新与伦理治理并重)以确保其健康、可持续的发展。
在项目初期,应优先聚焦于核心产品逻辑的构建,技术选型可依据实际需求灵活调整,待明确具体技术需求后,再针对性学习相关技术栈。对于应用开发而言,通过API调用实现功能集成是较为高效的实践路径。
- 批量发票图片识别,编辑/导出Excel
展示地址:https://gitxieada.github.io/Demo/ocr/index.html
纯html代码未使用框架,具体实现可查看原代码。
主要技术栈: ocr 识别库 tesseract.js、在线表格 x-data-spreadsheet
功能:批量发票图片识别,图片查看器预览发票图片,与表格中的信息进行对比,如果识别不了/出错,则可以通过在线表格编辑/导出Excel。前端跨界开发指南
书中演示的所有源代码均可以在 https://github.com/dashnowords/imfe 找到。
涉及类目较广,挑选了感兴趣的部分阅读,扩展视野,有启发。
我们常听到“技术深度”和“技术广度”这两个词语,基础知识的积累就属于加强“技术深度”的范畴,它提升的是开发者解决问题的能力,这种技术能力在面试、技术方案评审或定位并解决问题时才会表现出价值。如果你希望自己在常规的业务开发之外承担更多复杂度较高的工作,就需要不断加强“技术深度”。通过学习和应用优秀的第三方库来了解JavaScript除了用来写页面外还能做什么。
第1章 Mock.js:如何与后端潇洒分手
Mock.js 是使用JavaScript语言生成测试数据的第三方库,它能用一套相对规范的模板语法让开发者自行定制测试数据的结构,然后根据模板生成用于测试的数据。Mock.js的语法规范可以分为数据模板定义规范和数据占位符定义规范,规范的详细内容可以在项目GitHub仓库的wiki页中查看和学习。
Mock.js支持在浏览器环境和Node.js环境中使用。在浏览器中,Mock.js既可以使用<script>
标签直接引入,也可以使用诸如require.js等符合AMD规范的包管理库进行加载;在服务端Node.js环境中,通过“npm install mockjs”命令安装依赖项并引入该模块即可。引入Mock.js后,就可以在本地Web服务中监听对应的请求并返回虚拟数据了。
如果熟悉Node.js应用开发,可以尝试编写一些自动化工具。根据后端接口文档中的定义直接自动生成Mock数据模板,从而提高工作效率。可以利用Mock.js提供的自定义扩展接口定制符合开发需求或业务逻辑的占位符。Mock.js中提供了Mock.Random.extend方法来扩展占位符,该方法作为占位符时,会从给定的枚举项中随机选取某一项来生成数据。
作为前端工程师,熟练使用某个第三方工具库只是基本要求,你需要对相关技术的基本原理、优缺点甚至未来的迭代优化方向有自己的理解,建议先尝试手动实现一些核心特征,看看自己能不能做到,然后再来阅读源码,看看工具库的作者是如何设计整体代码架构的,反思一下自己实现的那一部分与作者的实现思路是否一致,再仔细研究一下自己写不出来的那一部分,相较于阅读相关的技术博客,这种方式更能促进你快速成长。
“策略模式”是前端领域使用率较高的经典设计模式之一,使用该模式需要先定义一系列的算法,把它们封装起来,然后在使用过程中根据参数来动态选择算法,其目的是将算法的使用和算法的实现隔离开来,这样一来,使用者对于可变部分的修改和扩展就不会影响到不可变的部分,这是让代码保持“开放封闭原则”的一种有效手段。代理模式也称为Proxy模式,有时还被称为“劫持”模式,是前端使用率较高的经典设计模式中的一种,其目的是为其他对象提供一种代理机制,以控制对这个对象的访问。代理模式使用代理对象来控制具体对象的引用,代理对象几乎可以是任何对象:文件、资源、内存中的对象,或者是一些难以复制的东西。
有很多开源的API管理平台可以选择。
第2章 Node.js:连接
Node.js是一个基于Chrome V8引擎的JavaScript运行环境。Node.js使用了一个事件驱动的、非阻塞式I/O的模型,轻量又高效,它的底层是用C/C++编写的。由于Node.js底层使用的是异步非阻塞的I/O机制,因此它更适合于I/O密集、少量业务逻辑和计算消耗的场景。尽管解释型脚本语言本身并不适合执行计算型任务,但Node.js底层是由C/C++代码编写的,并且提供了JavaScript代码层与C/C++代码交互的接口,面对计算密集型任务时,Node.js只需要作为启动脚本调用底层C/C++程序来完成计算密集型任务就可以了。
Node.js的fs模块几乎为每个文件操作接口都提供了同步和异步两种方法,同时也支持以流的方式对读写过程实现更细粒度的控制,甚至还可以监测指定文件或文件夹的变动。
最流行的Express和Koa框架,仅仅提供了框架和基本中间件,要想实现更多的功能,还需要引入或者自行开发大量中间件。这时开发人员之间的差别就会表现得非常明显,即使完全不懂Node.js,后端开发人员也很清楚自己应该寻找具备日志记录、错误追踪、会话管理、安全校验、性能监控、对象关系映射(ORM)、数据库连接等功能的模块或中间件,而普通的前端开发人员却除了业务逻辑的增删改查外,往往连使用“try…catch…”语句捕获运行时错误的意识都没有。前端工程师很容易只考虑业务逻辑一切正常的情况,只要主流程能够正常运行,就觉得万事大吉了,然而在真实的开发过程中,往往是那些没有覆盖到的边界情况需要花费更多的精力。
业界用Node.js做什么:
1)前端工程化
全生命周期的自动化工具支持,除此之外,“多端编译”技术也是前端工程化领域的热门方向之一。
2)中间层
“中间层”,顾名思义就是建立在前端和后端之间的逻辑分层,最大的作用就是整合,包括整合接口、整合数据、整合逻辑,通常由前端工程师编写和实现。利用中间层来聚合接口和逻辑,就可以将复杂的逻辑链条和各个请求细节都隐藏在服务端,只为客户端暴露一个调用接口,并最终返回数据或包装后的异常信息。除了接口整合和数据清洗之外,中间层代码还可以完美胜任鉴权和会话管理、请求过滤、访问日志记录、应用接口升级等任务。
中间层的出现也是“单一职责原则”的体现,它使得整体的技术架构变得更清晰,每个环节需要承担的宏观任务类型也变得更加清晰。
3)SSR引擎
SSR是指服务端渲染(Server Side Render),其实服务端渲染并不是什么新技术,只是在Node.js的帮助下,前端工程师可以更方便地实现该技术。
除了那些对访问速度有较高要求且变化较少的项目,更多的项目仍然会采用客户端渲染的方式来实现。
SSR技术通常可用于以下几个典型场景。
1.提升首屏渲染速度
2.提升搜索引擎优化(SEO)性能
3.独立运营页面的制作
4)协作连接
为团队成员提供自动化的工具。在与后端人员进行协作时,可以使用DocLever或Rap2搭建内部API管理平台,推动更加规范的API管理工作流,以免因为API的不断变动而承担额外的工作。又或者通过在中间层提供日志来协助运维人员获得更多有针对性的信息,
前端工程师可以主动思考和优化与团队其他成员的合作方式,并将可行的实践转化为工具,提供给其他与自己工作有交集的协作者,以便在实践中逐步完善。
第3章 ESLint:你的代码里藏着你的优雅
在工程实践中你会发现,即使花费再多的精力去制定和完善编码规范,并不断组织学习和宣讲,也依然很难奢求此规范获得所有人的重视,因为在很多开发者的眼里,这属于“无关紧要的小事”。当一个人意识不到某些事情的重要性时,将事情的结果寄托在强制要求和自觉性上是一种不明智的做法。
利用各种辅助工具为团队制定编码规范。
使用ESLint规范编程风格,新秀工具Prettier。ESLint更倾向于发现和修复语言本身相关的漏洞或风险,而Prettier关注的则是格式和排版风格方面的一致性,两者各司其职。
第4章 模块演义与Require.js
模块化规范的出现,本身就是软件工程的一种诉求,它的目的是提高工程层面的可维护性,并不会直接面向业务逻辑场景。
如果<script>
标签上没有设置任何延迟执行的属性(defer或async属性),那么<script>
标签的执行就会阻塞文档对象模型(Document Object Model,即DOM对象)的解析,加载的脚本文件越多,页面完成初始化的时间就会越长,所以我们经常会看到<script>
标签被放在<body>
标签之后,这可让网站首屏的内容信息先完成解析渲染,再为页面增加交互,因为交互和逻辑能力的增加对用户而言在视觉上几乎是无感知的。
在现代化基于构建的前端工程体系中,应用程序的入口已经转移到了JavaScript中,多模块加载顺序和并发请求限制数的问题也将通过JavaScript基础工具来实现。为了满足代码隔离的基本需求,业内出现了以立即执行函数(Immediately Invoked Function Expression,IIFE)为模块包装的第一代模块化解决方案,在ES6标准之前,JavaScript只能使用函数来划分作用域,也就是说JavaScript需要借助函数来解决多人协作时的代码隔离问题。
常规的脚本在加载完成后就会自动执行,如果访问的模块还没有解析就会引发错误。如果不同模块的依赖关系非常明确,我们就可以在代码层面对这种依赖关系进行强制加载,并对执行顺序进行限制,这样做能够尽量避免环境差异带来的影响,提高代码的健壮性和稳定性,同时清晰的依赖关系也是代码优化所需要的重要信息。模块化最基本的诉求是解决代码隔离和依赖管理两大问题。
前端模块化的困难在于规范和实现的分离所带来的一系列工程层面的兼容性问题。在谈及AMD、CMD和UMD这几种模块定义规范时,事实上都只是在描述工程实践层面的约定,浏览器并没有对它们进行原生支持,因此你需要事先引入一个实现了某种模块化规范的库(AMD标准使用Require.js,CMD标准使用Sea.js),之后所引入的模块才能够被识别,相当于在运行时预制了模块化管理的代码,它并不受运行环境原生支持。UMD模块化规范,它并不是一种具体的规范,而是一种代码模式,遵循UMD规范的模块在加载时,会根据适用的API来推断当前工程所遵循的模块化规范,并以恰当的方式把封装在模块中的内容提供给引用者。
CommonJS规范(它是一个模块化规范,并不是外部类库),Node.js对CommonJS模块化规范提供了原生支持,这就意味着使用JavaScript进行服务端开发时,不需要借助任何外部类库,就可以实现模块化管理。遗憾的是,要想让浏览器识别CommonJS模块,通常还需要依赖于构建工具注入的模块加载器代码来实现。随着ES6标准的出现,JavaScript终于有了自己的模块化规范——ES Module规范,AMD规范推崇模块依赖前置,(表现上就是当前模块执行时可以通过形参来访问注入的模块)。CMD规范推崇在代码中就近编写依赖,它通过参数注入的方式为开发者提供了一个加载方法require,被依赖的模块只有在被需要时才会去解析和执行。
当代码中需要引用一个体积较大的外部依赖时,无论是采用AMD规范还是CMD规范的方式来书写,对应模块的下载都是提前进行的,区别只是解析这个模块的时机,CMD的机制通常称为“懒执行”,但由于模块解析相较于网络请求而言耗时非常短,因此这样的设计并没有表现出显著的差异。“懒加载”技术,有时也称为“分包加载”。“分包加载”是一种宏观的异步行为,它不像AMD或CMD规范中要求的那样需要提前下载依赖,然后按需解析,而是当代码执行到需要外部依赖的时候才会下载该依赖文件,这种处理方式在组件化开发的性能优化中很常见,因为它可以有效减小首屏依赖代码的体积。在CommonJS规范下,既支持具名模块导出,也支持默认模块导出。导出方式exports和module.exports会指向内存中的同一个地址,且最终导出的模块会以module.exports为准,CommonJS中加载模块使用的是require关键字,它是同步执行的,并且只能全量加载模块的导出。ES Module规范,它同样支持具名模块导出和默认模块导出这两种形式,这两种模块的导出方式可以共存但不能混用,在使用import关键字引用模块时使用的语法也不同。
模块化规范的兼容实际上是构建工具通过工程化的手段回避了模块化规范兼容性的问题。
如果流行的自动化工具链让你觉得过于复杂,难以掌握,那么你完全可以从使用Require.js开始着手来学习模块化的相关知识,以了解在模块管理和加载中需要解决的问题,以及Require.js提供的解决方案。虽然我们使用的工具在不断升级,但需要解决的软件工程问题是一致的。
“造轮子”有的时候并不是为了得到一个简陋的解决方案,而是帮助我们更好地拆分和理解所面对的问题,从而在有能力学习和研究其他流行的技术方案时,更容易明白新工具到底好在哪里,而不只是人云亦云地紧追潮流。
第5章 Lodash.js是工具,更是秘籍
一个开发者若能跳出编码的细节,从更高的角度看待问题,那么他才有可能将更多的精力用于关注代码的可读性、模块划分、用户体验、业务逻辑的合理性或者前端工程的整体架构上。每个人的时间和精力都是有限的,如果一直困在低级的琐事上,自然就会无法接触和体验相对更高级的事物,更别提领略程序设计的逻辑之美了。
Lodash.js一个具有一致性、模块化且高性能的JavaScript实用工具库。将经典代码中包含的思想和技巧内化为自己的能力。
第6章 静态类型检查:Flow.js和TypeScript
动态类型的灵活性并不是没有成本的,灵活性必然会带来编码的多样性和随意性,这无疑会增加调试和维护的难度。
静态类型的引入为语言增加了静态类型检查的能力,从而使得开发者不必运行代码就可以检测出明显的语法错误,另外,它还可以用来共享接口定义或类定义等一些公共的定义信息。这些看似多余的做法都是为了能够让JavaScript在现代前端开发中承担更多的责任,而不只是被当作一种“玩具”语言。
静态类型检查的优势:1.提前发现Bug和编码错误;2.替代部分注释信息;3.捕获重构引发的错误;4.更少却更有意义的单元测试。
静态类型检查的劣势:1.附加的学习成本;2.代码变得冗长;3.短期内可能会延缓开发的进度。
Flow.js 是Facebook出品的JavaScript静态类型检查工具。TypeScript是JavaScript的超集,它完全兼容JavaScript,并且可以通过引入更多高级特性来提高JavaScript承载大型应用的能力,但最终你编写的代码还是会被编译为JavaScript代码。
第7章 用函数描述世界:Ramda.js
“函数式编程”是一种程序设计泛式,使开发者能够把焦点从实体关系和行为逻辑转移到对于数据的映射关系这种更底层的表现上,它的抽象度更高,同时也意味着不需要绑定任何具体的业务逻辑,越具体的东西能够复用的场景就越小。
函数式编程中所传递和使用的函数必须是“纯函数”。纯函数要求函数只能依赖自己的参数,并且在执行的过程中不能有副作用,所谓副作用是指对函数作用域以外的某个数据造成了影响。不可变数据是指一个数据生成以后,就无法再发生改变了。JavaScript中,原始数据类型就是不可变的,而引用类型是可以改变的。
“深备份”是一种典型的防御性编程策略,相对来说更耗费性能,但是其可以保证对于复制结果的后续操作不会影响到原对象。在“浅备份”机制下,对于引用类型的数据,复制过程中只会复制它的引用,因此在复制出来的新对象的某个属性实际上与原对象指向的是同一份数据(而不是结构相同的两份数据),这就造成了数据间的耦合,从而可能会在其他操作中造成意料之外的影响。
操作对象类型的数据,Ramda.js和Lodash.js也提供了许多工具和方法,用于保证你的操作不会影响到源数据。
第8章 Rxjs:前端世界的“老人与海”
Rxjs (Reactive Extensions for JavaScript)即JavaScript的响应式扩展,是一个基于可观测数据流在异步编程中应用的框架,它能够帮助JavaScript开发者更好地实现响应式编程,常被集成在Angular技术栈中。
“响应式编程”有自己的适用场景,它更适合用在状态变动频繁、交互逻辑复杂或是对反馈实时性有明确要求的场景中,例如表单填写或动画的场景,只要建立起联动关系,变化就会自动传播开来;而对于上述特性并不显著的场景,强行使用“响应式编程”反而会将简单的问题复杂化。
第9章 不可变数据的制造艺术:Immer.js和Immutable.js
克隆是JavaScript中最常见的获得不可变数据的方法,常见的数组克隆方法包括Array.prototype.slice()、Array.prototype.concat(),以及ES6中加入的扩展运算符,常见的对象克隆方法是Object.assign(),它们全都遵循“浅克隆”的策略。相较于“浅克隆”,“深克隆”方式占用的空间更大、性能更差,因为它不得不递归遍历引用类型的数据。
诸如Lodash.js之类的第三方工具库提供的深克隆方法。JSON.String + JSON.parse
这组方法可以将对象转换为字符串,再由字符串生成新对象,在这个过程中无论是原始数据类型还是引用数据类型都会生成新的克隆,但它通常只被用作业务逻辑数据,因为在转换过程中只会复制对象的值,而无法对函数或特殊类型进行复制。
Immer.js是由状态管理框架MobX的作者研发的,他希望用简洁的语法来获得不可变数据。Immutable.js除了提供新的数据类型之外,同时还会提供专用的数据处理方法,方法的命名和使用方式均与Lodash保持一致,几乎不用学习就可以直接上手。如果没有Immer.js,你需要掌握ES6中Proxy和Reflect的新特性才能够获得不可变数据;如果没有Immutable.js,你需要有扎实的数据结构基础知识和算法知识才有可能设计出想要的结构。
我们需要学习应用层的编程技术,但也必须意识到不是所有的问题都可以依赖应用层技术和开发经验来解决,当面对一个找不到通用解决方案的难题时,考验的永远都是开发者的基本功和解决问题的能力。
第10章 Day.js:算个日期能有多难
Day.js 是一个同时支持浏览器环境和Node.js环境的日期时间处理库,它和moment.js保持了一致的API,不同的是,Day.js采用了“不可变对象”的形式来处理日期和时间,并且只保存了核心能力,而将一部分功能降级为插件的形式供开发者选择,这使得它在不引入跨语言扩展包的情况下,总体积大小只有2KB,可以说是非常轻量级的了。
所谓“不可变对象”,是指调用API后返回的对象总是全新的,不会影响其他对象,也就是遵循着之前学习过的“Immutable Data”的理念。
第11章 所见即所得的流程图:jsplumb.js和viz.js
jsplumb.js的官方网站 提供了大量的展示范例(demo),可以很直观地查看它们是否能够满足自己所面对的开发场景。jsplumb.js分为Community(社区版)和Toolkit(正式版)两个不同的版本,社区版是一个免费的开源项目。
图布局引擎viz.jsjsplumb.js的社区版是不包含自动化布局特性的,所以开发者通常会引入dagre (稳定的有向图布局工具)或功能更丰富的viz.js (著名的自动化布局工具graphviz 的JavaScript封装,以下直接称viz.js),来实现流程图的自动化布局。
第12章 easel.js:一个标签一个世界
Canvas提供了强大的图形图像操作功能,但原生的Canvas API带有明显的面向过程编程的特点,无论是图元管理还是代码维护都比较烦琐,easel.js提供了丰富的语义化的API和交互解决方案,能够优雅地实现对象分层管理、事件机制、链式调用等功能,其作为游戏开发整体解决方案CreateJS的组成部分,所有的API都挂载在createjs命名空间下。
第13章 Echarts.js:看见
D3.js和Echarts.js很像原生JavaScript和现代SPA开发框架的关系。D3.js的API相对偏底层,这意味着它拥有更好的性能、定制自由度和可扩展性,但使用起来也更为烦琐复杂,这样的特性使它更适合用于定制度较高的专业可视化领域,相比之下,Echarts.js的易用性要高出好几个数量级。
第14章 SVG变形记
SVG(Scalable Vector Graphics,可伸缩矢量图形)是使用XML格式定义的图形。它的实用工具库Snap.svg。技术的选型一定是由需求场景决定的。如果仅仅是为了实现一些酷炫的特效,善用CSS和原生SVG也许就能应付大多数需求。
第15章 Three.js:构建立体的用户界面
Three.js 是用于实现前端图形学开发的工具库,开发者不需要有WebGL原生编程或者矩阵计算的知识,就可以在浏览器环境中直接开始构建三维模型或者实现一些动画和仿真操作。Impress.js 是利用JavaScript来实现幻灯片制作的工具库(当然,它并不是唯一的,Reveal.js 也是非常优秀的工具库,只是它们的侧重点有所不同)。
第17章 Velocity.js与高性能动画之谜
CSS动画通常是指transition属性实现的过渡动画以及使用animation属性实现的“关键帧动画”。JavaScript动画也不仅仅是指用脚本来动态控制元素类名实现对CSS动画的调度,我们可以将整个动画的控制权交给JavaScript从而获得更加精细的控制能力。
在CSS的简洁性和JavaScript的动态控制能力之间找到平衡点。
CSS动画可以使用著名的animate.css预设动画库,其通过类名定义提供了很多“开箱即用”的动画效果。而JavaScript动画则可以借助于Velocity.js来实现
第18章 扭曲时间:tween.js和jQuery Easing Plugin
缓动函数的作用可不仅仅是用来增加动效的仿真程度的,它还可以通过改变动画的节奏来对用户的体验产生直接的影响。18.3 使用Tween.js和jQuery Easing Plugin
CSS动画可以使用cubic-bezier函数生成三阶贝赛尔曲线来作为时间函数,但通常很难直接写出准确的控制点位置,这时既可以通过 https://cubic-bezier.com 网站以可视化的方式来调出满意的参数,也可以翻看一些流行动画库的源码,直接把它们使用的有类似效果的贝赛尔曲线参数复制过来。
常用的缓动函数速查网站是 http://easings.net 。tween.js是前端动画解决方案CreateJS中的组成部分,需要配合之前介绍过的Canvas操作库easel.js使用,它操作的对象是easel.js定义的图形实例,tween.js提供了完整的逐帧动画、缓动函数以及事件通知机制。在常规的应用开发中,动画库更多地是使用velocity.js,其官方文档示例中建议集成jQuery Easing Plugin 缓动函数库,并在使用时直接传入名称关键词。
第19章 用Recorder.js实现语音信号处理
Recorder.js提供的官方示例可以让我们播放自己的录音并拿到wav格式的输出文件;用于音频处理的AudioContext对象,它的构造函数可以接收一个配置项,开发者只需要在其中传入自定义的sampleRate值就可以修改原始采样率了。Web环境中音频和视频的采集是通过WebRTC(Web Real-Time Communication,网页即时通信)技术实现的,
浏览器环境采用Web Audio API 来实现丰富且强大的音频处理功能。
第20章 jsmpeg.js流媒体播放器
如果你的目的仅仅是在浏览器环境中播放不同格式的视频,那么大多数时候直接使用video.js 和它的官方扩展插件就可以了,只需要在初始化播放器时传入一些定制参数。
如果将原生<video>
标签的src属性直接指向m3u8的索引或是TS媒体文件,就会发现浏览器并不能直接识别它们,现代化的浏览器中使用的视频播放技术称为Media Source Extensions(MSE,媒体源扩展),它是W3C为浏览器提供的多媒体能力扩展技术。在实际应用中,开发者使用的仍然是<video>
标签,但其src属性并不会指向某个固定的静态资源,而是指向通过JavaScript创建的MediaSource对象包装成的虚拟URL地址。当资源无法直接被MSE播放时,既可以调整播放器,也可以调整资源格式,调整资源格式时,既可以在客户端进行也可以在服务端进行,至于具体方案的选择,就要根据实际场景和需求进行分析和评估了。
jsmpeg.js ,其使用mpeg1video标准进行视频编解码,使用mp2标准进行音频编解码(当然它也强制要求多媒体资源使用这样的编码方式),并依据MPEG2-TS标准进行传输,客户端的TS“解复用”和多媒体解码全部使用JavaScript完成,最后使用Canvas和WebGL技术构造渲染器来完成画面的逐帧渲染,同时利用WebAudio API播放解码后的音频。
jsmpeg.js在一些低端浏览器中是非常消耗性能的,基于JavaScript的解码器和基于Canvas的渲染引擎所承担的任务量是非常大的,而JavaScript本身是一种解释型语言,在性能方面存在天生的弱势。在较高版本的浏览器中,jsmpeg.js可以使用基于WebAssembly的解码器,它将C语言实现的原生解码模块编译为WebAssembly模块,从而在JavaScript环境中执行,以此来提高密集型计算任务的处理速度。同时,在支持WebGL的浏览器中,使用纹理来实现画面渲染将具有更高的效率,因为它可以借助纹理系统和GPU并行计算的特点来提高像素颜色信息的处理速度,即便是参考已有的技术方案,高性能播放器的实现过程也是非常复杂的。
jsmpeg.js的一个非常典型的应用场景就是安防监控领域,监控摄像头的画面通常是基于RTSP(Real Time Streaming Protocol,实时流传输协议)进行传输的。
浏览器中无法直接解析RTSP。一种很流行的方式是使用Nginx及其nginx-rtmp-module模块来启用一个流媒体服务,然后使用ffmpeg将RTSP码流推送至对应端口,并由Nginx将RTSP码流转换为浏览器更容易识别的RTMP(Real Time Messaging Protocol,实时消息传输协议)码流,最后在客户端连接拉流端口获取视频画面。
第21章 “懒”是第一生产力:制作命令行工具
使用Commander.js 制作的命令行工具称为Git风格命令行工具,它通过“主命令+子命令+参数”的模式来实现输入采集,只需要实现业务功能相关的命令定义即可,Commander会自动添加对“-h, –help”参数的响应,并罗列出所有自定义的子命令、配置参数和示例代码等,与你在命令行输入“git –help”命令后看到的信息一样。
对于一些使用频率较低、配置参数较多的命令,开发者很难长时间准确记忆每个参数的用法,这时就可以借助交互式命令行工具来获得更好的体验,其使用问答的模式来收集命令参数。使用Inquirer.js 在终端界面上构建的交互式的命令行工具。
工具本身只是一种载体而不是最终的目的,它所承载的是前端工程化建设中沉淀出来的解决方案、协作规范和开发工作流。好的工具不仅可以提高开发效率并协助规范落地,同时也会在工作流的关键节点上设置门禁,为工程质量提供强制保障。
前端工程化建设的方向,基础建设越完备,业务开发人员的知识水平对项目的影响就越小,整体的用人成本也可以有效降低。
第22章 用Shelljs实现自动化部署
Shelljs将Node底层丰富的系统级操作API封装起来,对外提供了与Shell命令一致的语法,借助Node天然的跨平台运行能力,使得前端开发者可以不依赖任何其他工具而直接使用最熟悉的JavaScript来编写Shell脚本并实现跨平台的运行。开发者通常会使用SSH工具来连接远程服务器,可选的工具软件也非常多,笔者常用的是MobaXterm。当你对Linux的相关命令不够熟悉时,可以利用支持FTP(File Transfer Protocol,文件传输协议)的工具来实现此需求,MobaXterm也可以用来建立FTP连接。除此之外,文件传输常用的软件还有WinSCP和FileZilla,它们几乎全都支持批量选择和鼠标拖曳,上手难度很低。
Cmder 可以算是Windows命令行工具的加强版,它不仅有更加美观的UI样式,还增加了对Linux命令和Tab式多窗口的支持,完整版的Cmder集成了git命令行,它可以让开发者在Windows系统中使用Linux命令。
cross-env 是一个很小的NPM(Node Package Manager,Node.js的包管理器)包,这就意味着它本质上是一个Node.js脚本,可以用来解决跨平台设置和使用环境变量的问题
Shelljs,是基于node API实现的可以在Windows、Linux和Mac OS三大系统中使用的Shell工具,在Shelljs的帮助下,可以使用JavaScript代码来编写Shell脚本,并且各个平台都可以通过“node [scriptname].js”
或是“npm scripts”
的方式来运行这个脚本文件,从而解除了跨平台的困扰。
PM2是基于Node.js开发的,除了支持守护进程之外,它还支持多应用管理、集群管理、Hook自动化更新等许多功能,不仅方便易用,对于刚开始接触服务端部署和工程化的前端开发者来说它也是非常好的入门工具。在Windows系统中编写Shell脚本的另一个问题是回车换行符,Windows系统中回车键会输入CRLF(表示回车并换行),而Linux系统中敲回车键会输入LF(表示换行),这虽然看起来是个小问题,但的确有可能导致在Windows系统中编写的Shell脚本在Linux机器上无法正常运行,开发人员在定位问题时需要多加注意。
第23章 跨端技术的秘密
Cordova以移动端原生的WebView控件作为应用的容器,将前端技术开发的Web应用在移动端展示出来,同时它还向应用层提供了一组与设备相关的API,这样开发者就可以在JavaScript中调用智能设备的加速度传感器、摄像头、网络通信、本地通知、本地存储等原生能力了。跨平台技术的初衷就是以牺牲性能为代价来换取更高的开发效率。
React Native(后文简称RN)是由Facebook于2015年4月开源的跨平台移动应用框架,它可能是目前使用最广的跨平台开发技术。由于架构和渲染机制的不同,使用RN开发的应用的确比使用Cordova开发的应用更加流畅,使用体验也更加接近于原生开发。但性能的提升是有代价的,一个RN项目通常需要Web开发者、Android工程师和iOS工程师互相协作才能够达到较好的效果。React Native对独立开发者而言不够友好,它更适合于对用户体验有一定诉求且人员结构多样化的团队来使用。
建议在选用一项技术之前做好评估工作,它的优势是大家都希望借助的,但它的风险和代价却不是每个团队都能承担的。
如果你不介意自己的应用程序依附于第三方平台而存在,甚至本来就需要依赖平台方的流量扶持,那么笔者认为小程序可能是目前最好的选择。它对于前端开发者而言上手难度最低,且天生具备跨平台能力。
在个人和小型项目中优先选择小程序或Cordova,节省自己在技术细节上花费的精力,从而用更多的时间去思考产品和业务本身,那才是我们在商业活动中追求的价值,从这个维度上看,技术只不过是价值的一种承载方式罢了。在有强大团队支持的情况下可以考虑其他跨平台方案,这样即便遇到障碍,也不至于给项目的交付带来过高的风险,如果对应用性能有诉求且时间充裕,也可以直接选择原生开发。
第24章 protobuf与二进制消息
在为不同的场景设计通信方案时,通信协议和数据交换格式都是可以灵活选择的,一些看似微不足道的优化和选择可能会随着通信量的增大而最终产生差异巨大的结果。
protobuf格式 全称为Protocol Buffers,是Google推出的一种基于二进制编码的跨语言、跨平台、易扩展的数据交换格式,广泛应用于服务端通信等场景,其设计初衷也是为了将结构化的数据转换为序列化的数据,以便在通信传输中使用。protobuf为常见的服务端开发语言提供了运行时的支持,可以通过它的官方代码仓库 进行了解。
protobuf并不是唯一的选择,Facebook推出的Thrift也是一种二进制通信协议,它们都可以在大规模的跨语言服务开发场景中使用。与Web开发领域常用的表单、XML和JSON等数据交换格式相比,使用二进制编码后的消息体积更小且其编码速度更快,代价就是使用流程比较烦琐且编码后的消息几乎丧失了可读性。protobuf格式在使用时通常遵循如下几个步骤:首先将接口声明编写在扩展名为“.proto”的文件中,它拥有自己的语法,接着使用编译器来生成指定语言可以访问的消息读写类,最后在自己的程序中引用对应语言的运行时库和消息读写类来使用编解码函数。从protobuf的官方代码仓库 中下载对应平台的编译工具protoc,将解压后目录中bin文件夹的绝对路径添加到环境变量的Path变量中,之后就可以在命令行工具中使用protoc命令来编译.proto文件了。在Node.js程序中使用protobuf时,需要引用官方提供的运行时依赖google-protobuf(直接使用npm安装即可),但并不需要对其进行显式引用。
protobuf.js 是一个基于JavaScript二进制数据处理能力实现的运行时框架,这就表示并不需要提前编译proto文件,而是可以在运行时直接加载和使用。
它可以同时支持浏览器和Node.js环境,除此之外,还可以在TypeScript中使用,其引入的方式与其他库并没有什么不同。
proto文件的编写通常是以接口为粒度来进行的,如果想在客户端使用,可以使用官方提供的命令行工具pbjs来进行预处理,它可以在打包构建环节将存放在前端工程中的proto文件打包成.json或*.js文件,相当于提前进行了加载环节的处理,等到运行时直接在JavaScript运行环境中使用加载后的结果就可以了。
如果我们的目的是实现统一的接口管理,那么只需要将proto文件编译输出为TypeScript能够识别的接口定义就可以了,这样不仅能够在编码时享受到IDE的智能提示,实现对接口所需数据的校验,而且不用担心增加最终打包文件的体积。
RPC(Remote Procedure Call)即远程过程调用,这里的远程并不一定是指运行在不同机器上的程序,即使是运行在同一台机器上不同进程里的程序,也会由于资源隔离的机制而无法直接调用另一个进程中定义的函数。而RPC提供的功能就是将本地函数的调用映射为对另一个进程中的同名函数的调用,它可以隐藏更多的通信细节,让应用层的代码具有更自然的语义性。需要注意的是,RPC调用只是一种接口风格,它并没有绑定具体的实现方式,与“高性能”也没有必然的联系。gRPC 是Google在protobuf格式的基础上推出的高性能开源RPC框架,它同样具备跨平台和跨语言的特点。目前主要应用于服务端通信场景中。
第25章 控制反转与Inversify.js
初级开发者在编程时千万不要只满足于实现眼前的需求,而是应该多思考如何降低需求变动可能对自己造成的影响,甚至是如何直接通过“控制反转”将细节定制的环节以配置文件的形式提供给产品人员。软件工程师的任务是设计软件,让软件和可复用的模块帮助自己实现需求。25.4 用Inversify.js实现依赖注入
Inversify.js 提供了更加完备的依赖注入实现方法,它是使用TypeScript语言编写的。25.5 小结
作为软件工程师,我们需要了解技术背后的原理和思想,以便扩展自己的思维,但对技术的敬畏之心不应该演变成对高级技术的盲目崇拜。“依赖注入”不过是设计模式中的一种,模式总会有它适合或不适合的使用场景,常用的设计模式还有很多,经典的设计思想也有很多,只有灵活运用才能让自己在代码结构组织的工作上游刃有余。
第29章 brain.js:写给前端的神经网络入门课
brain.js 是一个支持GPU加速的神经网络框架,在浏览器和Node.js应用中都可以使用。它的API基于神经网络算法设计的,使用时只需要依次调用构建(new)、训练(train)和运行(run)就可以了,非常简洁。
人工智能领域的复杂度不同于软件技术的工程复杂度,想要深入研究,至少需要具备过硬的数学基础、英文文献阅读能力,掌握人工智能领域知识以及科学研究的基本方法,如果没有相关的基础知识,很容易出现一系列自己完全没有办法解决的问题,但这些问题在行业里可能早就有了通用的解决方案。
作为前端工程师,我们只需要了解其基本原理和适用场景,在必要的时候知道该找什么盟友合作即可,不建议花费大量时间和精力去进行相关领域的研究。
第30章 TensorFlow.js:开箱即用的深度学习工具
TensorFlow 是Google推出的开源机器学习框架,其针对浏览器、移动端、IoT设备及大型生产环境均提供了相应的扩展解决方案。TensorFlow.js是JavaScript语言版本的扩展,在它的支持下,前端开发者可以直接在浏览器环境中实现深度学习的功能。浏览器环境在构建交互型应用的方面有着天然的优势,而端侧机器学习不仅可以分担部分云端的计算压力,也具有更好的隐私性,同时还可以借助Node.js在服务端继续使用JavaScript进行开发,这对于前端开发者而言非常友好。
第31章 用JavaScript玩转物联网
入门级物联网“玩具”Arduino。
串行接口通信,简称串口通信,是计算机和其外设之间常用的接口通信方式,也是IOT领域应用非常广泛的通信方式,USB通信协议也是串口协议的一种。许多常见的工业级硬件设备都会同时支持网络请求和串口通信等不同的方式来获取数据,从而适配不同的场景需求。JavaScript的开发者可以使用serialport 模块来实现串口通信,serialport模块提供的各种不同的转换器可以帮助开发者以特定的格式解析串口通信数据。
Johnny-Five 平台是一个使用JavaScript进行机器人和IOT开发的辅助模块,Johnny-Five的主要目的是提高IOT控制程序的可扩展性和跨平台移植性。Johnny-Five很难应对一些对软件系统实时性要求较高的场合,例如飞行器控制或是实时图像传输等场景,对于实验室中以原型设计为目的的开发,Johnny-Five是完全可以胜任的。
智能前端技术与实践
本书首先介绍了相关的开发环境、前端开发基础知识、深度学习基础知识、前端智能框架和卷积神经网络,然后讲述了线性回归、logistical回归、XOR问题、人体姿态检测、目标检测、光学字符识别等方面的案例,最后讲解了前端智能化案例。
快速过了一遍,写的一般,后续如果有需求要做相关项目再仔细看看。
开发环境配置
需要的开发环境,包括Anaconda3、TensorFlow 2、npm包管理工具、TensorFlow.js相关包、WebStorm工具及Google浏览器和微信开发者工具等。如果你在安装Anaconda3时遇到下载速度过慢的问题,推荐使用Anaconda3的清华镜像来完成安装
具体安装方法请自行搜索(建议使用镜像安装)。
前端开发基础
该章比较基础,一些JavaScript API等知识建议查看官网。
深度学习中支持的JavaScript数据类型是TypedArray,它是一种介于原始数组与NDArray之间的数据结构。
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区,它是一个字节数组。由于ArrayBuffer仅仅是内存上的二进制缓冲区,因此它并不提供任何操作数据(读取数据、写入数据)的方法,即我们并不能直接操作ArrayBuffer的内容,而要通过TypedArray或DataView对象来操作。
在 Web 浏览器或微信小程序中部署机器学习应用时,经常会采用从服务器端加载现成的JavaScript模型或转换TensorFlow模型这两种方法。JavaScript语言采用的是单线程模型,所以对于网络 I/O 请求等一些耗时较长的任务,通常会通过设置回调函数、使用 Promise对象、使用async/await函数来处理。
深度学习概述
由于GPU设备价格昂贵,因此对于大部分个人开发者来说,云端深度学习环境往往是首选。
免费提供算力的云端环境:Kaggle Kernel云端环境、Google Colab云端环境、阿里云天池云端环境、百度AI Studio。
深度学习领域中常用的深度学习框架,包括MindSpore(华为开源自研AI框架)、PaddlePaddle(百度开源)、NCNN(腾讯优图实验室)、Caffe(贾扬清)、MXNet(亚马逊)、Keras(谷歌)、PyTorch(Meta)及TensorFlow(谷歌)等。
TensorFlow 2.0的相关基础知识,包括TensorFlow的数据类型、数值精度、操作和计算图、自动微分和梯度带及广播机制等。深度学习的相关基础知识,包括BP神经网络、激活函数、softmax函数、损失函数、梯度下降算法和反向传播等。
TensorFlow.js框架详解
TensorFlow具有多种语言可用的API,包括Python版本、JavaScript版本、C++版本、Java版本、Go版本、Swift版本,可用于构建和执行图,Python版本的API目前是最完整和最容易使用的,但其他语言的API可能更容易集成到实际项目中,并在图执行方面提供一些性能优势。
TensorFlow.js中的API分为以下6类。TensorFlow.js Core:用于实现神经网络和数值计算的低阶API。TensorFlow.js Layers:用于实现类似于Keras功能的高阶API。TensorFlow.js Data:用于准备和加载与tf.data数据类似的简单API。TensorFlow.js Converter:用于将TensorFlow保存的模型转换成TensorFlow.js模型。TensorFlow.js Vis:用于在浏览器中将TensorFlow.js模型转换成可视化的库。TensorFlow.js AutoML:用于加载和运行由AutoML边缘设备生成的模型API集合。
注意,TensorFlow.js包括以下6个部分。TensorFlow.js CPU Backend:用于Node.js和浏览器的纯JavaScript后端。TensorFlow.js WebGL Backend:用于浏览器的WebGL后端。TensorFlow.js WASM Backend:用于浏览器的WebAssembly后端。TensorFlow.js WebGPU:用于浏览器的WebGPU后端。TensorFlow.js Node:通过TensorFlow C++版本适配的Node.js平台。TensorFlow.js React Native:通过expo-gl适配的React Native平台。
卷积神经网络
卷积神经网络(Convolutional Neural Network,CNN)是一类包含卷积运算且具有深度结构的前馈神经网络,是深度学习的代表算法之一,被广泛应用于计算机视觉、自然语言处理等领域。标准的卷积神经网络由输入层、卷积层和池化层及全连接层组成,其核心思想包括局部感知野和参数共享。
轻量级的卷积神经网络:SqueezeNet、MobileNetV1、ShuffleNetV1和Xception。
实战
在Web项目中,我们可以通过以下3种方式开发机器学习应用。运行现有模型:在大多数实际应用场景中,我们经常将Python版本的TensorFlow深度学习模型转换成TensorFlow.js Layers格式,并在Web项目中进行加载。重新训练现有模型:使用自己的数据集来重新训练现有的机器学习模型。使用JavaScript开发机器学习模型:使用TensorFlow.js官方提供的API直接构建和训练模型。
好用的OCR工具,包括百度OCR、tesserocr和万维易源数据平台。
Google官方开发的有趣的人工智能应用,其中包括恶意评论检测、微信同声传译、Google面馆、猜画小歌、Face Touch Monitor、Invisibility Cloak和Teachable Machine等。