关于大前端:互动游戏团队如何将性能体验优化做到TOP级别

一、背景随着互动游戏业务 DAU 量级减少,性能和体验重要性也越发重要,好的性能和体验不仅能够减少用户应用体感,也能够减少用户对于互动游戏的应用粘性。 对现状剖析,次要存在首屏渲染速度慢、关上页面存在白屏、页面加载过多资源等问题,外围伎俩是减少骨架、接口优先级调整、预渲染、减小包体积等。 优化后,互动游戏签到性能做到同类业务性能体验 Top 级别,上面是优化后数据: 首屏渲染速度:优化后晋升首屏渲染速度 39%。首屏骨架:骨架体积大小缩小 44%(压缩后缩小 50%)。首次加载总资源:资源总体积优化后,大小缩小 69%。二、骨架骨架屏是指在页面加载时,长期显示出页面的次要构造,能够让用户在期待页面加载实现时,失去视觉上的反馈,晋升页面的用户体验。骨架示意图vs数据渲染 能够看出在接口返回数据之前,能够先应用骨架失去一些界面反馈。 三、缓存尽管骨架屏能够让用户在视觉上失去反馈,毕竟不是实在的数据,总体还是有一些简陋,用户也可能并不知道这块区域理论渲染的是什么样的内容,若是网络环境不好,很可能会长工夫的停留在骨架屏阶段,为了加强一些体感,应用缓存进一步对页面进行优化。应用缓存渲染具备以下劣势: 与骨架屏相比,缓存渲染非常靠近用户最终所见,因为每次接口返回数据都会更新缓存,用户再次进入时看到的都是本人上次进入时的数据。当用户处在弱网或者断网等不可抗力的环境中时,能够失去较为残缺的页面数据展现,能够很好削弱用户环境带来的网络营销。应用缓存注意事项: 一些缓存渲染应屏蔽事件响应,防止造成不必要的报错和客诉。比方商品的缓存渲染,因为商品存在下架、优惠券调整等状况,缓存的数据和理论数据会存在肯定的偏差。缓存渲染逻辑须要更加前置,不应该将缓存渲染的逻辑放在本来的地位,这样会拖慢渲染的机会。四、接口后置浏览器对同一时间内的申请数量是有限度的,既并发申请限度。当一个页面首次渲染时须要浏览器发动很多接口申请,用于填充页面渲染须要的数据,若是对于页面渲染时的申请数量不加以控制,便可能导致一些问题呈现。 当初有 home 和 info 两个接口,home 接口返回的数据是首屏渲染须要依赖的,info 接口返回的数据则不是首屏必须依赖的。假如当初还有一些其余申请占据了并发申请限度的数量,导致 home 接口申请变慢。若是 info 接口响应慢,长时间占据这浏览器的申请过程,会导致页面首屏渲染速度更慢,那么就须要有个一套计划能够依据接口的优先级进行加载顺序控制,能够将程序变为如下。计划: 当页面加载实现后肯定工夫后,进行低优先级接口的申请,或者触发页面的滚动、点击等时立刻进行接口申请。 此计划实用于:确定接口提早加载并不会阻塞用户的交互和操作。 将其封装为一个 hooks,便于复用,间接先看代码再解释: import { useRM, createRM } from 'xxx'const listen = (type: string, listener: () => void) => { const l = () => { listener() document.removeEventListener(type, l) } document.addEventListener(type, l)}const pageFlowModule = createRM( { assemble(state) { const reactionObserver = () => { state.isUserReactioned = true } ;['scroll', 'mousedown', 'touchstart'].forEach((type) => { listen(type, reactionObserver) }) setTimeout(reactionObserver, 4000) }, }, { isUserReactioned: false },)pageFlowModule.actions.assemble()export const usePageFlow = () => { const [state] = useRM(pageFlowModule) return state}应用: ...

February 23, 2024 · 3 min · jiezi

关于大前端:开源数据可视化开发平台FlyFish数据源应用教程详解

介绍飞鱼(FlyFish)是云智慧开源的一款收费的数据可视化编排平台。通过繁难的形式疾速创立数据模型,通过利落拽的模式,疾速生成一套数据可视化解决方案。在飞鱼产品中能够通过间接连贯 MySQL 、 Oracle 等数据库间接从数据源中获取数据展现在可视化利用上,本文旨在为读者形容如何从数据源连贯到数据展现在利用的步骤。 数据源类型飞鱼(FlyFish)目前反对的数据源类型有如下几种。其中 MySQL、Postgres、ClickHouse、MariaDB、SqlServer、达梦、Oracle均为数据库,能够间接写sql获取数据。http数据源能够填写申请门路参数等信息,最终对返回的json构造做解决反对利用展现。 数据库类型数据本篇文章以MySQL数据源为例,详细描述一下数据库类的数据源解决流程。 数据源创立首先点击数据源治理页面的新建按钮,能够看到如下页面: 选中MySQL数据源类型,而后填写对应信息,其中具体信息含意如下: 数据源名称:为新创建的数据源命名以便创立胜利后在列表中找到他。连贯地址:填写MySQL数据库的连贯地址如图中示例,留神ip和端口号以及db名称的正确填写。数据库名称:该值不须要填写,会从连贯地址中主动解析。用户名:连贯MySQL数据库的用户名。明码:连贯MySQL数据库的用户名对应的用户明码。须要留神的是,因为对于不同的数据库定位到一个db所需的配置不同,所以不同的数据库所要填写的值可能不同,例如Oracle数据库如果上述内容,还有Schema名称须要填写。 信息填写实现之后能够点击链接测试按钮,校验以后db是否能够胜利链接。弹出如下图所示内容,则示意胜利链接。 如果弹出如下图,阐明以后db并没有连贯胜利,须要查看所填写的信息是否正确,以及是否是网络问题,比方局部用户的db只在本人的内网能够拜访。 测试链接胜利后,点击保留数据源按钮保留、设置好的数据源信息。能够点击编辑去更改数据源的信息,以及删除按钮去删除掉不想要的数据源。在列表上看到保留胜利的数据源如下: 数据查问创立创立好数据源只是、应用数据源的第一步,下一须要通过写SQL来获取所需内容。点击侧边栏的数据查问按钮来创立新的数据查问。点击新建根底查问按钮咱们看到如下页面: 如果以后数据源过多,能够输出之前设置好的数据源名称来进行检索。选中之前增加好的数据源,能够看到所有的数据表信息会展现在页面上,如下图所示: 选中想要获取数据的表会跳转到书写SQL的页面,并且主动生成全表查问的SQL如下图所示: 在这能够去书写想要实现的SQL语句,须要留神,这里并不是只限度查问以后选中的表,仍然能够写其余的表名或者做关联查问。此外对于不同类型的数据源须要留神SQL语法,比方MySQL的语法和Oracle的语法就会有区别,须要依据数据源的类型书写能够辨认的sql语句。写完SQL之后能够点击输出右上角的执行按钮,来执行编写的SQL语句,如下图所示: 在输入框上面,能够看到以后SQL语句查问返回的数据信息,如果后果和预期不符能够持续更改SQL改成本人称心的成果。此外,输入框右上角还有一个设置参数的按钮。该按钮次要是为了解决SQL复用问题。举个例子,比方有两张大屏,一张须要id字段,另一张须要name字段,那么用户是不是须要写两句SQL呢?而设置参数就完满解决了这个问题,上面来看一下设置参数如何应用。 如下图可将我本人须要查问的字段设置为一个叫做param的参数,即应用{{}}将我想要设置的参数包裹起来: 而后点击设置参数按钮,零碎会主动解析须要设置的参数如下图弹窗 在这里设置这个参数的类型为:文本,而后默认值为:id,填写一个形容信息,而后点击确定。当再次点击执行按钮就会应用参数默认值,展现新的后果如下图: 这个参数能够利用于语句的各个中央,查问字段、表名、查问条件等,开发者能够根据集体需要进行变量设置。前面会详细描述如何在大屏上怎么设置此类变量。 当调整好SQL语句点击页面右上角的保留,会呈现如下弹窗: 为查问起一个不便记忆的名字,是很好的抉择,以便能够很快找到它。点击确定即保留胜利。此时,在数据查问的列表页,便能够看到新建胜利的数据查问,如下图所示。 点击数据名称能够对数据查问进行编辑,须要留神的是,如果该数据查问曾经利用于大屏组件,如果更改后返回后果与之前不统一,可能导致大屏展现异样。 数据查问的利用接下来讲一下如何将曾经配置好的数据查问利用于大屏。 从侧边栏点击到利用创立->利用开发,能够新创建一个利用或者在之前的利用中编辑,在利用上点击开发,进入如下开发页面: 以滚动列表图中组件为例。拖动一个滚动列表组件到编辑器而后选中该组件,在右侧边栏选中【数据】 ,而后在数据类型下拉选中选中【数据查问】,之后在数据查问输入框中输出之前命名好的数据【查问名称】,在搜寻后果中选中它,能够发现之前设置的参数也会同时展现在上面,这个时候就能够去更改参数的值,如下图所示: 上图中能够看到入选中之前创立的数据查问,而后将参数值改为name,点击利用后就能够看到组件上展现的信息曾经变更为name字段的信息。而后进行利用的保留即可。至此实现数据源从配置到利用的全副流程。 http类型数据http数据源辨别于数据库类的数据源增加的时候有本人独自的逻辑。 数据源创立在数据源列表页面,点击新建按钮而后选中数据源类型为http看到如下界面: 字段解释: 数据源名称:自定义新增数据源的名称,符合要求即可。数据库名称:定义一个数据库的名称,用于前面的sql加工。申请:下拉选抉择申请类型,而后在前面的地址栏填写对应的门路。header申请头:填写该申请的header信息。申请参数:填写该申请的参数信息。申请体:填写申请体信息。全副填写实现后点击保留数据源即可保留胜利。需注意以后数据源在前面数据查问的创立时会被当做一个db解决,所以数据库名名称会呈现在SQL的查问语句中,这里的命名须要合乎对应的规定。 数据表创立回到数据源列表页面,找到新建的数据源点击进入数据源详情页面,如下图所示: 点击左下角的新增表格,而后输出自定义的数据表的名称,点击回车即可开始建表。这里能够了解为数据库的建表,便于后续做SQL加工建表过程中,会把数据源的header及参数信息回显在这里,而后点击执行查问按钮,能够在后果预览中看到申请返回的数据如上图所示。随后能够开始对返回的信息做字段定义来进行json抽取,点击定义字段上面的增加按钮,看到如下弹窗: 字段解释: 字段名称:定义一个字段名称,能够了解为数据库中的列名,用于后续sql加工字段类型:下拉选抉择字段的类型数据抽取:填写jsonpath门路,用于提取json中的数据。数据预览:在填写jsonpath的过程中会实时展现以后jsonpath提取到的信息对于jsonpath的具体用法可参考:https://blog.csdn.net/software_test010/article/details/125427926,在数据预览中看到已提取到所需数据之后,点击确定来保留以后字段的设置。提取到所需字段会有相似数据库的行列展现如下图: 图中数据表的展现信息即以后数据表最终拿到的后果,点击保留即可。反复下面步骤能够对同一数据源创立多张数据表,即对返回的后果进行不一样的字段抽取来解决申请复用问题。 数据查问创立创立数据查问的过程与数据库相似,可参考之前段落。 点击新建数据查问,抉择曾经创立的数据源,以及创立的数据表,而后编写SQL,如下图: 须要留神的是,这里是不反对连表查问,由Http数据源创立的数据表只能在单表中查问。此外,上述应用的是Spark的SQL语法,底层是应用Spark引擎进行SQL剖析和解决的,书写SQL时须要留神。 设置参数的操作以及如何将数据查问利用在组件上进行展现在上文中曾经形容过,此处不再赘述。 结语开源数据可视化编排平台FlyFish是一款功能强大且易于应用的数据可视化工具,可能帮忙用户将大量的数据转化为直观、易于了解的图表和图形。作为一个全面的数据可视化解决方案,该平台不仅提供了丰盛的可视化选项,还反对多种数据源的利用技术。 至此,置信各位开发者对如何在FlyFish平台新增数据源,以及如何在数据源中获取本人想要的数据并利用于组件中,应该有了大抵的理解。心动不如口头,点击下方链接,快来通过FlyFish搭建属于本人的一套数据可视化大屏吧! GitHub 地址: https://github.com/CloudWise-OpenSource/FlyFish ...

