Friday, November 12, 2021

SegmentFault 最新的文章

SegmentFault 最新的文章


前端架构师神技,三招统一代码风格(一文讲透)

Posted: 11 Nov 2021 06:41 PM PST

本文从代码规范,代码检查,代码格式化,以及编辑器自动化实现的方向,介绍代码规范统一在我们团队的实践应用。

大纲预览

本文介绍的内容包括以下方面:

  • 认识代码规范
  • 制定和统一规范
  • 神技一:ESLint
  • 神技二:Prettier
  • 神技三:VSCode
  • 附录:命名和项目结构规范

认识代码规范

先来思考两个问题:

  1. 什么是代码规范?
  2. 为什么需要代码规范?

如果你是一个经验丰富的前端开发,你一定接触过这样的老项目:变量名是 abcfds 这种随意起的,或者是 name1, name2 这种带数字起名,这样的变量不加注释,鬼都不知道它是干什么的。

这类代码就是一种典型的不规范代码。这样的代码除了让我们开发人员情绪暴躁,最重要的问题是,它极大的降低了团队协作的效率和程序质量。

在团队协作过程中,当组内其他人需要使用或 review 你的代码,看到这种情况,除了喷你,还要花费大量时间了解你写的是什么。同时这样非常容易造成变量冲突,带来未知隐患,调试困难等问题,甚至可以看出一个程序员的编码态度和专业程度。

当然,代码规范包含很多方面,变量命名规范只是最基础的规范。不规范的地方越多,程序质量越低,团队协作的效率也就会越低。

了解了不规范的代码以及不规范代码带来的问题,作为前端架构师,我们就要思考三个问题:

  1. 如何制定规范?
  2. 如何统一团队的规范?
  3. 如何检测规范?

制定和统一规范

像上面给变量随意乱起名字的情况,在早期的前端项目中非常常见。

因为早期项目规模,团队规模有限,没有命名规范这种意识,随意起名貌似也没有太大的问题,只要不重复就好。但是随着前端项目规模越来越大,复杂度越来越高,不规范带来的问题越来越多,这种规范意识才慢慢的被重视起来。

经过社区的不断发展,协定了命名包含以下几种规范:

  • 下划线命名:user_name
  • 中划线命名:user-name
  • 小驼峰命名:userName
  • 大驼峰命名:UserName

有了这些规范,开发者们起名字的时候心里就有谱了。而且这些规范目前也被大多数开发者们接受,如果不按照规范命名,很可能会被同事吐槽喽!

当规范成为普遍共识之后,大家按照自己的喜好使用不同的规范,逐渐形成了自己的编码习惯。在一个团队中,每个开发者往往各自有各自的编码习惯。

然而这又成为了问题。再拿变量举例:一个团队中,有的人习惯用下划线命名变量,如 user_name;有的人习惯用驼峰命名变量,如 userName。这两种命名方式都正确,都符合规范,但是会造成团队的代码风格混乱,无法统一。

那为什么要统一呢?

统一的好处有很多。比如我们统一规定:命名变量用下划线,命名方法用小驼峰。那么在团队协作时,大家看到下划线就知道这是一个变量,看到小驼峰就知道这是一个方法。十个人的代码写出来是一个人的风格,不需要了解其他的编码风格,实现无障碍协作。

十个人的代码写出一个人的风格,说起来很理想,但是靠监督和自觉实现几乎是不可能的。

怎么办呢?下面就是本文重点:祭出实现代码规范的三招神技

神技一:ESLint

上面说到,团队协作开发项目,由于每个人的编码习惯不同,会写出各种各样的代码。这样的代码又乱又难以维护。

所以我们希望有这样一个工具,可以制定一套比较完整全面的规范,如果大家的编码不符合规范,程序就会警告甚至报错,用这种工具来倒逼团队成员遵守统一的代码风格。

这个工具是有的,我们都听过,就是大名鼎鼎的 ESLint

ESLint 有两种能力:

  • 检查代码质量,如是否有已定义但未使用的变量。
  • 检查代码风格,换行,引号,缩进等相关的规范。

这两种能力几乎涵盖了绝大部分代码规范,并且具体规范是可配置的,团队可以定制自己喜欢的代码风格。

定制规范后,项目运行或热更新时,ESLint 就会自动检查代码是否符合规范。

:ESLint 检查与 TypeScript 检查有啥区别?

TypeScript 只会检查类型错误,而 ESLint 会检查风格错误

尝试 ESLint

首先在项目下安装:

$ npm install eslint --save-dev

然后运行命令初始化配置:eslint --init

eslint 是一个交互式命令,可以上下切换选择适合项目的选项;完成会生成 .eslintrc.json 文件。

基本配置

.eslintrc.json 的基本配置如下:

{   "env": {     "browser": true,     "es2021": true,   },   "extends": [     "eslint:recommended"   ],   "parserOptions": {     "ecmaVersion": 12,     "sourceType": "module",   },   "rules": {}, };

这个基本配置包含了一套默认推荐的配置,定义在 eslint:recommended 这个扩展中。

React 配置

React 在默认配置的基础上,也有一套推荐的语法配置,定义在 plugin:react/recommended 这个插件中,如果你的前端框架是 React,要定义 eslint 规范,那么在基本配置上添加下面标记 + 号的配置即可:

{   "env": {     "browser": true,     "es2021": true   },   "extends": [     "eslint:recommended", +   "plugin:react/recommended"   ],   "parserOptions": { +   "ecmaFeatures": { +     "jsx": true +   },     "ecmaVersion": 12,     "sourceType": "module"   }, + "plugins": [ +   "react" + ],   "rules": {   } };

React + TS 配置

若要 React 支持 TS,还要加一些额外配置:

{   "env": {     "browser": true,     "es2021": true   },   "extends": [     "eslint:recommended",     "plugin:react/recommended" +   "plugin:@typescript-eslint/recommended"   ], + "parser": "@typescript-eslint/parser",   "parserOptions": {     "ecmaFeatures": {       "jsx": true     },     "ecmaVersion": 12,     "sourceType": "module"   },   "plugins": [     "react", +   "@typescript-eslint"   ],   "rules": {   } };

代码检查

上面定义好规范之后,我们现在来写一段代码,并执行规范检查。

新建 index.js 文件,写入内容:

const a = '13' function add() {   return '1' }