May 29, 2023 · 1 min · jiezi

关于大前端:前端设计走查平台实践前端篇

我的项目背景 随着前端业务的一直倒退,前端对设计稿的还原水平也成为了影响用户对产品体验的一个要害指标,作为最靠近用户侧的研发,前端工程师通常须要和设计师同学通力配合来晋升用户体验。其中,设计走查是设计同学最常见的测试前端同学是否完满还原了本人设计理念的形式,本文旨在通过设计走查平台在前端侧的实际总结下在前端上游研发链路中的一些根底建设,以期可能为其余有相干须要的同学提供一些实际思路。 计划 一个前端工程师的次要指标是寻找一款贴近浏览器原生的框架,svelte 是你不二的抉择。前端架构选型,从整体的产品业务状态来看,属于较为简单的繁多页面状态,并且思考到要反对浏览器的插件生态,因此前端局部抉择应用了svelte的框架计划。抉择 svelte 作为本业务的前端技术选型次要思考到以下两方面起因:一是思考到业务状态较为简单,只有一个上传图片的页面;二是因为浏览器插件相干的编写还是更加偏差原生js一些,应用大型框架有些大材小用。综合近几年 svelte 的迅猛发展,小型业务还是思考应用它作为一个框架应用的,其在编译时利用位掩码做的脏值查看的思路其实还是能够作为框架开发者借鉴的一个思路的(ps:对这个感兴趣的同学,能够看一下新兴前端框架 Svelte 从入门到原理这篇文章的介绍),然而目前倒退绝对还是比拟初期,整个生态绝对还不够欠缺,同时也是给宽广开发者提供了很好的蓝海空间,比方:目前还没有呈现相似 Element UI 和 Ant Design 这种非常好用的组件库零碎,尽管有几个,然而个人感觉很不好用,作者在本我的项目中对须要用到的几个组件做了简略的封装,有须要的同学能够参考借鉴一下。 目录public buildbg.jpegfavicon.pngglobal.cssindex.htmlmanifest.jsonscripts setupCrxScript.jssetupTypeScript.jssrc components Button.svelteDialog.svelteIcon.svelteInput.svelteMessage.svelteTooltip.svelteUpload.svelteutils function.jsimage.jsindex.jsApp.sveltemain.jsrollup.config.js实际 设计走查平台提供了治理平台及对应的Chrome插件,可提供给测试及UI同学用于图片的比对,晋升研发效率 源码 svelte作者--前端驰名的轮子哥Rich Harris,同时也是rollup的作者,因此本我的项目中就抉择了 rollup 作为打包构建的工具,同时为了将Chrome插件公布到内网中(ps:本我的项目次要用于我的项目外部基建利用,因此未在私有云及Chrome官网平台去公布,服务端波及到了图片的比对计算);在scripts目录下内置了两个脚本,一个用于生成ts,一个用于向云平台发送压缩包;因为 svelte 的组件库生态绝对不是特地丰盛(ps:业界常见曾经开源的 svelte 组件库能够参看这篇文章Svelte的UI组件库),比照了业界几个相干的组件库后,决定本人实现下业务中须要用到的组件,具体组件放在了components目录下 rollup.config.jsimport svelte from 'rollup-plugin-svelte';import commonjs from '@rollup/plugin-commonjs';import resolve from '@rollup/plugin-node-resolve';import livereload from 'rollup-plugin-livereload';import { terser } from 'rollup-plugin-terser';import css from 'rollup-plugin-css-only';const production = !process.env.ROLLUP_WATCH;function serve() { let server; function toExit() { if (server) server.kill(0); } return { writeBundle() { if (server) return; server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { stdio: ['ignore', 'inherit', 'inherit'], shell: true }); process.on('SIGTERM', toExit); process.on('exit', toExit); } };}export default { input: 'src/main.js', output: { sourcemap: true, format: 'iife', name: 'app', file: 'public/build/bundle.js' }, plugins: [ svelte({ compilerOptions: { // enable run-time checks when not in production dev: !production } }), // we'll extract any component CSS out into // a separate file - better for performance css({ output: 'bundle.css' }), // If you have external dependencies installed from // npm, you'll most likely need these plugins. In // some cases you'll need additional configuration - // consult the documentation for details: // https://github.com/rollup/plugins/tree/master/packages/commonjs resolve({ browser: true, dedupe: ['svelte'] }), commonjs(), // In dev mode, call `npm run start` once // the bundle has been generated !production && serve(), // Watch the `public` directory and refresh the // browser on changes when not in production !production && livereload('public'), // If we're building for production (npm run build // instead of npm run dev), minify production && terser() ], watch: { clearScreen: false }};scriptssetupCrxScript.js通过minio这个库来进行公有云平台的对象存储库上传,archiver这个次要用于压缩 ...

September 27, 2022 · 10 min · jiezi

关于大前端:开源星001-号落地-FlyFish欢迎登陆赢神秘大礼包

前言往年 5 月 6 日,腾讯·腾源会社区联结 FlyFish 等在内的 80 余家开源社区、国内外开源基金会等,独特发动「开源摘星打算」。发展 3 月以来,咱们累计为近百位优良摘星贡献者,送出激励大礼包 300 余份;同时为 700 位的开源爱好者搭建了独特的交换乐园,帮忙很多人实现了从开源萌新到「过来人」的成长、变质。 明天,「开源摘星打算」持续「001号」工作摸索,船长登陆,心愿能和 FlyFish 星开掘新一批的优良摘星者,独特将 FlyFish 星建设得更好以下是船长发来的火线信号…… Hi,各位开源爱好者,大家好! 我是「开源摘星号」飞船船长小源 很快乐今日起飞 FlyFish 星 执行「开源星球」001 号工作 在 FlyFish 星上 我投递了有数的能量块 侥幸的你只有从今日开始收集 上面这些非凡能量块 就有机会取得我在 8 月为你筹备的登陆礼包 (证书、奉献卡、鹅厂周边、盛典入场券……) 残缺参加攻略欢送查看 FlyFish 星「能量块」介绍FlyFish代码仓库地址 FlyFish 是云智慧公司自主设计、研发的一款低门槛、高拓展性的低代码利用开发平台, 为数据可视化开发场景提供了高效的一站式解决方案。飞鱼提供丰盛的组件和利用模板库, 可通过利落拽的模式实现数据可视化开发,零开发背景的用户也可实现数据可视化开发工作。 同时,飞鱼也提供了灵便的拓展能力,反对组件开发、自定义函数与全局事件等配置, 面向简单需要场景可能保障高效开发与交付。 应用形式一: 线上Demo环境体验应用形式二: 本地下载部署应用能量块 1: 文档修复 具体阐明: 通过体验FlyFish发现并欠缺FlyFish官网技术文档问题,并提交PR。 难度: 10 积分 工作详情: https://github.com/CloudWise-... 能量块2: 体验报告 具体阐明: 应用 FlyFish 并输入无效体验报告并公布至云智慧AIOps社区 难度: 10 积分 工作详情: https://github.com/CloudWise-... 能量块3: BUG 修复 ...

August 9, 2022 · 1 min · jiezi

关于大前端:大前端2022版全面升级某课完结

download:大前端2022版全面降级某课完结线段树(动静开点)的两种形式题目描述Tag : 「线段树(动静开点)」、「线段树」实现一个 MyCalendar 类来存放你的日程安排。如果要增加的工夫内不会导致三重预订时,则可能存储这个新的日程安排。MyCalendar 有一个 book(int start, int end) 方法。它意味着在 start 到 end 工夫内减少一个日程安排,注意,这里的工夫是半开区间,即 [start,end)[start, end)[start,end), 实数 xxx 的范畴为, start<=x<end start <= x < end start<=x<end。当三个日程安排有一些工夫上的交叉时(例如三个日程安排都在同一时间内),就会产生三重预订。每次调用 MyCalendar.book 方法时,如果可能将日程安排胜利增加到日历中而不会导致三重预订,返回 true。否则,返回 false 并且不要将该日程安排增加到日历中。请按照以下步骤调用 MyCalendar 类: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end)示例:MyCalendar();MyCalendar.book(10, 20); // returns trueMyCalendar.book(50, 60); // returns trueMyCalendar.book(10, 40); // returns trueMyCalendar.book(5, 15); // returns falseMyCalendar.book(5, 10); // returns trueMyCalendar.book(25, 55); // returns true 解释: 前两个日程安排可能增加至日历中。 第三个日程安排会导致双重预订,但可能增加至日历中。第四个日程安排流动(5,15)不能增加至日历中,因为它会导致三重预订。第五个日程安排(5,10)可能增加至日历中,因为它未使用已经双重预订的工夫10。第六个日程安排(25,55)可能增加至日历中,因为工夫 [25,40] 将和第三个日程安排双重预订;工夫 [40,50] 将独自预订,工夫 [50,55)将和第二个日程安排双重预订。复制代码提醒: ...

July 19, 2022 · 6 min · jiezi

关于大前端:从开源模型框架到自研声网-Web-端虚拟背景算法正式发布

依据钻研发现,在均匀 38 分钟的视频会议外面,大略会有 13 分钟左右的工夫用于解决和烦扰相干的事件。同时钻研也表明在加入在线会议的时候,人们更加偏向于语音会议,其中一个要害起因就是大家不心愿个人隐私裸露于公众的视线。 如何在视频会议中突出演讲者,缩小背景当中的烦扰信息,并晋升人们对视频会议的参加激情成为了实时音视频技术所要解决的问题,而实时虚构背景正是一项这样的技术。不同于绿幕等传统技术手段,虚构背景通过机器学习推理对实时视频内容当中的人像进行宰割,实现对人像外内容的替换。因而用户无需对事实环境中的背景进行安排即可应用,具备便捷高效的长处。 2021 年 8 月,声网落地了基于 Web SDK 的第一个虚构背景插件版本,实现了背景替换与背景虚化性能。在近期公布的虚构背景插件更新中,该性能失去进一步晋升,目前已可反对图片虚构背景、基于 CSS 色值的纯色背景、3 档不同水平的虚化背景。机器学习推理引擎也从通用机器学习框架降级为 Agora AI 实现,不仅整体包增量从 3M 升高至 1M,运算性能实现了 30% 以上的进步,新的 API 也更为易用。 回顾声网 Web SDK 虚构背景性能的研发过程,次要经验了三个阶段: 第一阶段 开源模型 + 开源机器学习框架在这一阶段,咱们基于 MediaPipe selife 人像宰割模型和TFlite机器学习框架实现了虚构背景在 Web 平台的工程化实际。实现了从图像采集、实时处理到编码发送的残缺管线。在这一个过程中,咱们对影响解决性能的关键因素进行了大量剖析,并对这些性能瓶颈进行了针对性的优化。同时咱们也对不同机器学习框架在 Web 人像宰割的利用场景进行了定制和优化,这其中包含对 MediaPipe 和 TFlite 框架的定制。 MediaPipe 应用 TFlite 作为机器学习推理引擎,MediaPipe 的 TFlite 人像宰割模型所应用的算子除了蕴含 TFlite 反对的通用算子,还蕴含 MediaPipe 提供的非凡算子。在实践中,咱们将 MediaPipe 人像宰割模型所依赖的 MediaPipe 非凡算子间接移植到 TFlite,实现了 selife segmentation 模型脱离 MediaPipe 框架间接在 TFlite 上的运行。同时应用自研 WebGL 算法代替 Mediapipe 提供的图形处理性能。这样就打消工程对 MediaPipe 的依赖,不仅升高了 MediaPipe 带来的整体包增量,同时使机器学习运算和图像处理解耦,整体计划更具灵活性。 ...

May 6, 2022 · 1 min · jiezi

关于大前端:建议收藏总结了42种前端常用布局方案

作者:一碗周 原文链接:https://juejin.cn/post/702896... 著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。 对CSS布局把握水平决定你在Web开发中的开发页面速度。随着Web技术的一直变革,实现各种布局的形式曾经多得不可胜数了。 本篇文章总结了四十二种CSS的常见布局,这四十二种布局能够细分为如下几类: 程度居中垂直居中程度垂直居中两列布局三列布局等分布局Sticky Footer布局全屏布局这些内容也正是本篇文章的目录。 程度居中实现程度布局比较简单,办法也比拟多,这里总结了7种罕用的布局办法,其公共的CSS代码如下所示: .parent { background: #ff8787; }.child { height: 300px; width: 300px; background: #e599f7; }复制代码其HTML构造也是固定的,就是一个父级,其宽度继承了<body>的宽度,还有一个子级,这里是固定的300px*300px,代码如下: <div class="parent"> <div class="child"></div></div>复制代码最终的实现成果如下: 上图中玫瑰色的块是父级,随页面宽度减少的;淡紫色是子级,绝对于父级居中的。 1. 应用text-align属性若元素为行内块级元素,也就是display: inline-block的元素,能够通过为其父元素设置text-align: center实现程度居中。实现的CSS代码如下: .parent { /* 对于子级为 display: inline-block; 能够通过 text-align: center; 实现程度居中 */ text-align: center;}.child { display: inline-block;}复制代码2. 定宽块级元素程度居中(办法一)对于定宽的的块级元素实现程度居中,最简略的一种形式就是margin: 0 auto;,然而值得注意的是肯定须要设置宽度。 实现CSS代码如下: .child { /* 对于定宽的子元素,间接 margin:0 auto; 即可实现程度居中 */ margin: 0 auto;}复制代码3. 定宽块级元素程度居中(办法二)对于开启定位的元素,能够通过left属性 和margin实现。 实现CSS代码如下: .child { /* 开启定位 */ position: relative; left: 50%; /* margin-left 为 负的宽度的一半 */ margin-left: -150px;}复制代码4. 定宽块级元素程度居中(办法三)当元素开启决定定位或者固定定位时,left属性和right属性一起设置就会拉伸元素的宽度,在配合width属性与margin属性就能够实现程度居中。 ...

April 13, 2022 · 8 min · jiezi

关于大前端:FlyFish-20已发布大屏开发应用更加灵活便捷

云智慧数据可视化编排平台-FlyFish 自开源至今已有2个月啦!在这期间,这款具备低门槛、高拓展性的利用开发平台,不仅为用户提供了数据可视化一站式解决方案,还取得了中国云联盟优良开源我的项目奖,并成为Gitee最有价值开源我的项目(GVP)。与此同时,在云智慧AIOps社区中,因FlyFish汇聚了一群酷爱开源与技术的小伙伴,与他们一起交流学习更是让FlyFish吸取了泛滥贵重倡议和反馈。近期,通过降级与优化后,FlyFish2.0版本正式公布。 较大扭转:FlyFish 2.0 将拆分为组件开发和数据利用两个平台;精细化分工,使得大屏的开发和利用更加专一和高效。 新增性能:组件开发平台用于组件开发及组件积淀,组件开发平台的独立将更有利于组件的开发及灵便的拓展与保护。 新增组件分类性能,反对组件分类管理,反对组件筛查。反对组件组织批改,依据组件的类型、应用范畴等更改组织类别。新增组件导入导出性能,便于组件灵便分享和接入。反对组件共用;一个组件开发平台能够对接多个利用平台。反对组件下载和导入;已下载的组件可导入数据利用平台。升高组件占用空间;导入到数据利用平台的组件体积更小。数据利用平台用于大屏的开发和利用;减少了标签性能,更为便捷的治理大屏。 新增标签治理性能;创立大屏可抉择预设标签,使大屏的分类管理更加直观便捷。新增可视化组件模块;反对组件封面上传,组件展现更加直观,反对组件二次更新。新增组件:视频组件 按钮-1组件 按钮-2组件 导航栏-1组件 导航栏-2组件 降级形式:FlyFish 2.0 需重新安装部署,可参考下列步骤,点击 “浏览原文” 获取我的项目地址。 组件开发平台部署文档配置文件批改 1.进入我的项目 cd component_platformnpm install2.初始化数据库配置 本地:pm2 run init_database_dev开发:pm2 run init_database_development测试:pm2 run init_database_staging生产:pm2 run init_database_production在线编辑器服务启动 1.clone 仓库 ssh : git clone ssh://git@git.cloudwise.com:36000/FlyFish/code-server.githttps : git clone https://git.cloudwise.com/FlyFish/code-server.git[2.如在本地开始,须要批改vscode编辑器文件门路] 批改本地web代码,path:component_platform_web/CodeEditor.jsx批改codeServerUrl folder参数为组件所在目录3.批改配置文件 vi ~/.config/code-server/config.yaml{ bind-addr: 0.0.0.0:8080 // 可应用localhost:8080 或者 127.0.0.1:8080拜访 auth: none // 删除明码登录}3.装置依赖 npm i pm2 -g4.启动 mac: npm run macos-startlinux: npm run linux-start启动/进行 //启动本地:pm2-dev-start开发:pm2-development-start测试:pm2-staging-start生产:pm2-production-start//重启本地:pm2-dev-restart开发:pm2-development-restart测试:pm2-staging-restart生产:pm2-production-restart//从新加载本地:pm2-dev-reload开发:pm2-development-reload测试:pm2-staging-reload生产:pm2-production-reload//进行本地:pm2-dev-stop开发:pm2-development-stop测试:pm2-staging-stop生产:pm2-production-stop数据利用平台部署文档配置文件批改 1.进入我的项目 ...

December 17, 2021 · 1 min · jiezi

关于大前端:技术干货前端性能优化快速定位代码bug

分享人:Mark Wu( 吴银波 )云智慧前端工程师,致力于云智慧大屏产品及ITSM、DOMM、DOEM等产品线定制化开发,领有丰盛的前端性能优化和开源我的项目教训。背景介绍:不晓得你有没有碰到过这些状况: 被告诉下周一前肯定要解决某个bug,当初曾经是周五下午了;上线封版前一天被告诉客户机器性能不行,打不开某个页面,过后曾经是早晨10点了;早晨2点接到电话,某个零碎当初运行不起来,然而今天要给客户领导演示,而后你还没带电脑回家...如果你也有这些状况,那么祝贺你,这只是开始... 如果没有,那么也祝贺你,你迟早会遇到的... 那么, 如果咱们可能找到一些疾速定位问题的办法,那大概率能够防止这样的问题,大幅提高效率。 联合具体的示例来分享一下我是如何利用Performance性能面板和console面板来定位问题的,开端也和大家分享一个应用这个办法优化后造出的轮子。 一、Performance性能剖析面板当初看一下Performance性能剖析报告: 能够看到时间轴上面蕴含FPS、CPU、网络等;这一块次要 关注FPS,察看有没有飘红的区域,可定位到上面的Main指标对应的js执行过程,察看程序哪局部影响了页面性能,这能帮忙咱们疾速确定须要优化的代码地位; 还应关注总 阻塞工夫,这是对以后页面运行是否晦涩的一个总体评估,应尽可能减少阻塞工夫; 最初关注 摘要局部,比照正在执行脚本与渲染工夫,确定JS执行和页面渲染哪个为次要优化对象(优化往往是两者并行)。 上面两个示例别离偏重JS执行效率和页面渲染效率进行优化,JS执行效率次要升高代码空间复杂度,缩小不必要的内存开销,防止深拷贝,及时革除定时器等;页面渲染效率次要缩小页面重排次数,尽量同步页面动画与显示器帧数刷新。 二、JS执行性能优化示例呈现问题DOMM定制化我的项目:现场某场景内G6拓扑组件节点数量一多,浏览器假死,开发环境无奈重现。 剖析:页面假死通常是js线程阻塞、栈内存溢出,或者是页面动画过于简单导致css线程卡死、频繁布局抖动等造成的。 Performance剖析: 从上图能够看到js执行工夫比拟长,渲染工夫占用比拟短。这种状况先排除css线程以及布局抖动的影响,确定问题是在JS执行上。并且在页面性能优化时针对这种状况想要再去较大地优化页面渲染效率是很难也是不划算的,这个时候的重点也是在JS执行效率上。 应用console打印各环节工夫耗费,确定问题代码通过对于Performance的Main进行剖析并联合代码剖析,确定问题代码区域,在代码执行次要节点上打印工夫耗费,针对耗时较大的区域代码进行细化,最终确定问题代码。 计算耗时打印 耗时打印状况: 剖析:能够看到这部分JS代码总执行时长1027ms,其中计算节点、计算连线耗时最长,而且反复执行了两次,设置防抖函数。 剖析:设置防抖后,此段JS总执行时长599ms,持续细化“计算连线”局部耗时打印。 细化耗时打印: a、 “ 连线计算 ” 耗时过长 剖析:“计算连线”段JS代码被屡次援用,持续细化这部分耗时打印; b、单次连线耗时 剖析:“连线耗时”为计算单次节点间连线耗时,大量执行且单次耗时不短,对此局部代码持续细化,发现存在可疑的代码--深拷贝。 c、深拷贝耗时 剖析:“克隆耗时”的打印法则和“连线耗时”相当,且存在耗时较长问题,应用累加计时打印深拷贝总体耗时。 剖析:深拷贝累加有三次打印,总耗时679ms,占比很大。 耗时定位:每次深拷贝耗时较长,深拷贝算法须要优化或者连线计算逻辑避开深拷贝 剖析:拷贝层级过深,造成耗时较长,应用浅拷贝代替。 优化深拷贝耗时后打印 剖析:应用浅拷贝打印总耗时6ms,绝对于原来的679ms耗时很短。 动画渲染剖析当初不能确定现场部署就没有问题,再来看看拓扑节点数量对于JS执行以及页面渲染效率的影响。 i 加载200个节点前端渲染耗时 ii 加载1个节点前端渲染耗时 剖析:能够看到200节点与单节点页面渲染耗时相差不大,次要是执行JS脚本多了25ms,因为现场最大会有800多个节点的状况,简略计算了下,发现耗时比照原先的1027ms仍有很大晋升。 三、动画渲染性能优化示例遇到问题:之前开发一张大屏,本地跑没有问题,然而联调测试发现右侧的滚动组件模块(有4个)中有一个模块没有货色,接口失常返回,字段也是失常的。最初发现是接口返回了190多条数据,前端全副渲染了这些组件,以致模块假死。 先看下现场效果图。左侧别离是地图、轮播图、饼图、轮播图,两头下面是两个拓扑链路图轮播,上面是4个echarts图表,右侧是4个滚动模块(图片不全)。当初除了要解决上述问题还得做好整张大屏的加载同步。 现场大屏的展现成果↓ 剖析:当初来看这个问题,既然全副加载会导致模块假死,那就不加载全副,而是采纳过一条渲染一条(onebyone)形式,当初演示单个成果: onebyone模式 单模块成果 注:绿框为可视区域,红框为滚动组件,渲染固定数量的滚动单位,利用css管制页面动画,定时刷新对应的滚动单位。 onebyone模式 单模块Performance剖析面板 ...

December 7, 2021 · 1 min · jiezi

关于大前端:如何优雅地操作数据库ORM了解一下

写作不易,未经作者容许禁止以任何模式转载!如果感觉文章不错,欢送关注、点赞和分享!继续分享技术博文,关注微信公众号  前端LeBron原文链接什么是ORM 对象关系映射(Object Relational Mapping,简称ORM),是一种程序技术,实现面向对象编程语言中的内存对象与关系型数据库中的业务实体之间的关系映射。这样在咱们操作数据库的时候,不再须要和简单的SQL语句打交道,只须要简略地操作对象的属性和办法就能够间接实现对数据库中对应实体表的CRUD(增删改查)的操作。常见的ORM框架有Node.js 的TypeOrm、Sequlize,Java的Hibernate、Mybatis和Go的Gorm、GoRose等。 ORM的方法论基于三个外围准则 简略:以最根本的模式建模数据传播性:数据库构造被任何人都能了解的语言文档化精确性:基于数据模型创立正确、标准化的构造为什么会呈现ORM面向对象编程语言和关系型数据库都是目前最风行的技术,但他们的模型是不一样的。简直所有的程序外面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,咱们是面向对象的。当对象信息发生变化的时候,咱们须要把对象的信息保留在关系数据库中。以 MVC 分层模式为例。Model 作为数据承载实体,在用户界面和业务逻辑层之间,数据以面向对象的模式传递;而当咱们须要通过 Controller 散发申请把数据长久化的时候,咱们就遇到了内存中的对象如何长久化成关系数据库中存储的一条理论数据记录的问题。面向对象是从软件工程的根本准则,即封装,继承,多态的根底上倒退起来的;而关系型数据库则是从数学实践的根底上倒退起来的,两者之间是不匹配的。所有就呈现了 ORM 以我的项目中间件的模式实现数据在不同场景下的数据关系映射。。而对象关系映射就是这样一种为了解决面向对象与关系数据库存在的互不匹配的景象的技术。在其根底上诞生很多对象和关系之间的映射框架,也即ORM技术。ORM的应用 以Sequelize为例仅示例,更多操作可参考Sequelize 中文文档RobinBuschmann/sequelize-typescriptSequelize 是一个基于 Promise 的 Node.js ORM, 目前反对 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具备弱小的事务反对, 关联关系, 预读和提早加载,读取复制等性能。 Sequelize 听从 语义版本控制。 反对 Node v10 及更高版本以便应用 ES6 性能。 连贯数据库设置应用sequlize插件,并配置要连贯的数据库定义Model通过面向对象Class 和 关系型数据库的表建设连贯 @Column 示意数据库的一列 @PrimaryKey 示意主键 import {  Column,  Model,  PrimaryKey,  Table,} from '@gulu/sequelize/typescript';enum GameType {  micro_game = 'micro_game',  mobile_game = 'mobile_game',  micro_app = 'micro_app',}@Table({ modelName: 'game', timestamps: false })export default class GameModel extends Model {  @PrimaryKey  @Column  gameId!: string;  @Column  name!: string;  @Column  description?: string;  @Column  type!: GameType;  @Column  icon?: string;  @Column  isDelete!: number;}操作数据库通过Model的办法操作数据库import GameModel from '../model/game';// 游戏列表查问服务async query() {  return GameModel.findAll({    // 去除软删除字段    attributes: {      exclude: ['isDelete'],   },    // 查问未被软删除的游戏    where: {      isDelete: 0,   }, });}相当于以下SQL语句select gameId, name, description, type, icon from game where isDelete = 0;当然Sequlize也反对SQL语句查问import GameModel from '../model/game';// 游戏列表查问服务async query() {  return GameModel.sequelize.query(      'select gameId, name, description, type, icon from game where isDelete = 0', );}ORM的优缺点长处暗藏了数据拜访的细节,“关闭”的通用数据库交互是ORM的外围。他使得咱们的通用数据库交互变得简单易行,并且齐全不必思考SQL语句。开发效率更高,ORM使咱们结构固化数据变得简单易行,在ORM诞生前,咱们须要见过咱们的对象模型转化为一条一条的SQL语句,通过直连或者是DB helper在关系数据库结构咱们的数据库体系。而当初,基本上所有的ORM框架都提供了通过对象模型结构关系数据库构造的性能。数据拜访更形象、轻便,反对面向对象封装。数据模型都在一个中央定义,更容易更新和保护,也利于重用代码ORM有现成的工具,很多性能都能够主动实现,比方数据消毒、预处理、事务等等。它迫使你应用MVC架构,ORM就是人造的Model,最终使代码更清晰。基于ORM的业务代码比较简单,代码量少,语义性好,容易了解。防备SQL注入攻打不用编写性能不佳的SQL。毛病无可避免的,自动化意味着映射和关联治理,代价是就义性能。当初的各种ORM框架都在尝试应用各种办法来加重性能上的损失,如懒加载技术、缓存技术等。面向对象的查询语言作为一种数据库与对象之间的过渡,尽管暗藏了数据层面的业务形象,但并不能齐全屏蔽数据库层的设计。ORM库也不是轻量级的工具,须要花很多精力学习和设置,无疑将减少学习老本。ORM难以实现过于简单的查问。尽管能够实现,然而须要破费很大的代价(性能不如原生SQL)。长久化层不足弹性,一旦呈现业务需要变更,就必须批改长久化层的接口长久化层同时与域模型与关系数据库模型绑定,不论域模型还是关系数据库模型发生变化,都要批改长久化层相干程序代码,减少了软件的保护难度。什么是“长久化” 层长久(Persistence),即把数据(如内存中的对象)保留到可永恒保留的存储设备中(如磁盘)。长久化的次要利用是将内存中的数据存储在关系型的数据库中,当然也能够存储在磁盘文件中、XML数据文件中等等。总结:当下ORM的开发模式是支流,进步了代码的封装性和可读性,同时防备了SQL注入攻打。以较小量级的性能损失换来了显著的开发效率晋升,显著的性能损失往往存在于简单的查问,这种状况能够抉择应用ORM提供的SQL语句接口进行查问以优化性能。原文链接掘金:前端LeBron知乎:前端LeBron继续分享技术博文,关注微信公众号  前端LeBron

August 11, 2021 · 1 min · jiezi

Nodejs到底是什么

接触前端也有一段时间了,逐渐开始接触Node.js,刚刚接触Node.js的时候一直都以为Node.js就是JavaScript,当对Node.js有一定的了解之后,其实并不然两者之间有关系,其中的关系又不是必然的,对Node.js进行的一些了解,对其进行一些概述,本篇文章并没有对Node.js的API进行讲解,而是能够更加的明白Node.js是什么。 到底什么是Node.js先看一下Node.js官网中是如何形容Node.js的,打开官网看到的第一句话就是Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.(Node.js是一个JavaScript运行时建立在Chrome的V8 JavaScript引擎。)在上面这段话中最重要的一点就是运行时。 到底什么是运行时呢?其实在笔者看来运行时就是程序在运行时所需要的组件,可以将其想象成为是一种编程语言的运行环境。然而这个运行环境包含了代码运行时所需要的解释器和底层操作系统的支持等。 文章开头也说过Node.js与JavaScript之间有关系,但是其关系也不是必然,到这里大概也就有点眉目了。对于任何语言来说,其中最终要的就是其解释器如何去处理这些编程语言。Node.js的底层是使用C++实现的,然而语法则是遵循ECMAScript规范,其实完全可以把其实现换乘一种新的编程语言,更换语言的同时也就意味着其解释器发生了翻天覆地的变化。 Node.js为什么要选择JavaScript到了这里可能有些疑问,编程语言和解释器有关系,那么为什么要选择了JavaScript然而不是其他的语言呢?Node.js作者(Ryan Dahl)说,在创造Node.js的时,其目的是为了实现高性能的Web服务器,其看重的并不是JavaScript这门语言。但是他需要的事一种编程语言来实现其想法,这种编程语言不能带有任何的IO功能,并且需要良好的支持事件机制。说到这里感觉就是在说JavaScript这门语言(感觉就是天命之选,O(∩_∩)O哈哈~)。首先JavaScript完全满足上述的两个条件,然而就顺其自然的JavaScript就成了Node.js的主导者。 Runtime上面一直提到的就是Runtime,Runtime是什么?运行时刻是指一个程序在运行(cc或者在被执行)的状态。也就是说,当你打开一个程序使它在电脑上运行的时候,那个程序就是处于运行时刻。在一些编程语言中,把某些可以重用的程序或者实例打包或者重建成为运行库。这些实例可以在它们运行的时候被链接或者被任何程序调用(节选自百度百科)。 其实对于开发者来说根本就不用去考虑其背后到底是怎样实现的,我们站在开发的角度来想一想,对于某一种语言的Runtime表示开发者可以在Runtime上运行某种语言所编写的代码,如果把这个概念扩大一下说的话,Chorome也是一个JavaScript运行时依赖于背后的JavaScript引擎来运行JavaScript代码而已。 其对应的Runtime可以对其编程语言进行一些拓展,比如在Node.js中的fs、Buffer就是其对ECMAScript的拓展,Runtime并不包含整个ECMAScript中的全部特性。反过来讲,就算一个特性没有体现在标准里,而大多数的运行时都支持它,也可以变成实际上的规范。通过上述所说我们可以理解到对于任何语言来讲我们无需对其底层的实现,所有的东西都依赖于其运行时的实现而已,运行时环境对其支持情况才能表现出其语言的特性。 同样的一段代码可能在浏览器端可以顺利执行,但是放到Node.js中不一定可以顺利执行,反之也是一样的,这样的就足可以说明上述问题了。 Node.js内部机制Node.js中有几个很重要的关键词单线程,非阻塞异步IO,在笔者刚刚接触Node.js的时候,这几个词经常听到,有些懵懵懂懂不是太能理解。为了更好的了解其内部机制那么针对这些东西进行说明。 回调函数为什么要说回调函数呢?对Node.js模块有一定了解的话Node.js中模块都是依赖于回调函数的,那么什么是回调函数呢? 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。(节选自百度百科)。 上面说了一堆套话,其实回调函数就是讲一个函数作为参数传给另一个函数作为参数,并且该函数可以被执行。回调方法和主线程处于同一个线程,假设主线程发起了一个底层的系统调用,操作系统会执行这个系统调用,当这个系统调用完成之后则会再回到主进程去执行后续的方法。 在Node.js中在操作过程中可能会有一个比较耗时的IO操作,当IO操作有了返回结果之后才会继续向下执行,其中在进行IO操作时就造成了代码的阻塞,在Node.js最初设计的时候已经考虑到了这一点,所以提出了异步函数加回调函数的方式,也能实现高并发的处理。对于前端来讲Ajax就是一个异步回调函数,当发起请求时如果有后续代码会先向下继续执行,而不会等待期请求结果。 回调函数机制: 定义一个回调函数;提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。同步/异步有关于同步/异步也搜索了一些文献,但是都是简简单单概括一下,没有细致的说明。所谓同步和异步其描述的事进程和线程的调用方式。因为Node.js的单线程,因此同个时间只能处理同个任务,所有任务都需要排队,前一个任务执行完,才能继续执行下一个任务,但是,如果前一个任务的执行时间很长,比如文件的读取操作或网络请求,后一个任务就不得不等着,拿文件的读取操作来说,当用户向后台读取大量的文件时,不得不等到所有数据都读取完毕才能进行下一步操作,后续程序只能在那里干等着,很有可能造成响应超时。因此,Node.js在设计的时候,就已经考虑到这个问题,主线程可以完全不用等待文件的读取完毕,可以先挂起处于等待中的任务,先运行排在后面的任务,等到文件的读取有了结果后,再回过头执行挂起的任务,因此,任务就可以分为同步任务和异步任务。 同步任务:同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站时,网站的渲染过程,比如元素的渲染,其实就是一个同步任务异步任务:异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程,当我们打开网站时,像图片的加载,音乐的加载,其实就是一个异步任务上述所说同步调用指的是进程/线程发起调用后,一直等待调用结果返回后才会继续向下执行,但是对于Node.js来说虽然也是这样,但是并不代表的CPU在这段时间内也会一直等待,操作系统多半会切换到另一个进程/线程上等调用返回结果后在切回原有进程/线程。然而异步则恰恰相反,当发起异步调用时,进程/线程会继续向下执行,当调用返回结果后通过某种技术手段通知其调用者已经有其结果。 我们一直都在说的一句话就是JavaScript是一门异步语言,但是对于ECMAScript而言并没有对异步有明确的规范,其实是其解释器(Node.js或浏览器)的runtime的其他线程来实现的,这些并不是JavaScript这门语言本身的功能。 对于异步请参考:浅析JavaScript异步 阻塞/非阻塞笔者在没有了解阻塞/非阻塞之前一直以为同步/异步与阻塞/非阻塞之间是没有区别的,然而现实就是这么的打脸,阻塞/非阻塞和同步/异步完全就是两组概念,他们之间没有任何的必然关系。很多人大概和我一样同步=阻塞,异步=非阻塞,这种概念是完全不对的。 在了解阻塞与非阻塞之前首先要了解一下什么是IO操作,IO操作其实是内存与外部设备之间复制数据的过程。 在阻塞的情况,是会一直等待直到write完全部的数据再返回。这点行为上与读操作有所不同,究其原因主要是读数据的时候,通常刚开始我们并不知道要读的数据的长度,而是在数据的头部设置了一个长度,在读完指定长度的头部后,才知道整个要读的数据长度。如果一开始就贸然设置一个要读的数据长度,然后像阻塞的write那样去等读完,则很可能会造成死循环;而对于write,由于需要写的长度是已知的,所以可以一直再写,直到写完。不过问题是write是可能被打断造成write一次只write一部分数据,所以write的过程还是需要考虑循环write, 只不过多数情况下一次write调用就可能成功。 非阻塞写的情况,是采用可以写多少就写多少的策略。与读不一样的地方在于,有多少读多少是由网络发送端是否有数据传输到本地内核缓存为准。但是对于可以写多少是由本地的网络堵塞情况为标准的,在网络阻塞严重的时候,网络层没有足够的内存来进行写操作,这时候就会出现写不成功的情况,阻塞情况下会尽可能(有可能被中断)等待到数据全部发送完毕, 对于非阻塞的情况就是一次写多少算多少,没有中断的情况下也还是会出现write到一部分的情况。 其实用一句话来说讲的话,同步调用会造成进程的IO阻塞,而异步不会造成调用进程的IO阻塞。 单线程与多线程Node.js并没有提供多进程的支持,这代表在程序中所编写的代码只能运行在当前进程中,用于运行代码的事件也是单线程进行的。开发者无法在一个独立进程中增加新的线程吗,但是可以派生出多个进程来达到必行完成任务。 进程 进程是指在操作系统中正在运行的一个应用程序 线程 线程是指进程内独立执行某个任务的一个单元。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈)。 对于Node.js,如果说JavaScript的函数式编程方式使得其异步编程的思想对程序员展现得更自然,那么它背后的功臣Libuv,则为异步编程的实现提供了可能。 上图中从左往右分为两部分,一部分是与Network I/O相关的请求,而另外一部分是由File I/O, DNS Ops以及User code组成的请求。 从图中可以看出,对于Network I/O和以File I/O为代表的另一类请求,异步处理的底层支撑机制是完全不一样的。 对于Network I/O相关的请求, 根据OS平台不同,分别使用Linux上的epoll,OSX和BSD类OS上的kqueue,SunOS上的event ports以及Windows上的IOCP机制。 而对于File I/O为代表的请求,则使用thread pool。利用thread pool的方式实现异步请求处理,在各类OS上都能获得很好的支持。Libuv团队为什么要选择thread pool的机制。基本上原因不外乎编码和维护复杂度太高、可支持的API太少且质量堪忧、技术支持较弱,而用thread pool则很好地避开了这些问题。 Node.js的异步调用时由Libuv来支持的,以readFile为例的话,读取文件的系统调用是由Libuv来完成的,Node.js只负责调用Libuv所提供的接口就可以了,等结果返回后在执行对应的回调方法。 并行与并发自从Node.js出现后,JavaScript开始涉及后端领域,因为其出色的并发模型,被很多企业用来处理高并发请求。 ...

October 6, 2019 · 1 min · jiezi

Android屏幕适配方案分析

为什么要屏幕适配Android开发过程中我们常用的尺寸单位有px、dp,还有一种sp一般是用于字体的大小。但是由于px是像素单位,比如我们通常说的手机分辨例如1920*1080都是px的单位。现在Android屏幕分辨率碎片化720x1280、1080x1920、2280x1080,这就造成例如187px会在各个分辨率的机型上都是显示一样大小的,那肯定不是我们想要的效果,所以用px单位我们是难以达到适配效果的,那么为什么用dp可以呢? 使用px单位从左到右依次为 480 800、1080 1920、1440 * 2560 使用dp单位从左到右依次为 480 800、1080 1920、1440 * 2560 屏幕总宽度依次为 320dp、415dp、411dp 那么什么是dp?dp指的是设备独立像素,以dp为尺寸单位的控件,在不同分辨率和尺寸的手机上代表了不同的真实像素,比如在分辨率较低的手机中,可能1dp=1px,而在分辨率较高的手机中,可能1dp=2px,这样的话,一个187dp高度的控件,在不同的手机中就能表现出差不多的大小了。 dp如何计算成pxandroid中的dp在渲染前会将dp转为px,计算公式: px = density * dp;density = dpi / 160;px = dp * (dpi / 160);而dpi是根据屏幕真实的分辨率和尺寸来计算的,每个设备都可能不一样的。 由于density不是固定不变的,所以每个分辨率不同的设备他们的density都肯定不相等,这样就会造成每个设备的宽/高对应的总dp都是不同的,假设480 800分辨率的density是1.5,1080 1920分辨率的density是2.6,1440 * 2560分辨率的density是3.5。那么它们对应的宽度总dp = (宽度px) / density,分别为320dp、415dp、411dp。可以看出单位为dp的时候三个设备之间的差距就不是很大了,但是这样肯定还是不能满足我们对屏幕适配的要求的。下面来看看Android常见的三种比较成熟的屏幕适配方案,并分析这几种方案的优劣。 屏幕适配方案1.1 宽高限定符适配 设定一个基准的分辨率,也就是设计图对应的分辨率,其他分辨率都根据这个基准分辨率来计算,在不同的尺寸文件夹内部,根据该尺寸编写对应的dimens文件。 比如我们的设计图 375 * 667为基准分辨率 宽度为375,将任何分辨率的宽度整分为375份,取值为x1-x375高度为667,将任何分辨率的高度整分为667份,取值为y1-y667那么对于1080*1920的分辨率的dimens文件来说, x1=(1080/375)*1=2.88pxx2=(1080/375)*2=5.76pxy1=(1920/667)*1=2.87pxy2=(1920/667)*2=5.75px当代码里面引用高度为y_187,在APP运行时会根据当前设备分辨率去找对应xml文件中对应的高度,我们就可以按照设计稿上的尺寸填写相对应的dimens引用了,这样基本解决了我们的适配问题,而且极大的提升了我们UI开发的效率。 验证方案简单通过计算验证下这种方案是否能达到适配的效果,例如设计图上有一个宽187dp的View。 480 * 800 设计图占宽比: 187dp / 375dp = 0.498实际在480 800占宽比 = 187 1.28px / 480 = 0.4981080 * 1920 ...

May 6, 2019 · 2 min · jiezi

happyChat开发系列:使用websocket.io实现双向通信的乐聊大前端开发

一、前言乐聊是一个自己用websocket写一个完整的应用,虽然功能比较欠缺,但是实现了基本的文字聊天,以及群聊,私聊,机器人聊天等功能。因为这个自己做了PC端,无线端(手机端),以及使用cordova打包成一个android的apk。实现了一个大前端的项目,虽然现在android端还是有点有问题,在修改bug。二、websocket的原理介绍1、为什么需要websocket?因为 HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。2、简介websocket特点:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。其他特点包括:(1)建立在 TCP 协议之上,服务器端的实现比较容易。(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。(3)数据格式比较轻量,性能开销小,通信高效。(4)可以发送文本,也可以发送二进制数据。(5)没有同源限制,客户端可以与任意服务器通信。(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。三、websocket.io使用1、前端在vue项目中,在index.html中 <script src=“https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script><script> // const socketWeb = io(‘http://localhost:3000’); const socketWeb = io(‘http://chat.chengxinsong.cn’); const userInfo = JSON.parse(sessionStorage.getItem(“HappyChatUserInfo”)) if (userInfo) { socketWeb.emit(‘update’, userInfo.user_id); }</script>2、后端后端是使用koa作为后端const app = new Koa();const server = require(“http”).createServer(app.callback());const io = require(“socket.io”)(server);io.on(“connection”, socket => { const socketId = socket.id; /登录/ socket.on(“login”, async userId => { await socketModel.saveUserSocketId(userId, socketId); }); // 更新soketId socket.on(“update”, async userId => { await socketModel.saveUserSocketId(userId, socketId); }); //私聊 socket.on(“sendPrivateMsg”, async data => { const arr = await socketModel.getUserSocketId(data.to_user); const RowDataPacket = arr[0]; const socketid = JSON.parse(JSON.stringify(RowDataPacket)).socketid; io.to(socketid).emit(“getPrivateMsg”, data); }); // 群聊 socket.on(“sendGroupMsg”, async data => { io.sockets.emit(“getGroupMsg”, data); }); //加好友请求 socket.on(“sendRequest”, async data => { console.log(“sendRequest”, data); const arr = await socketModel.getUserSocketId(data.to_user); const RowDataPacket = arr[0]; const socketid = JSON.parse(JSON.stringify(RowDataPacket)).socketid; console.log(‘给谁的socketid’,socketid) io.to(socketid).emit(“getresponse”, data); }); socket.on(“disconnect”, data => { console.log(“disconnect”, data); });});四、简介和功能乐聊,一个快乐聊天的应用,支持PC端和无线端和安卓APP。(1)PC端和无线端线上地址:http://chat.chengxinsong.cn(2)下载安卓APP地址:暂时还有点小问题待解决,后边放出地址版本v 1.0.0- 1、支持注册用户和邮件激活用户;- 2、支持登陆- 3、支持机器人聊天;- 4、支持加好友,一对一聊天;- 5、支持创建群,加群,一对多聊天;- 6、支持删除好友,退出群- 7、支持个人信息编辑- 8、支持添加好友备注- 9、支持聊天中文字发送- 10、支持浏览器:Chrome,Firefox,Safari,IE9及以上; 版本v 1.1.01、支持聊天中图片发送2、支持聊天中表情发送待续五、运行截图等等。。。六、前后端源码前端代码:https://github.com/saucxs/hap…后端代码:https://github.com/saucxs/hap…七、最后欢迎fork和star,有问题提issue ...

April 16, 2019 · 1 min · jiezi

【2019-03-29】记录过去一周看过觉得很好的文章

跨平台抓包工具,亲自测试并使用,总的来说就是配置非常简单好用,值得拥有Mobile Debug官方网站(代理抓包/移动端H5调试/请求劫持/HTTPS支持/Hosts管理/WebSocket数据捕获/跨平一个可以更好排版微信公众号工具微信公众号工具一个专门收集web的面试的栏目,很多也很全,无聊的时候刷一刷看一看自己还有那些还不会的工作日每天一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己。本文主要是将flutter在iOS和安卓中的实践以及遇到的问题,flutter是Google的又一个跨平台框架,主要是解决安卓和iOS不同系统带来的多成本和开发效率问题,目前国内已经又不少团队入坑,有兴趣可以玩玩。flutter实战Xcode 10.2发布,是和swift 5一起发的,主要是支持swift 5的开发 ,同时也新增了不少特性,解决了大量已存在问题。xcode 10.2这是网站有很多Mac系统应用,都是免费的,如果你在使用Mac,但是有些应用的付费的你又不想出钱,不妨来这里找找看有没有替代品或者是免费的。mac 免费下载ifunmac作者认为:良好的架构和优秀的实现。就像一个大的项目会拆分成很多模块一样,想要提高自己的编程能力也要拆分成很多小模块去达成。比如你的觉得你的命名不好,代码可读性差,你就去找这方面相关的资料去针对性的学习。可以看看《编写可读代码的艺术》《Clean code》。如果你觉得自己模块抽象能力不好,学习一下面向对象、设计模式之类的。如果本身这些具体模块的好坏自己不了解,直接学习一个优质项目也是囫囵吞枣。一个优质的项目应该具有什么特点swift5版本 正式更新,这是一个大版本更新。主要有:不再包含swift标准库的动态链接”瘦身app“;新增语言特性“#”解决字符串分隔符来带的转译混乱问题;在标准库中新增了simd类型和基本操作符以及set、dictionary等等;Swift5 更新预览Dio 是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等。目前Dio在pub上综合得分100分,排名已上榜pub首页(All Tab下) !同时Dio也是Github上最受欢迎的Flutter第三方库,项目地址:Dio-Github。Flutter Http库Dio 2.1正式发布flutter是一个由Google开发的跨平台框架,主要是解决iOS和安卓开发时由于使用不同不的语言导致开发成本和开发效率低的问题,当然也是顺应潮流,因为大前端是web端目前的大势,如果你先学习flutter不妨到这里的flutter光网看看,写个 hello worldflutter中文官网

March 29, 2019 · 1 min · jiezi

浅谈前端技术选型(一)

现在前端,都往大前端方向发展,pc, wapApp, 小程序,混合开发,桌面开发,node 后台。不光发展方向多,同一个方向的技术选型也同样多,比如wapApp的 vue,react,angular。那么问题来了,在项目中,我们到底应该如何展开我们的技术选型呢,我就结合我的经历讲一讲。所在项目组的技术原型为什么会有这个选型1.pcpc端我们要做推广,我当时考虑单页应用SEO不好做,而且页面几乎没有数据交互,不要为了单页应用而单页应用, 但是考虑到静态应用代码不能复用,就想到用 node模板引擎直接渲染。 访问速度应该还快一点(没做考究).2.h5h5, 我们已经有两个h5的项目,一个 vue ,一个 react。 但是最终还是选择 vue ,react 的包比较大,不利于前端快速加载,vue 相比于 react(dva 那一套) 的出活率高。而且国内vue确实火,小程序和混合开发相对应的解决方案都有,那么,就是他了。3.小程序小程序之前用原生的写过一个,用原生写不利于维护,感觉有点乱,就在两个 star 数高的、大公司维护的里面选 wepy 和 mpvue,mpvue 能生成对应的 wapAPP,并且合适 vue 的技术栈.在合适不过了。4.混合开发我们项目组是有安卓和ios的,但是有些内容ios 审核麻烦,所以要热更新。现在阶段,性能比较好的混合开发,就是 weex、 rn、 flutter。 1.weex: 阿里巴巴使用再生产环境的,国内比较友好,基于 vue ,性能可以,可以热更 2.rn: 脸书出品,近一年热度下降,基于 react, 性能可以,可以热更 3.flutter: 谷歌开源,基于 dart.js,因为实现方式,性能和体验应该比前两者好,不能热更,因为使用 dart.js 学习成本大 最终: flutter 不能热更 pass(解决不了最重要的需求); rn: 相对来说还是倾向于选择国内的技术,文档好理解,和统一客户端的技术栈(vue) pass。5.node 框架本人喜欢企业级的框架,特别是公司项目中,约定优于配置,降低维护成本,选择阿里 egg6.管理后台管理后台数据太多了,目前应该有100多个接口,vue 维护是个问题,而且阿里 ant design pro 很好用,就它了。总结:1.技术都是服务产品的,应该通过产品需求去选择技术 2.选择技术、要考虑社区活跃度,维护团队、文档、招聘相关人员是否容易等 3.尽量用少的技术栈去实现多的业务,降低人工成本 4.在公司项目中,尽量用企业级、大而全的框架(针对这一点,下次另开一篇,为什么我不用 大而全的angular,却用了渐进式的 vue?都有什么利弊?)

March 18, 2019 · 1 min · jiezi

一篇文章了解大前端

大前端是什么?简单来说,大前端就是所有前端的统称,比如Android、iOS、web、Watch等,最接近用户的那一层也就是UI层,然后将其统一起来,就是大前端。大前端最大的特点在于一次开发,同时适用于所有平台,开发者不用为一个APP需要做Android和iOS两种模式而担心。大前端是web统一的时代,利用web不仅能开发出网站,更可以开发手机端web应用和移动端应用程序。大前端为什么出现?由于node的出现,前端工程师不需要依赖于后端程序而直接运行,从而前后端分离起来。所以当开发一个新产品的时候服务只需要写一次,但是面向用户的产品可能有很多,例如网站、Android客户端、iOS客户端和微信小程序等。由于各个平台使用的技术栈都不一样,代码无法复用,非常浪费人力、物力。那么有没有什么技术能够解决这一痛点呢?大前端应运而生,其实大前端的主要核心就是跨平台技术,有了跨平台技术,各个平台的差异性就抹平了,开发者只需要一套技术栈就可以开发出适用于多个平台的客户端。跨平台方案简介目前的主流跨平台方案:Cordova/phoneGap、React Native、Weex、微信小程序、PWA和Flutter等,根据其原理性,可以分为三大类。H5+原生(Cordova、Ionic、微信小程序)JavaScript开发+原生渲染 (React Native、Weex、快应用)自绘UI+原生(Flutter)增强版Web App(PWA)接下来简单介绍这三种跨平台方案。H5+原生混合开发这种模式又称为Hybrid开发,现在很多App都用这种模式去开发,常见的有微信、淘宝、美团、爱奇艺等知名移动应用等。国内也有很多公司使用Hybrid模式去开发平台,供开发者使用,像Dcloud、AppCan、Inoic等,基本上都是参考Cordova衍生出的混合开发框架。这类框架主要原理就是将APP的一部分需要动态变动的内容通过H5来实现,通过原生的网页加载控件WebView (Android)或WKWebView(ios)来加载,H5部分是可以随时改变而不用发版,这样就解决了动态化的需求,同时,由于h5代码只需要一次开发,就能同时在Android和iOS两个平台运行,这也可以减小开发成本,我们称这种h5+原生的开发模式为混合开发。采用混合模式开发的APP我们称之为混合应用或Hybrid APP。由于原生开发可以访问平台所有功能,而混合开发中,h5代码是运行在WebView中,而WebView实质上就是一个浏览器内核,其JavaScript依然运行在一个权限受限的沙箱中,所以对于大多数系统能力都没有访问权限,如无法访问文件系统、不能使用蓝牙等。所以,对于H5不能实现的功能,都需要原生去做。而混合框架一般都会在原生代码中预先实现一些访问系统能力的API, 然后暴露给WebView以供JavaScript调用,这样一来,WebView就成为了JavaScript与原生API之间通信的桥梁,主要负责JavaScript与原生之间传递调用消息,而消息的传递必须遵守一个标准的协议,它规定了消息的格式与含义,我们把依赖于WebView的用于在JavaScript与原生之间通信并实现了某种消息传输协议的工具称之为WebView JavaScript Bridge, 简称 JsBridge,它也是混合开发框架的核心。混合应用的优点是动态内容是H5,使用web技术栈就可以开发,社区及资源丰富,缺点是性能不好,对于复杂用户界面或动画,webview不堪重任。JavaScript开发+原生渲染这类开源框架的代表主要是Facebook的React Native、阿里的Weex,当然也有未开源的美团的Picasso,以及最新推出的快应用。JavaScript开发+原生渲染的方式主要优点如下:采用Web开发技术栈,社区庞大、上手快、开发成本相对较低。原生渲染,性能相比H5提高很多。动态化较好,支持热更新。当然也有缺点如下:渲染时需要JavaScript和原生之间通信,在有些场景如拖动可能会因为通信频繁导致卡顿。JavaScript为脚本语言,执行时需要JIT,执行效率和AOT代码仍有差距。+由于渲染依赖原生控件,不同平台的控件需要单独维护,并且当系统更新时,社区控件可能会滞后;除此之外,其控件系统也会受到原生UI系统限制,例如,在Android中,手势冲突消歧规则是固定的,这在使用不同人写的控件嵌套时,手势冲突问题将会变得非常棘手。React NativeReact Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 React 在原生移动应用平台的衍生产物,目前支持iOS和Android两个平台。RN使用Javascript语言,类似于HTML的JSX,以及CSS来开发移动应用,因此熟悉Web前端开发的技术人员只需很少的学习就可以进入移动应用开发领域。React Native的原理和React设计一致,React中虚拟DOM最终会映射为浏览器DOM树,而RN中虚拟DOM会通过 JavaScriptCore 映射为原生控件树。JavaScriptCore 是一个JavaScript解释器,它在React Native中主要有两个作用:为JavaScript提供运行环境。是JavaScript与原生应用之间通信的桥梁,作用和JsBridge一样,事实上,在iOS中,很多JsBridge的实现都是基于 JavaScriptCore 。而RN中将虚拟DOM映射为原生控件的过程中分两步:布局消息传递; 将虚拟DOM布局信息传递给原生原生根据布局信息通过对应的原生控件渲染控件树由于React Native是原生控件渲染,所以性能会比混合应用中H5好很多,同时React Native是Web开发技术栈,只需维护一份代码,即可在多个平台上使用。WeexWeex是阿里巴巴于2016年发布的跨平台移动端开发框架,思想及原理和React Native类似,最大的不同是语法层面,React Native使用React.js作为开发框架,而Weex则使用Vue.js作为开发框架。Vue和React堪称前端领域最火的JavaScript框架,它们的易用性和功能性都非常强大,Weex在淘宝上也有广泛的应用。快应用快应用是华为、小米、OPPO、魅族等国内9大主流手机厂商共同制定的轻量级应用标准,目标直指微信小程序。它也是采用JavaScript语言开发,原生控件渲染,与React Native和Weex相比主要有两点不同:快应用自身不支持Vue或React语法,其采用原生JavaScript开发,其开发框架和微信小程序很像,值得一提的是小程序目前已经可以使用Vue语法开发(mpvue),从原理上来讲,Vue的语法也可以移植到快应用上。React Native和Weex的渲染/排版引擎是集成到框架中的,每一个APP都需要打包一份,安装包体积较大;而快应用渲染/排版引擎是集成到ROM中的,应用中无需打包,安装包体积小,正因如此,快应用才能在保证性能的同时做到快速分发。自绘UI+原生通过在不同平台实现一个统一接口的渲染引擎来绘制UI,而不依赖系统原生控件,所以可以做到不同平台UI的一致性。注意,自绘引擎解决的是UI的跨平台问题,如果涉及其它系统能力调用,依然要涉及原生开发。这种平台技术的优点如下:性能高;由于自绘引擎是直接调用系统API来绘制UI,所以性能和原生控件接近。灵活、组件库易维护、UI外观保真度和一致性高;由于UI渲染不依赖原生控件,也就不需要根据不同平台的控件单独维护一套组件库,所以代码容易维护。由于组件库是同一套代码、同一个渲染引擎,所以在不同平台,组件显示外观可以做到高保真和高一致性;另外,由于不依赖原生控件,也就不会受原生布局系统的限制,这样布局系统会非常灵活。不足之处:动态性不足;为了保证UI绘制性能,自绘UI系统一般都会采用AOT模式编译其发布包,所以应用发布后,不能像Hybrid和RN那些使用JavaScript(JIT)作为开发语言的框架那样动态下发代码。FlutterFlutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter提供了丰富的组件、接口,开发者可以很快地为 Flutter添加原生扩展。Flutter既不使用WebView,也不使用操作系统的原生控件。 相反,Flutter使用自己的高性能渲染引擎来绘制widget。这样不仅可以保证在Android和iOS上UI的一致性,而且也可以避免对原生控件依赖而带来的限制及高昂的维护成本。Flutter使用Skia作为其2D渲染引擎,Skia是Google的一个2D图形处理函数库,包含字型、坐标转换,以及点阵图都有高效能且简洁的表现,Skia是跨平台的,并提供了非常友好的API,目前Google Chrome浏览器和Android均采用Skia作为其绘图引擎,值得一提的是,由于Android系统已经内置了Skia,所以Flutter在打包APK(Android应用安装包)时,不需要再将Skia打入APK中,但iOS系统并未内置Skia,所以构建iPA时,也必须将Skia一起打包,这也是为什么Flutter APP的Android安装包比iOS安装包小的主要原因。但是Flutter也有不足之处,不支持动态下发代码和热更新。PWA(Progress Web App)PWA不属于上述跨平台开发的某一种,它是一种理念,PWA 本质上是 Web App,借助一些新技术也具备了 Native App 的一些特性,比如离线能力、本地缓存、和通知推送,兼具 Web App 和 Native App 的优点,看起来更像一个原生App。PWA完全使用前端技术栈,不过它需要手机和浏览器的支持,目前支持ServiceWorker和Google Play Service的Android手机,以及搭载11.3以上的iOS手机可以使用PWA。由于国内手机厂商和浏览器厂商的统一性问题,PWA在国内发展不是很好,但是在国外并没有这些问题。大前端趋势大前端不仅会成为移动开发与Web前端的发展趋势,也将会是未来的显示设备终端的开发技术趋势。大前端将做更多的终端开发、工程化等工作,而不仅仅只是开发Web页面。大前端工程师将能搞定所有端上的开发。与充满争议的全栈工程师相比,它更具可操作性。但同时对开发者而言,要会更多的技术栈,比如原生开发者要学习html、css、js等前端知识,前端开发人员也要学习Android或iOS的原生开发技术,然后了解一下常见的跨平台技术,只有这样才能更好的融入到大前端的这个大家庭中。

February 24, 2019 · 1 min · jiezi