从 js 角度讲,这两行代码是没问题的。然后我们运行检查命令:

$ npx eslint index.js

这时会在控制台看到报错:

2:7   error  'a' is assigned a value but never used  no-unused-vars 4:10  error  'add' is defined but never used         no-unused-vars  2 problems (2 errors, 0 warnings)

错误的意思是变量 a 和函数 add 已声明但未使用,说明代码不符合约定的规范。这种异常也很常见,在脚手架构建的项目中使用 npm run devnpm start 时就会执行上面的检查命令。

ESLint 规范

上面说过,ESLint 可以自定义检查规范,规范定义在 .eslintrc.json 配置文件的 rules 对象下。

比如,定义规范,字符串必须使用双引号:

{   "rules": {     "quotes": ["error", "double"]   } }

定义好之后,如果你的代码中字符串使用单引号,ESLint 就会报错。

quotes 表示引号规范,是众多规范中的一个,它的值是一个数组。

数组第一项是错误级别,是以下 3 个值之一:

  • "off" or 0 - 关闭规范
  • "warn" or 1 - 警告级别规范
  • "error" or 2 - 错误级别规范

数组第二项才是真正的规范,具体完整的规范参考 这里

打开上面的网页,打绿钩的表示是已配置的。需要自定义直接写在 rules 里即可。

神技二:Prettier

上一步我们用 ESLint 实现了规范的制定和检查。当开发人员完成一段代码保存时,项目会自动执行 eslint 检查命令检查代码,检查到异常后输出的控制台,待开发人员修复异常后才能继续开发。

如果你配置的编码规范比较复杂和严格,比如字符串必须单引号,代码结尾必须用分号,换行必须是 2 个 tab 且不可以用空格。像这种很细的规范,大家开发过程中难免会有不符合,这个时候控制台就会频繁报错,开发人员就会频繁修复一个空格一个标点符号,时间久了异常烦人。

正因为如此,在脚手架生成的项目中虽然默认都开启了 ESLint,但是很多人使用不久后觉得烦人,效率低下,所以都手动关闭了 ESLint。

那么,有没有更高效的方法,让大家非常快捷的写出完全符合规范的代码呢?

有,它便是第二招神技:Prettier

Prettier 是当前最流行的代码格式化工具,它最主要的作用就是格式化代码。

什么是格式化?上面我们用 ESLint 定制了编码规范,当检测到不规范的代码,提示异常,然后需要我们开发人员按照提示手动修复不规范的地方。

而格式化的威力,是将不规范的代码,按照规范一键自动修复

听起来很振奋人心,我们来试一下。

首先在项目下安装:

$ npm install prettier --save-dev

然后新建 .prettierrc.json 文件:

{   "singleQuote": true,   "semi": true }

这个配置文件和上面 ESLint 下的 rules 配置作用一致,就是定义代码规范 ——— 没错,Prettier 也支持定义规范,然后根据规范格式化代码。

列一下 Prettier 的常用规范配置:

{   "singleQuote": true, // 是否单引号   "semi": false, // 声明结尾使用分号(默认true)   "printWidth": 100, // 一行的字符数,超过会换行(默认80)   "tabWidth": 2, // 每个tab相当于多少个空格(默认2)   "useTabs": true, // 是否使用tab进行缩进(默认false)   "trailingComma": "all", // 多行使用拖尾逗号(默认none)   "bracketSpacing": true, // 对象字面量的大括号间使用空格(默认true)   "jsxBracketSameLine": false, // 多行JSX中的>放置在最后一行的结尾,而不是另起一行(默认false)   "arrowParens": "avoid" // 只有一个参数的箭头函数的参数是否带圆括号(默认avoid) }

定义好配置后,我们在 index.js 文件中写入内容:

const a = "13" function add() {   return "1" }

然后在终端运行格式化命令:

$ npx prettier --write index.js

格式化之后,再看 index.js 文件变成了这样:

const a = '13'; function add() {   return '1'; }

看到变化了吧,双引号自动变成了单引号,行结尾自动加了分号,刚好与配置文件中定义的规范一致。

喜大普奔!终于不用再手动修复不规范的代码了,一个命令就能搞定!

上面是格式化一个文件,当然也支持批量格式化文件。批量格式化通过模糊匹配查找文件,比较常用,建议定义在 script 脚本中,如下:

// package.json "scripts": {   "format": "prettier --write \"src/**/*.js\" \"src/**/*.ts\"", }

Prettier 还支持针对不同后缀的文件设置不同的代码规范,如下:

{   "semi": false,   "overrides": [     {       "files": "*.test.js",       "options": {         "semi": true       }     },     {       "files": ["*.json"],       "options": {         "parser": "json-stringify"       }     }   ] }

:ESLint 与 Prettier 有啥区别?

相同点:都可以定义一套代码规范。

不同点:ESLint 会在检查时对不规范的代码提示错误;而 Prettier 会直接按照规范格式化代码。

所以,ESLint 和 Prettier 定义的规范要一致,不能冲突

神技三:VSCode

上面,我们通过 ESLint 和 Prettier 两招神技,实现了代码规范制定,代码规范检查,以及根据规范一个命令格式化代码,使得统一团队代码风格变的非常容易。

然而,突破效率的挑战是没有极限的。这时候又有小伙伴发声了:虽然是容易了,但是检查代码还是得依赖检查命令,格式化代码也得依赖格式化命令,这样总显得不够优雅。

好吧,不够优雅,那还有优雅的解决方案吗?

答案是有。它就是我们的第三招神技 —— VSCode

强大的插件

VSCode 对我们前端来说都不陌生,是我们日日相伴的开发武器。当前 VSCode 几乎统一了前端圈的编辑器,功能强大,倍受好评。

既然能得到如此广泛的认可,那么就必然有它的优越性。VSCode 除了轻量启动速度快,最强大的是其丰富多样的插件,能满足不用使用者各种各样的需求。

在众多插件中,ESLint 就是非常强大的一个。没错,这个插件就是我们前面说到的神技第一招 ESLint 在 VSCode 上支持的同名插件。截图如下:

image.png

安装了这个插件之后,之前需要在终端执行 eslint 命令才能检查出来的异常,现在直接标记在你的代码上了!

即使是你敲错了一个符号,该插件也会实时的追踪到你错误的地方,然后给出标记和异常提醒。这简直大大提升了开发效率,再也不用执行命令来检查代码了,看谁还说不优雅。

既然编辑器有 ESLint 插件,那是不是也有 Prettier 插件呢?猜对了,当然有插件,插件全名叫 Prettier - Code formatter,截图如下,在 VSCode 中搜索安装即可。

image.png

Prettier 插件安装之后会作为编辑器的一个格式化程序。在代码中右键格式化,就可以选择 Prettier 来格式化当前代码。

如果要想 Prettier 实现自动化,则还需要在编辑器中配置。

编辑器配置

VSCode 中有一个用户设置 setting.json 文件,其中保存了用户对编辑器的自定义配置。

这个配置非常丰富,详见官网。首先我们在这个配置当中将 Prettier 设置为默认格式化程序:

{   "editor.defaultFormatter": "esbenp.prettier-vscode",   "[javascript]": {     "editor.defaultFormatter": "esbenp.prettier-vscode"   } }

设置好这一步之后,重点来了! 我们再来配置保存文件自动格式化:

{   "editor.formatOnSave": true }

配好之后,神奇的事情发生了:当你写完代码保存的时候,发现你正在编辑的文件立刻被格式化了。也就是说,无论你的代码按不按照规范写,保存的时候自动帮你格式化成规范的代码。

这一步其实是保存文件的时候自动执行了格式化命令。因为我们上面配置了默认格式化程序为 Prettier,现在又配了保存时格式化,相当于将文件保存和 prettier 命令连接了起来。

到这一步,在三大神技的加持之下,我们已经实现了代码的自动检查与自动格式化,现在你编码的时候不需要考虑什么格式规范的问题,只要正常保存,编辑器会自动帮你做好这些事情。

共享编辑器配置

上面我们在编辑器经过一顿配置,终于实现了自动格式化。现在我们要把这些设置同步给团队内的其他成员,该怎么办,难道要一个一个再配一遍?

别慌,不用这么麻烦。VSCode 的设置分为两类:

  • 用户设置:应用于整个编辑器
  • 工作区设置:应用于当前目录/工作区

这两类的配置内容是一模一样的,区别只是优先级的问题。如果你打开的项目目录包含工作区设置,那么这个工作区设置会覆盖掉当前的用户设置。

所以要想将设置同步给团队内的其他成员,我们不需要去改动用户设置,只需要在项目目录下新建一个工作区设置即可。

添加工作区设置方法:在项目根目录下新建 .vscode/setting.json 文件,在这里写需要统一的编辑器配置。所以我们把上面的 Prettier 配置写在这里即可实现共享。

附录:命名和项目结构规范

上面介绍了代码规范,代码检查和代码格式化,统一代码风格已经很全面了。

在团队开发过程当中,我们也积累了一些并不会写在配置文件里的规范,这些规范在一个团队当中也是非常重要。这部分算是我们的团队规范的分享吧。

主要说两部分:命名规范和项目结构规范。

命名规范

命名规范,文章开头也说了,变量的四种命名规范。但是什么地方用哪种规范,我们也是有约定的。

  • 变量命名:下划线 user_id
  • CSS-Class 命名:中划线 user-id
  • 方法函数命名:小驼峰 userId
  • JS-Class 命名:大驼峰 UserId
  • 文件夹命名:中划线 user-id
  • 文件夹下组件命名:中划线 user-id
  • 组件导出命名:大驼峰 UserId

项目结构规范

项目结构规范主要是指 src 文件夹下的结构组织。

|-- src     |-- index.tsx # 入口文件     |-- assets # 静态资源目录     |-- components # 公共组件目录     |   |-- header     |   |   |-- index.tsx     |   |   |-- index.less     |-- stores # 状态管理目录,与 pages 结构对应     |   |-- admins     |   |   |-- index.tsx # 状态文件     |   |   |-- types.ts  # 定义状态类型     |   |-- index.tsx     |-- pages # 页面目录,与 stores 结构对应     |   |-- admins     |   |   |-- index.tsx     |   |   |-- index.less     |-- request     |   |-- index.ts # axios 实例,全局请求处理     |-- router     |   |-- home.tsx     |   |-- index.tsx     |   |-- root.tsx     |-- styles # 全局样式     |   |-- common.less     |   |-- index.less     |-- utils # 工具目录         |-- index.ts

往期精彩

专栏会长期输出前端工程与架构方向的文章,已发布如下:

如果喜欢我的文章,请点赞支持我吧!也欢迎关注我的专栏,感谢🙏🙏

“全真互联”时代:腾讯发力数实融合四大引擎

Posted: 11 Nov 2021 12:11 AM PST

"后疫情时代",数字经济正在成为推动全球化发展的新引擎。腾讯正积极拥抱产业互联网,发掘数字化新动能,立足优势能力,持续助力各行各业,发力用户、技术、安全和生态四大引擎,加速打造线上线下一体化、数字技术与真实世界融合的"全真互联"。  

当前,数字经济已经成为"后疫情时代"全球化发展的新引擎,我国也已将"迎接数字时代"提升至国家战略层面。刚刚过去的2021腾讯数字生态大会上,腾讯就邀请了业内众多专业大咖,共同探讨数实融合新趋势与新机遇,同时也带来了一系列"加速数实融合"的重磅方案,为地区各领域数字化建设注入强劲动力。

发力数实融合 腾讯主推"四大引擎"

随着数字经济的不断深入发展,社会各行业"数实融合"已成为大趋势。据中国信通院数据显示,2019年我国数字经济已达35.8万亿,占GPD的36.2%;2020年则达到39.2万亿元,占GDP的38.6%,同比增长9.7%。接下来,随着相关利好政策的不断出台,预计我国数字经济也将持续向着良好的势头发展。

本次大会上,腾讯公司高级执行副总裁、云与智慧产业事业群总裁汤道生也分别从社会公共服务、智能制造和消费市场这三个方面,就数字技术和产业互联网的发展对社会和经济发展的强助力做了主题分享。他认为,"对实体产业的价值助力是衡量产业互联网发展的重要标准"。

近年来,腾讯正积极拥抱产业互联网,已在工业、农业、政务、医疗、教育、出行、金融、零售等30多个行业,与9000家合作伙伴,打造了超过400个行业解决方案。接下来,为持续不断助力各行各业,发掘数字化新动能,腾讯将立足优势能力,打造用户、技术、安全和生态四大引擎:

一、打造用户引擎,将用户理解引入产业研发、生产、营销、服务,助力企业服务于人,激活增长;二、打造技术引擎,将前沿数字技术与产业落地融合,为产业升级提供更好用、易用的工具;三、打造安全引擎,以云原生、零信任为核心,塑造产业互联网时代的安全底座,让有数据的地方就有安全守护;四、打造生态引擎,通过数字化技术和资源的普惠开放,让"数字化养分"滋养产业全生态链条。

数实融合技术底座:"全真互联"

当前,消费互联网和产业互联网的蓬勃发展,让线上线下一体化、数字技术与真实世界融合的"全真互联"时代加速到来。会上,腾讯公司副总裁、云与智慧产业事业群COO兼腾讯云总裁邱跃鹏就对"全真互联"时代需要关注的三大技术趋势做了分享:

一、算力将延伸到网络的每一个角落,变得无处不在;二、云原生的重要性会进一步凸显,开发者和企业需要更懂得借助云来实现高效数字化转型;三、超高清、超低延时的网络传输是确保用户沉浸式体验的基础。

目前,腾讯云正在海量算力、实时分析、极致传输三个方向上,不断夯实全真互联的技术基础。其中,芯片是是产业互联网最核心的基础设施。据了解,腾讯已面向AI计算、视频处理、高性能网络这三个存在强烈需求的场景,研发推出了AI推理芯片紫霄、视频转码芯片沧海、智能网卡芯片玄灵。

作为当前数实融合的关键要素,安全议题常常被人们所提起。对此,腾讯副总裁、腾讯安全总裁丁珂也从安全厂商与客户共建、企业业务发展与安全共建、安全生态共建三个维度,为我们带来了专业解读。他表示,安全是数字经济健康可持续发展的基础保障,也是所有企业及政府的"必答题",而腾讯正在依靠自身积累的技术、人才和行业安全建设经验,来实现安全共建,为经济可持续发展和人们的美好生活提供坚实保障。

探索数实融合:腾讯勇当数字经济发展"排头兵"

为进一步推进数字经济的发展,基于云计算、大数据、AI等技术的科技企业正在勇当"数字技术激发产业新能效"的排头兵。近年来,腾讯也在积极探索数实融合新路径,目前腾讯云已在互联网、金融、教育、政务等方面取得了不少业务进展。

相关数据显示,腾讯云已服务了国内超过90%的音视频公司、超过80%的头部游戏公司以及绝大多数电商平台;客户覆盖银行、保险、证券、消费金融、产业金融等各细分领域;助力超过30个部委、20个省、500个市县数字化转型;助力超十万所大学建设智慧校园。

作为数实融合的典型场景,智慧交通出行及智慧零售领域也是产业互联网的重要落地领域。会上,腾讯副总裁、腾讯智慧交通和出行总裁及腾讯副总裁、腾讯智慧零售产研总裁分别对相关议题作了分享,并带来一系列推动行业模型转变、助力城市的高效治理的方案规划及落地成果。

特别是在实体经济方面,数字科技更是当下这个时代助力企业增长、创造更高价值的新引擎。对此议题,腾讯副总裁、腾讯智慧工业和服务业总裁李强也分别从组织高效、生产智能、流程优化和供应链协同四个方面来谈腾讯支持实体企业数字化。他表示,"将实体经济与数字经济加速实融合,不仅是新的经济增长点,也是传统产业数字化转型的支点"。

此外,腾讯微信事业群副总裁、企业微信负责人黄铁鸣也带来了企业微信连接在农业和政务场景方面的分享。他表示,连接,能带来信任、创新和发展。连接意味着洞察市场需求,捕获创新灵感,连接也在助力社会的发展。

《数字化转型指数报告2021》:全方位呈现数实融合新特征

为加速实现产业互联网数实融合,本次大会上,腾讯研究院还联手腾讯云重磅发布了《数字化转型指数报告2021》。

该报告显示,在数实融合已成为国家中长期重大战略的前提下,全国数字化转型指数持续走高,在2021年一季度达到307.26,同比增长207.4%,全国用云量(云计算指数)和赋智量(AI指数)持续增长,年增长量分别达57%和93%。

另外,广东、上海、北京是全国数字化转型指数排在三甲的省市。河南、湖北、湖南指数规模和增速均位列全国前十,成为"双强"省份,其中,2021年第一季度,湖北由于数字化助力抗疫恢复的突出成绩,首次跻身全国前十。

该报告表明,数字原生行业的数字化规模明显领先于传统行业,其中电商、金融、文创三大细分行业规模最大、最具典型性,成为推动中心城市产业数字化发展的中坚力量。但伴随新型基础设施加速普及,传统行业的数字化转型也呈现高速增长态势。在过去一年增速排名前十的行业中,广电、医疗、制造、教育、零售和能源等传统行业占据6席,其中广电行业规模同比增长近300%位居各行业之首。

深度融合数字技术:全新办会形式及参会体验

作为一场年度科技大展,本次"2021腾讯数字生态大会上就深度融合了腾讯的相关数字技术,让观众参会的同时,也能更直接感受数字技术带来的全新体验。

本次大会开设了40场行业及产品专场,涵盖了金融、智慧教育、智慧医疗、智慧零售、智慧交通、智能制造等诸多腾讯明星业务,在这里各行业的合作伙伴可以共同分享行业新机遇,开展深入合作。

比如为大会定制开发在线数字化签约的工具"腾讯电子签",包括腾讯云核心合作签约及碳中和、智慧地产、智能终端、智能传媒专场签约,都是通过腾讯电子签完成,签约双方在iPad上签名,电子合同自动存档,无需签署纸质文件。

由于其端到端60-80ms的低时延,因此线上观众也能通过云渲染方案打造的沉浸式云展厅,随时随地通过手机、微信小程序等轻量级终端享受高清高帧率体验,远程来感受现场展区的魅力。

此外,此次大会还在腾讯会议网络研讨会(webniar)实现办会,用户通过线上腾讯会议网络研讨会功能,就可以实时观看生态大会的40个论坛。而腾讯云AI数智人、腾讯同传、腾讯云企点的能力植入,也让腾讯仅用一场大会,就能直接展示产业数字化带来的全新高效工作与便利生活。

写在最后:

在AI、云计算等数字技术的不断演化下,社会经济型态正加速重构,我们的社会也正快速步入数字经济时代。而在数实融合的浪潮中,腾讯正在携手各行业乘风破浪不断探索,投入到社会经济腾飞发展中,为我国打造"数字强国"提供助力!

华为开发者大会主题演讲:全链路网络加速,全场景极速体验

Posted: 11 Nov 2021 12:50 AM PST

大家好!今天我要介绍的是全链路网络加速解决方案。现代社会人们离不开网络,上班地铁刷短视频、中午打场游戏、晚上看网络视频。但我们经常会遇到短视频转圈刷不出来、游戏资源下载慢、视频卡顿等问题。

全链路网络加速可以助力应用克服网络痛点。一个网络请求从无线网络接入到运营商的骨干网,再到互联网公网,最终来到数据中心或是服务器。每个过程都面临着非常多的挑战,比如无线网络的信号弱、干扰源多;接入网的带宽不足、拥塞;骨干网的DNS劫持;在跨运营商和跨洋数据交换的场景下,由于区域网络质量差异导致的路由调度不合理等。

全链路网络加速能力开放后,无线传输服务作为原子能力可以增强通信,对抗网络干扰。Network Kit一次接入全链路加速解决方案,在内容加载、文件传输、即时通信、多媒体等场景助力网络加速。WiseWAN全球精品网也正在构建中。

短视频应用 如何克服移动中的不稳定网络?

在移动网络的弱覆盖区域,视频类应用经常会出现加载中、卡顿的现象,这就是我们常说的信号黑洞。今年,无线传输服务推出了AI信号预测能力,使流媒体不再卡顿。如下图一辆车行驶在一段路径上,集成前经过弱信号区域时刷视频会卡顿,集成后在网络QoE(用户感知)变化、固定路线、AI机器学习的关键技术支撑下,可以进行弱网预测的及时反馈,提前缓存流媒体。

即时应用 如何对抗复杂干扰网络环境?

网络时延不止影响用户体验,还会影响应用的广告收入。华为付费展示服务数据显示,广告请求每慢100ms,点击率就会下降3%-5%。应用集成Network Kit可以获得全链路的网络增益。

在即时通信场景,帮助应用关键业务即发即达。其一:小报文拥塞算法。通过丢包和带宽检测,在弱网场景自适应增加冗余包,降低时延,提升消息到达率。其二:智能心跳算法。针对多变的移动网络和应用当前状态,灵活识别假链接,保证链接稳定,降低心跳频率。其三:自定义数据包优先级,保障关键业务在网络拥塞下能优先发送。

游戏关键报文、社交聊天、会控指令、视频弹幕等多个即时通信场景都适用。举个例子!消息应用LinkNow集成Network Kit后,IM消息发送场景的网络请求时延降低了18%。

在文件传输场景,帮助游戏资源包提速。玩一款制作精良的游戏时,需要下载人物、地图、道具等游戏资源,后续还会有版本的补丁升级。这些都直接影响着用户的游戏体验。Network Kit使用华为自研QUIC协议和大文件拥塞算法,提升吞吐量;运用AI智能分片算法、多线程、断点续传等关键技术,提升带宽利用率。三七互娱旗下游戏《斗罗大陆》集成Network Kit后,游戏资源包下载性能提升了40%。

页面加载 低时延秒开?

Network Kit的另一大能力是低时延内容加载。从华为应用市场的数据中得知,点击页面3秒无反应,40%的用户会选择退出。所以页面加载的成功率非常重要。

Network Kit针对互联网DNS分配不合理的问题做DNS预取,平均时延小于20毫秒。在弱网环境下,提升网络敏感性,调整动态网络参数,使网络环境自适应。基于AI预测业务行为,提前建链,使短链接开销实现长链接的效果。该能力适用于账号登入、订单信息查询、主页资源查询加载等应用场景。华为账号和华为会员中心集成后,业务请求平均时延降低了22%-32%。

多媒体应用 如何在网络拥塞场景高清播放无卡顿?

在点播类视频、直播、实时音视频等场景下,相信大家经常会遇到播一半突然卡顿加载且超过5秒的情况。数据显示,这时会有5%的用户直接退出页面。为提升用户体验,我们通过华为自研QUIC协议,自研多媒体拥塞控制算法,以及AI智能动态调整,在不同网络环境下调整网络参数。目前,我们和华为视频对接开发的Demo即将开放,致力打造流畅多媒体。

最后,我想简单总结一下全链路网络加速能力:第一,我们有无线传输服务的原子能力。开发者可以深度适配,比如AI信号预测能力,通过精准信息预测网络进入卡顿区的时间;多网协同,灵活调用接口,服务游戏、网课、即时通话场景。

第二,Network Kit简易集成,实现全链路加速。开放内容加载、文件传输、即时通信和多媒体等场景能力,整合无线传输服务的原子能力,集成后实现端到端的加速。
简单是最终极的复杂。我们提供开发者最简单的方式接入无线传输服务、Network Kit,使用到华为强大复杂的算法与庞大的端云部署。在这里,开发者能体验到最好的全链路网络加速服务。以上是我的介绍,谢谢大家!

了解更多详情>>

访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHubGitee

关注我们,第一时间了解 HMS Core 最新技术资讯~

现代化办公、AI、混合现实、可持续发展,微软进博会全回顾

Posted: 10 Nov 2021 11:50 PM PST

为期 5 天的"上海· 2021 年中国国际进口博览会"已圆满落幕。作为全球创新机遇的"窗口",进博会吸引了来自全球各地的知名大厂前来"秀肌肉",而其中最不容错过的便是 "硬科技" 展区。从 AI 技术加持的数字化转型浪潮,到打破虚拟与现实隔阂的软硬件体验,全新的数字世界让人连连惊叹!

今年 SegmentFault 思否 COO 江波也受邀作为微软展区的 "首席科技体验官" 来到了现场探秘。在 "叨扰" 了一众技术大咖后,她带回了来自现场的第一手资讯,让我们跟随她的镜头来一次 360° 全方位探索吧!

在本届进博会上,微软以"全球引擎 中国伙伴"为主题、从"前沿科技探索"和"数字化转型实践"两条主线入手,围绕可持续发展、数字经济等热门话题,以及智能零售、智能医疗、智能汽车、智能制造等创新领域,集中展示了微软"与中国共创新"的最新成果。

数字技术构建低碳、高效、可持续发展的未来

进入展区,首先映入眼帘的便是 "低碳城市" 与 "可持续发展之旅"。在这里,江波遇到了微软中国的 CTO 韦青。在韦青老师的带领下,我们看到了微软作为领先的技术企业,通过数字技术助力实体经济融合,帮助企业走向零碳的大量案例。

有趣的是,韦青老师还向我们介绍了微软与合作伙伴共同开发了首款海洋环保鼠标,在这款鼠标中有 20% 的材料由来自海洋的可回收塑料制成。

谈到环保,韦青老师还向我们介绍了微软的零碳、可持续发展目标。如今,可持续发展已经成为全球各行业共同关注的重大问题,而微软更是做出承诺:将在 2030 年实现碳负排放,2050 年前,清除公司自 1975 年成立以来直接或因电力消耗而间接产生的所有碳足迹。

波波看展杂记:在各大企业还将全部重心放在业务增长时,微软已经看到了若干年后的可持续。想拥有这款海洋鼠标,一边办公,一边幻想在海边度假。

除了"零碳"目标,长期致力于 "守护物种多样性" 的微软还在进博会上携手 3D 特效公司 Vision 3 为我们带来了名为《危险距离(Critical Distance)》的混合现实展览。微软为生活在太平洋中的虎鲸 Kiki 及其家族制作了"数字替身",通过混合现实的沉浸式体验,人们能了解到虎鲸这种高等海洋生物的生活习性、相互交流与惊人智慧,并切身感受到过度捕捞、旅游观光、海洋垃圾对其生活造成的严重威胁。

"首席科技体验官" 江波也走进了这一展区,戴上 HoloLens 2 便仿佛置身海洋一般,与虎鲸交流、对话。逼真的效果,和亲眼可见的、环境污染对海洋生物的重大威胁,让她印象深刻。在直播探展中,她曾说到 "如果不能身临其境、感同身受,我们大概很难理解这些海洋生物,也就很难真正将守护它们铭记心中"。我想这便是将混合现实技术应用到生物多样性保护中,最大的价值。

波波看展杂记:"元宇宙"概念大火,一时间 AR/VR 技术的应用层出不穷,虽看过不少 VR 游戏和影视作品,但微软的这一应用带给我的震撼依旧无可比拟。将技术和可持续发展相结合,通过混合现实技术打造出的沉浸世界,最大限度唤起了我们对于濒危动物保护的共鸣。

生产力拉满,全新 Surface 让人直呼 "真香"

到达现代化办公展区后,我们看到了一排崭新的 Surface,在了解了全新 Surface Go 3 助力周大福数字化转型的故事后,江波上手体验了这款轻如 Pad 却性能超强的全新笔记本电脑。

微软最让我们熟悉的其实就是办公版块,学习 Office 软件,几乎已经成为每一个职场人的终身必修课。然而相比于将自己定义为一款软硬件产品,微软则更喜欢将自己称之为"生产力平台",在微软 CTO 微软韦青总介绍下,我们了解到,除了 Windows,Office,Surface 为代表的软件公司,微软更是一家拥有 AI,混合现实,云计算等丰富前沿科技并积极拥抱开源的公司。在这里,你可近距离体验微软软硬结合的优势。

波波看展杂记:大呼"真香"的就是我本人了,作为一个 "飞行达人",常常各地出差的我,在 Surface Pro 8 开启预售后便果断下手,对我而言,电脑的便携性和待机时长是最重要的,而 Surface Pro 8 就像是为我量身定制。

创新科技探索,AI 让万物智慧可爱

创新科技探索,大概是当日最"智慧"的展区。微软以人工智能的语音、语义、视觉等技术能力为基础,将人工智能应用拓展到虚拟主播、智慧投资、超分辨率等使用场景。

其中最为吸睛的便是一个戴着虎头帽、脸上高原红的中国娃娃,他名叫"虎墩",来 CIIE 扮演一位 "人工智能虚拟主播"。

据导演邹燚老师介绍,"虎墩的诞生,包括形象设计上就花了三年的时间。如今,小虎墩已经成长为一个大IP,除了有动画电影,还出了漫画、游戏、主题公园 、盲盒等多样衍生项目。" 而此次和微软的合作,让虎墩有了"新本领",动漫人物能眉飞色舞地与人实时对话了,也赋予了虎墩新的生命力。

据了解,这背后用到了微软基于 Dialog Engine 的 Chatbot 智能对话技术,使用了 Microsoft Azure 智能云认知服务的语音 TTS(文字转语音)和 ASR(语音转文字, 利用唇形模型来控制动画形象的口型)技术,同时该动画人物基于 NLP 技术可自动生成对应的肢体动作。

波波看展杂记:AI 与动漫的融合让我看到了动漫作品新的发展。在和虎墩的对话中,我不仅能快速 Get 我想了解的信息,他的人物特点也展露无疑。人工智能技术的助力无疑可以让动漫人物更有趣、也更深入人心。

另一个让人印象深刻的展区便是 "智慧投资" 。在屏幕上,我们可以看到基金交易的动态曲线。微软尝试把 AI 用于智慧投资领域,帮助人们在纷繁复杂的信息中,摘取出有价值的重要内容,从数据分析、动态数据建模、风险识别和动态智能交易 4 个方面帮助人们进行投资决策。更让人兴奋的是,这一技术目前已在 GitHub 上开源,每一位投资者都可以轻松地用起来。

波波看展杂记:请记住这个"暴富"秘籍,GitHub 搜索开源项目 "Qlib" 让人工智能技术帮你日进斗金!

此外,在这一区域,还有微软以人工智能与大数据为基础,在临床试验阶段、药品上市等场景帮助药企数字化转型,利用图像超分辨率算法优化直播、视频会议画面质量等行业的应用。

携手本土生态伙伴,用"黑科技"助力企业数字化

在用数字技术构建低碳未来、助力数字化转型这件事上,微软并非 "独行侠"。面对全球加速数字化转型、中国引领创新发展的新常态,微软携手本土生态伙伴赋能千行百业。

在进博会的展台,微软也与一众合作伙伴,带来了他们在各行业数字化转型进程上的解决方案。在 "云原生零售解决方案" 展台,针对大型零售企业面临庞大客户群时,在客户分类、分阶段数据管理过程中容易产生人力资源浪费的问题,天正聚合基于微软 Azure (存储)+ Azure PaaS (调用)+D365 CRM,联合天正的微服务、分布能力和行业视角,设计了云原生 CDP 解决方案。

该项目以支付为原点、以'人'为中心、通过强大的数据分析能力,在零售行业展现客户管理及营销系统,通过对零售行业的数字化应用,综合提升了零售行业多客户的数据能力。

"智能座舱" 展台,微软与均胜、特斯拉、BYD、小鹏、联想等合作伙伴在智能汽车领域展开深入合作。微软基于强大的语音语义及数据架构的底层平台,通过强大的技术能力和底层平台赋能众多智能汽车厂商,开发形态多样的中控显示语音系统、配合多维的硬件结构,让用户体验更智能的驾驶座舱的交互感受。

"药企数字健康" 展台,微软以人工智能与大数据为基础,在临床试验、药品上市等场景帮助药企数字化转型。基于医药企业长期面临多项目、长进度、多工种、多人群、复杂流程的工作特点,化解了药企数字化转型难题。

"智能制造" 展区,微软则携手硕软(SoftwareONE)、南洋万邦、精诚中国、上海不工、艺康、台达等 6 大合作伙伴,从安全合规、 AIoT 智慧工厂、数字化采购供应链、供应链协同管理、水可持续发展、能源智能管控 6 个方面带来了制造业企业数字化转型的完善解决方案。

波波看展杂记:数字化转型,需要领先的技术,也需要深扎行业,对需求、痛点的细微洞察和解决能力。微软技术在千行百业的应用背后,是其扎扎实实的技术投入,也彰显了其强大的商业伙伴生态!

最后

正如江波在直播中所说 —— 逛完微软在进博会的展区,印入脑海的是微软扎扎实实的技术投入,千行百业的技术应用,和绿色可持续的技术情怀。微软真正让人敬佩的从来不仅仅是技术本身,而是透过技术看其应用时,所能窥探到的、其作为全球最大软件公司的社会责任感和历史使命感。

予力全球每一人、每一组织,成就不凡。透过 CIIE,我们读懂了微软的公司使命。

Go 开源 12 周年:新域名 go.dev 的启用|Russ Cox 发文庆贺

Posted: 10 Nov 2021 08:13 PM PST

自 2009 年 11 月正式对外发布后,至今 Go 开源已走过整整 12 个年头。刚刚,Go 开发团队技术 leader Russ Cox 就专门撰文庆祝 "Go 开源 12 周年"。

在这篇博客文章中,Russ Cox 对 Go 开源今年以来的变化及所取得进展做了回顾,并对下一阶段的发展进行了展望。

Russ Cox 提到了将 godoc.org 替换成 pkg.go.dev,以及新域名 go.dev 的启用,可将所有官方 Go 站点整合至统一域名下。

今年 2 月,Go 1.16 版本添加了对 macOS ARM64 的支持,以及文件系统接口和嵌入文件、默认启用 modules 等多项改进优化。

今年 8 月,Go 1.17 版本添加了对 Windows ARM64 的支持,大大提升了 TLS 密码套件决策的易用性和安全性;修剪模块图 (pruned module graphs)及全新易读的构建约束语法的引入,让 Go Modules 在大型项目中更高效。Go 1.17 版本还在底层上将 x86-64 的 Go 函数切换至基于寄存器的调用约定, 让 CPU 密集型应用程序的性能提高了 5-15%。

此外,IDE 方面也支持在 VS Code Go 中默认启用 gopls, 同时还为 gopls 和 VS Code Go 提供多项改进,包括由 Delve 提供支持的强大调试体验。

除了添加模糊测试支持的新提案,今年还正式提议向 Go 添加泛型,并明确将在 Go 1.18 中提供。

据了解,10 月初,"Go 语言之父" Rob Pike 曾在 Github 上撰文称"不建议在 Go 1.18 的标准库中使用泛型"的issue。而到了 10 月 28 日,Russ Cox 又发文终于明确了" Go 1.18 版本中将支持泛型"的信息。

对此,Russ Cox 在此次博文中表示,完善泛型将是 Go 团队明年的重点工作之一(另一项重点工作和供应链安全相关)。Go 1.18 中的初始版本只是一个开始,预计 Go 1.19(或将于 2022 年 8 月发布)及更高版本将进一步完善泛型的设计和实现,并将其进一步整合到整体 Go 体验中。

目前,Go 团队已经着手研究 Go 漏洞数据库以及用于报告程序依赖项中漏洞的相关工具,以提高此类工具的信噪比(如果程序不使用易受攻击的功能,则不会进行报告),预计明年会被作为独立工具提供,且将其添加到现有工具中。同时,在改进 Go 供应链安全态势方面,未来也还有更多工作需要开展。

关于 Go 语言

Go 语言最初由 Rob Pike 等谷歌工程师在 2007 年 9 月启动设计工作,在2009 年 11 月正式对外发布。

Go 语言完美融合了动态语言易于编写的特性和静态语言的高效性,具备良好的易用性和极佳的执行效率。

Go 语言最初定位于 Web 服务器、存储系统和数据库的程序设计,同时在语言中包含并发构造体,以帮助开发者创建并行任务。Go 开发团队曾表示,编译完成的 Go 程序运行速度接近 C 语言实现的程序。

简单、好懂的Svelte实现原理

Posted: 09 Nov 2021 06:19 PM PST

大家好,我卡颂。

Svelte问世很久了,一直想写一篇好懂的原理分析文章,拖了这么久终于写了。

本文会围绕一张流程图和两个Demo讲解,正确的食用方式是用电脑打开本文,跟着流程图、Demo一边看、一边敲、一边学。

让我么开始吧。

Demo1

Svelte的实现原理如图:

图中Component是开发者编写的组件,内部虚线部分是由Svelte编译器编译而成的。图中的各个箭头是运行时的工作流程。

首先来看编译时,考虑如下App组件代码:

<h1>{count}</h1>  <script>   let count = 0; </script>
完整代码见Demo1 repl

浏览器会显示:

这段代码经由编译器编译后产生如下代码,包括三部分:

  • create_fragment方法
  • count的声明语句
  • class App的声明语句
// 省略部分代码… function create_fragment(ctx) {   let h1;    return {     c() {       h1 = element("h1");       h1.textContent = `${count}`;     },     m(target, anchor) {       insert(target, h1, anchor);     },     d(detaching) {       if (detaching) detach(h1);     }   }; }  let count = 0;  class App extends SvelteComponent {   constructor(options) {     super();     init(this, options, null, create_fragment, safe_not_equal, {});   } }  export default App;

create_fragment

首先来看create_fragment方法,他是编译器根据AppUI编译而成,提供该组件与浏览器交互的方法,在上述编译结果中,包含3个方法:

  • c,代表create,用于根据模版内容,创建对应DOM Element。例子中创建H1对应DOM Element
h1 = element("h1"); h1.textContent = `${count}`;
  • m,代表mount,用于将c创建的DOM Element插入页面,完成组件首次渲染。例子中会将H1插入页面:
insert(target, h1, anchor);

insert方法会调用target.insertBefore

 function insert(target, node, anchor) {   target.insertBefore(node, anchor || null); }
  • d,代表detach,用于将组件对应DOM Element从页面中移除。例子中会移除H1
if (detaching) detach(h1);

detach方法会调用parentNode.removeChild

function detach(node) {   node.parentNode.removeChild(node); }

仔细观察流程图,会发现App组件编译的产物没有图中fragment内的p方法。

这是因为App没有变化状态的逻辑,所以相应方法不会出现在编译产物中。

可以发现,create_fragment返回的cm方法用于组件首次渲染。那么是谁调用这些方法呢?

SvelteComponent

每个组件对应一个继承自SvelteComponentclass,实例化时会调用init方法完成组件初始化,create_fragment会在init中调用:

class App extends SvelteComponent {   constructor(options) {     super();     init(this, options, null, create_fragment, safe_not_equal, {});   } }

总结一下,流程图中虚线部分在Demo1中的编译结果为:

  • fragment:编译为create_fragment方法的返回值
  • UIcreate_fragment返回值中m方法的执行结果
  • ctx:代表组件的上下文,由于例子中只包含一个不会改变的状态count,所以ctx就是count的声明语句

可以改变状态的Demo

现在修改Demo,增加update方法,为H1绑定点击事件,点击后count改变:

<h1 on:click="{update}">{count}</h1>  <script>   let count = 0;   function update() {     count++;   } </script>
完整代码见Demo2 repl

编译产物发生变化,ctx的变化如下:

// 从module顶层的声明语句 let count = 0;  // 变为instance方法 function instance($$self, $$props, $$invalidate) {   let count = 0;    function update() {     $$invalidate(0, count++, count);   }    return [count, update]; }

countmodule顶层的声明语句变为instance方法内的变量。之所以产生如此变化是因为App可以实例化多个:

// 模版中定义3个App <App/> <App/> <App/>  // 当count不可变时,页面渲染为:<h1>0</h1> <h1>0</h1> <h1>0</h1>

count不可变时,所有App可以复用同一个count。但是当count可变时,根据不同App被点击次数不同,页面可能渲染为:

<h1>0</h1> <h1>3</h1> <h1>1</h1>

所以每个App需要有独立的上下文保存count,这就是instance方法的意义。推广来说,Svelte编译器会追踪<script>内所有变量声明:

  • 是否包含改变该变量的语句,比如count++
  • 是否包含重新赋值的语句,比如count = 1
  • 等等情况

一旦发现,就会将该变量提取到instance中,instance执行后的返回值就是组件对应ctx

同时,如果执行如上操作的语句可以通过模版被引用,则该语句会被$$invalidate包裹。

Demo2中,update方法满足:

  • 包含改变count的语句 —— count++
  • 可以通过模版被引用 —— 作为点击回调函数

所以编译后的update内改变count的语句被$$invalidate方法包裹:

// 源代码中的update function update() {   count++; }  // 编译后instance中的update function update() {   $$invalidate(0, count++, count); }

从流程图可知,$$invalidate方法会执行如下操作:

  • 更新ctx中保存状态的值,比如Demo2count++
  • 标记dirty,即标记App UI中所有和count相关的部分将会发生变化
  • 调度更新,在microtask中调度本次更新,所有在同一个macrotask中执行的$$invalidate都会在该macrotask执行完成后被统一执行,最终会执行组件fragment中的p方法

p方法是Demo2中新的编译产物,除了p之外,create_fragment已有的方法也产生相应变化:

c() {   h1 = element("h1");   // count的值变为从ctx中获取   t = text(/*count*/ ctx[0]); }, m(target, anchor) {   insert(target, h1, anchor);   append(h1, t);   // 事件绑定   dispose = listen(h1, "click", /*update*/ ctx[1]); }, p(ctx, [dirty]) {   // set_data会更新t保存的文本节点   if (dirty & /*count*/ 1) set_data(t, /*count*/ ctx[0]); }, d(detaching) {   if (detaching) detach(h1);   // 事件解绑   dispose(); }

p方法会执行$$invalidate中标记为dirty的项对应的更新函数。

Demo2中,App UI中只引用了状态count,所以update方法中只有一个if语句,如果UI中引用了多个状态,则p方法中也会包含多个if语句:

// UI中引用多个状态  <h1 on:click="{count0++}">{count0}</h1> <h1 on:click="{count1++}">{count1}</h1> <h1 on:click="{count2++}">{count2}</h1>

对应p方法包含多个if语句:

p(new_ctx, [dirty]) {   ctx = new_ctx;   if (dirty & /*count*/ 1) set_data(t0, /*count*/ ctx[0]);   if (dirty & /*count1*/ 2) set_data(t2, /*count1*/ ctx[1]);   if (dirty & /*count2*/ 4) set_data(t4, /*count2*/ ctx[2]); },

Demo2完整的更新步骤如下:

  1. 点击H1触发回调函数update
  2. update内调用$$invalidate,更新ctx中的count,标记countdirty,调度更新
  3. 执行p方法,进入dirty的项(即count)对应if语句,执行更新对应DOM Element的方法

总结

Svelte的完整工作流程会复杂的多,但是核心实现便是如此。

我们可以直观的感受到,借由模版语法的约束,经过编译优化,可以直接建立状态与要改变的DOM节点的对应关系

Demo2中,状态count的变化直接对应p方法中一个if语句,使得Svelte执行细粒度的更新时对比使用虚拟DOM的框架更有性能优势。

上述性能分析中第四行select row就是一个细粒度的更新。想比较之下,React(倒数第三列)性能就差很多。

欢迎加入人类高质量前端框架群,带飞

No comments:

Post a Comment