【ubuntu 源码结构】【java webrtc直播 源码】【ios提取ipa 源码】心鸿源码

时间:2024-12-22 19:20:40 分类:程序源码怎么保存 来源:买卖宝 源码

1.【轻量级鸿蒙组件】JS虚拟机<3>——解析器
2.武汉电商直播系统源码
3.umi3源码解析之核心Service类初始化
4.华为鸿蒙系统和麒麟系统有什么区别?

心鸿源码

【轻量级鸿蒙组件】JS虚拟机<3>——解析器

       揭秘轻量级鸿蒙组件的心鸿源码JS虚拟机解析器:深度解析与功能详解

       JerryScript的解析器,犹如魔法般将JavaScript源代码转化为高效运行的心鸿源码字节码,其核心步骤包括递归解析和优化整合。心鸿源码这个过程涉及的心鸿源码关键组件,如同交响乐团的心鸿源码各个乐师,共同演奏出代码的心鸿源码ubuntu 源码结构美妙旋律。

       递归解析的心鸿源码艺术

       解析器采用递归策略,每一步都精心设计,心鸿源码以防止深度过深导致性能瓶颈。心鸿源码它在源代码中游刃有余,心鸿源码将每行代码转化为字节码的心鸿源码基石,但更进一步,心鸿源码它还实现了紧凑型字节码(CBC),心鸿源码以节省存储空间。心鸿源码

       核心组件的心鸿源码华丽演出

词法分析器Lexer,如同乐谱的解读者,将源代码中的关键字和符号转化为有意义的tokens,为后续解析提供基石。

扫描器Scanner,则如指挥家,解读tokens的多重含义,确保语法的准确性。例如,"for"可能是for-in或常规循环,"\'"可能是正则或除法运算,它通过后续token的引导,为每个词赋予精准的含义。

解析器Parser,则是整个过程的执行者,自上而下预测,从语句起点到可能的终点,逐步构建语义。在for-in语句中,解析器结合for和in来确定其确切含义。

       细节之处见真章

       解析器的每个函数,如lexer_next_token和lexer_parse_string,都精细地处理着字符的读取和处理。比如,lexer_next_token逐个解读字符,将其转化为token类型,并存储在parser_context_t中。而lexer_parse_string则负责精确解析字符串,确保数据的完整性和准确性。

       parser_parse_statements则是解析器中的核心函数,它通过解析堆栈,将语句转化为操作码,java webrtc直播 源码并在必要时进行变形,如CBC_PUSH_THIS和CBC_PUSH_PROP_THIS_LITERAL等。这需要深入理解字节码文件和BC值与代码逻辑的对应关系。

       文字对象的巧思

       在解析过程中,当遇到文字对象,解析器会调用lexer_process_char_literal来判断是否存储。这体现了解析器对内存管理的精巧处理,确保对象的有效利用。

       紧凑型字节码:轻量级的效率提升

       CBC作为轻量级的优化,通过压缩字节码,为代码运行带来显著的空间节省。在JerryScript 2.3.0版本中,CBC的操作码优化使得代码体积减小约%,展现了技术上的卓越与创新。

       总的来说,JerryScript的解析器是一个复杂而高效的工具,它将JavaScript源代码转化为执行效率极高的字节码,每个组件都在各自的领域中发挥着关键作用,共同构建了这个轻量级鸿蒙组件的基石。深入了解这个解析器的工作原理,无疑能让开发者更好地驾驭这个强大的工具。

武汉电商直播系统源码

       快手短视频直播带货,互联网的销售新模式互联网的兴起带来了许多改变,快手短视频直播带货就是其一,和传统的带货模式相比,快手短视频直播带货不仅灵活,而且方便。前两年自媒体行业开始兴起,到了年,快手短视频直播带货已经成为热点话题,也是许多网红、明星选择的销售模式,充满了让人无法抗拒的魔力。现在已经有越来越多的群体意识到快手短视频直播带货的优势,也有不少的头部主播和明星开始在快手短视频直播带货,武汉电商直播系统源码。有别于传统的销售方式,快手短视频直播带快手短视频短视频直播+教育还没有跨越鸿沟进入主流市场,红利犹在上周四(8月日)晚,小饭桌卓见“大咖说教育”专场中,北塔资本合伙人王凯峰站在投资人的角度分享了后教育创业的思考与未来机遇,并与凡卓资本投资经理苗萌、园钉创始人王旭、米来共享育儿MCN创始人邢子凯一同探讨了私域流量短视频直播教育抖音直播视频怎么录制?录播视频的方法技巧怎么录制抖音直播视频?想要录制他人直播视频怎么录制?或者是想要录制自己的直播视频以供回放该如何操作?目前的直播平台有虎牙直播、斗鱼主播、ios提取ipa 源码YY直播、抖音直播、繁星直播等,直播视频和经过剪辑处理的视频相比,武汉电商直播系统源码,武汉电商直播系统源码。功能是影响直播APP开发价格的另外一个重要因素,直播APP在开发技术上,相比于商城APP来说困难不少。武汉电商直播系统源码

       短视频程序拓宽了主流媒体的内容传播形式,作为新渠道,融合的发展是非常有必要的,尽管短视频程序已经存在多年,但不主打着每个人都已经对短视频做到了如指掌,初入短视频程序的商家,仍然要心存敬畏之心。短视频APP制作,互动广告成为短视频新玩法不知道从哪一年开始,各个平台都出现了集字赢红包的玩法,对短视频APP来说,这也成为了有效的拉新手段,但随着用户流量见顶,红包也需要更多吸引人的新玩法,来吸引新用户、留住老用户。短视频没人看?不是短视频代码的原因,看看你是不是踩雷了短视频不亚于一场精心准备的直播,从文案到剪辑,都需要up主用心去做,但很多up也遇到了自己精心做出来的视频没有人看的情况,自己看自己的视频没有问题,便开始怀疑是不是短视频代码的推荐机制出了问题。直播短视频源码,商家、平台都是打工仔,真正受益者是它直播带货的魔力已经在直播平台和短视频平台传播开来,盈利的不仅是商家和平台,还有各位入场的明星。短视频商城源码,同样是带货,为什么不试试短视频带货呢短视频商城源码随着带货直播的兴起而兴起,现在的用户购买习惯已经跳出了传统的图文产品介绍购买方式,开始接受视频介绍商品的方式。视频聊天系统源码。深圳教育直播系统价格一日中直播的贷款超市源码下载流量高峰期基本在晚上。

       短视频+电商的合作新模式伴随直播行业向移动平台的发展转移,电商平台也开始更注重移动端平台的发展。短视频带货源码的出现,将流量的变现效率直接拉满,短视频带货源码可谓是火遍了整个互联网。短视频APP源代码,入场者的不断增加为何短视频仍能保持热度短视频行业轰轰烈烈的进行着,但真正活跃的永远只有那几家,黯然退场的短视频APP数不胜数,对于这种情况的短视频APP源代码为什么还能成为开发的热点,是什么推动着短视频APP源代码开发的进行。短视频系统开发公司告诉你,短视频变长收益能提高多少短视频是继文字、、音频视频后的一种新型内容传播形式,它将自己的覆盖面从文字中、传统音视频中脱离出来,力求拿下用户们碎片化时间这一块,依托各种拍摄、剪辑手段,在短视频系统上进行分享互动。短视频平台搭建,成功覆盖到很难获取的用户靠的是什么在这次期间,很多人养成了看短视频的习惯,身边的朋友除了看电视,就是刷短视频,了解新闻资讯,打发时间。期间短视频的爆发式增长也催生了不少的爆款视频,尤其是与防疫有关的内容,更是得到了各个用户的关注。短视频程序,想和短视频平台合作,要看这四个关键点毫无疑问。

       短视频的火爆是源于短视频程序源码所开发的功能特殊在短视频程序源码的开发里很关键的是搭建平台首页观看页面的功能布局,要保证有逻辑性和技术性搭建主页的视频顺序及长短。能够立在用户的视角,用与众不同的目光和严苛的技术性来进一步加深视频内容的画面感和意境,开发出…直播间源码的开发为什么需要做市场定位?直播间源码的开发为什么需要做市场定位?所以说定位的关键环节是用户而不是产品,了解用户需要什么就做什么这才是很好的方法。所以说开发公司务必清楚用户在什么情境下需要你这个平台,及其大家所开发设…解读直播带货源码开发的直播带货系统本质直播的形式更改了原始电商图文静态展示产品的情况,直播方式更加形象。2、网络红人的干洗店源码出现逐渐开启了网红营销模式,促进了网红营销这一新变现方式的出现。2、相对于传统电商模式,直播带货模式在产品呈现形式、时…直播软件源码的开发是如何渗入我们生活点滴中的?送走了共享经济,我们又迎来了直播经济,直播软件开发的受到了当下社会的欢迎,直播软件源码所开发的各类直播系统已成为我们生活娱乐的一种方式,直播软件源码的开发是有哪些亮点吸引着我们。将商品价值直观的传递给消费者;消费者观看电商直播的背后,隐藏的是对质量产品或者时尚产品的追求。

       之下,仿佛万物皆可直播,而赛新科技近日也研发了直播电商系统,为商家提供直播电商的解决方案。年“口红一哥”李佳琦赚了将近2亿元,视频博主李子柒赚了,快手辛巴武汉捐款,这些足以证明红人的掘金能力。年初的加速了直播电商的爆发,网红经济的崛起。直播这么火,商家如何借东风?线下传统实体店如何布局直播电商?直播除了卖货以外,我们到底如何利用直播建设和传播品牌?企采科技认为:可以从以下4个方面下手。1、自己开店铺直播如果你是传统实体商家,拥有齐全的营业执照及产品资质,赛新科技建议您开通线上网店,当你有了自己的线上店铺之后,就可以通过平台直播的形式挂出你的商品。如果你的产品有优势的话,通常当下直播3个小时以上,每天稳定在线观看人数在几百人的话,一个月的收入也可以达到几万元。如果能创造更多的流量,那么相应获取的收入会更多。而赛新科技直播电商系统。2、直播定位企业做直播,除了卖货以外,一定要想好通过直播给观看用户传递什么样的品牌理念和关键价值,表达什么样的态度,主播的人设定位是什么?邻家小姑娘?职场OL?霸道总裁?还是其他?直播大忌,切不可随便找一个主播上来卖商家产品。企业运用直播平台实际上是通过“直播+电商”的方式走向内容化,将商品进行内容化解读。天津电商直播系统哪家好

       音视频实时互动是直播系统开发中的关键。武汉电商直播系统源码

       启博云产品是怎样通过“直播+电商+社交”闭环服务私域直播的?对此还是让启博软件小编告诉大家一些经验。1、以直播为售货做好前期铺垫人们对直播总是感兴趣的,尤其是直播卖货,这对人们来讲是很新鲜的事?启博云直播电商荐微信群直播来了!私域直播潜力有多大?昨天,微信偷偷的开始灰度测试微信群直播。这个功能,预计不久之后就会全量推开!相比于视频号,我觉得群直播在想象空间上,可能不会小于抖音现在的直播间带货。可以说,微信群直播即将开启私域直播的时代!微信直播私域流量微信小程序可以直播哪些内容直播功能准入类目要求微信小程序加入直播功能,商家可以直接在小商店内开通直播帮助自己的商品和服务进行带货,那么有哪些商品可以在小商店内进行直播呢,这里我们来一起看下小商店带货的具体类目。微信小程序郑爽回应直播争议郑爽首要直播卖货引发颇多争议,其在生日直播带货过程中突然发脾气,对直播大为不满,表示这不是她想要的直播。郑爽在直播中直言“我真的很反感,这场直播的感觉和节奏并不是我想要的”,直播期间甚至情绪崩溃,期间还多次哽咽、哭泣。面对这个意外情况,请来助阵的两个男女主播也尴尬无比,试图救场,然而并没有结果,不得不先后离场。武汉电商直播系统源码

       成都赛新科技有限公司主要经营范围是教育培训,拥有一支专业技术团队和良好的市场口碑。公司业务分为网校系统 ,在线网校系统, 在线教育系统,培训系统等,目前不断进行创新和服务改进,为客户提供良好的产品和服务。公司秉持诚信为本的经营理念,在教育培训深耕多年,以技术为先导,以自主产品为重点,发挥人才优势,打造教育培训良好品牌。成都赛新科技公司秉承“客户为尊、服务为荣、创意为先、技术为实”的经营理念,全力打造公司的重点竞争力。

umi3源码解析之核心Service类初始化

       前言

       umi是一个插件化的企业级前端应用框架,在开发中后台项目中应用颇广,确实带来了许多便利。借着这个契机,便有了我们接下来的“umi3源码解析”系列的分享,初衷很简单就是从源码层面上帮助大家深入认知umi这个框架,能够更得心应手的使用它,学习源码中的设计思想提升自身。该系列的大纲如下:

       开辟鸿蒙,今天要解析的就是第一part,内容包括以下两个部分:

       邂逅umi命令,看看umidev时都做了什么?

       初遇插件化,了解源码中核心的Service类初始化的过程。

       本次使用源码版本为?3.5.,地址放在这里了,接下来的每一块代码笔者都贴心的为大家注释了在源码中的位置,先clone再食用更香哟!

邂逅umi命令

       该部分在源码中的路径为:packages/umi

       首先是第一部分umi命令,umi脚手架为我们提供了umi这个命令,当我们创建完一个umi项目并安装完相关依赖之后,通过yarnstart启动该项目时,执行的命令就是umidev

       那么在umi命令运行期间都发生了什么呢,先让我们来看一下完整的流程,如下图:

       接下来我们对其几个重点的步骤进行解析,首先就是对于我们在命令行输入的umi命令进行处理。

处理命令行参数//packages/umi/src/cli.tsconstargs=yParser(process.argv.slice(2),{ alias:{ version:['v'],help:['h'],},boolean:['version'],});if(args.version&&!args._[0]){ args._[0]='version';constlocal=existsSync(join(__dirname,'../.local'))?chalk.cyan('@local'):'';console.log(`umi@${ require('../package.json').version}${ local}`);}elseif(!args._[0]){ args._[0]='help';}

       解析命令行参数所使用的yParser方法是基于yargs-parser封装,该方法的两个入参分别是进程的可执行文件的绝对路径和正在执行的JS文件的路径。解析结果如下:

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}

       在解析命令行参数后,对version和help参数进行了特殊处理:

       如果args中有version字段,并且args._中没有值,将执行version命令,并从package.json中获得version的值并打印

       如果没有version字段,args._中也没有值,将执行help命令

       总的来说就是,如果只输入umi实际会执行umihelp展示umi命令的使用指南,如果输入umi--version会输出依赖的版本,如果执行umidev那就是接下来的步骤了。

       提问:您知道输入umi--versiondev会发什么吗?

       运行umidev

//packages/umi/src/cli.tsconstchild=fork({ scriptPath:require.resolve('./forkedDev'),});process.on('SIGINT',()=>{ child.kill('SIGINT');process.exit(0);});//packages/umi/src/utils/fork.tsif(CURRENT_PORT){ process.env.PORT=CURRENT_PORT;}constchild=fork(scriptPath,process.argv.slice(2),{ execArgv});child.on('message',(data:any)=>{ consttype=(data&&data.type)||null;if(type==='RESTART'){ child.kill();start({ scriptPath});}elseif(type==='UPDATE_PORT'){ //setcurrentusedportCURRENT_PORT=data.portasnumber;}process.send?.(data);});

       本地开发时,大部分脚手架都会采用开启一个新的线程来启动项目,umi脚手架也是如此。这里的fork方法是基于node中child_process.fork()方法的封装,主要做了以下三件事:

       确定端口号,使用命令行指定的端口号或默认的,如果该端口号已被占用则prot+=1

       开启子进程,该子进程独立于父进程,两者之间建立IPC通信通道进行消息传递

       处理通信,主要监听了RESTART重启和UPDATE_PORT更新端口号事件

       接下来看一下在子进程中运行的forkedDev.ts都做了什么。

//packages/umi/src/forkedDev.ts(async()=>{ try{ //1、设置NODE_ENV为developmentprocess.env.NODE_ENV='development';//2、InitwebpackversiondeterminationandrequirehookinitWebpack();//3、实例化Service类,执行run方法constservice=newService({ cwd:getCwd(),//umi项目的根路径pkg:getPkg(process.cwd()),//项目的package.json文件的路径});awaitservice.run({ name:'dev',args,});//4、父子进程通信letclosed=false;process.once('SIGINT',()=>onSignal('SIGINT'));process.once('SIGQUIT',()=>onSignal('SIGQUIT'));process.once('SIGTERM',()=>onSignal('SIGTERM'));functiononSignal(signal:string){ if(closed)return;closed=true;//退出时触发插件中的onExit事件service.applyPlugins({ key:'onExit',type:service.ApplyPluginsType.event,args:{ signal,},});process.exit(0);}}catch(e:any){ process.exit(1);}})();

       设置process.env.NODE_ENV的值

       initWebpack(接下来解析)

       实例化Service并run(第二part的内容)

       处理父子进程通信,当父进程监听到SIGINT、SIGTERM等终止进程的信号,也通知到子进程进行终止;子进程退出时触发插件中的onExit事件

       initWebpack

//packages/umi/src/initWebpack.tsconsthaveWebpack5=(configContent.includes('webpack5:')&&!configContent.includes('//webpack5:')&&!configContent.includes('//webpack5:'))||(configContent.includes('mfsu:')&&!configContent.includes('//mfsu:')&&!configContent.includes('//mfsu:'));if(haveWebpack5||process.env.USE_WEBPACK_5){ process.env.USE_WEBPACK_5='1';init(true);}else{ init();}initRequreHook();

       这一步功能是检查用户配置确定初始化webpack的版本。读取默认配置文件.umirc和config/config中的配置,如果其中有webpack5或?mfsu等相关配置,umi就会使用webpack5进行初始化,否则就使用webpack4进行初始化。这里的mfsu是webpack5的模块联邦相关配置,umi在3.5版本时已经进行了支持。

初遇插件化

       该部分在源码中的路径为:packages/core/src/Service

       说起umi框架,最先让人想到的就是插件化,这也是框架的核心,该部分实现的核心源码就是Service类,接下来我们就来看看Service类的实例化和init()的过程中发生了什么,可以称之为插件化实现的开端,该部分的大致流程如下

       该流程图中前四步,都是在Service类实例化的过程中完成的,接下来让我们走进Service类。

Service类的实例化//packages/core/src/Service/Service.tsexportdefaultclassServiceextendsEventEmitter{ constructor(opts:IServiceOpts){ super();this.cwd=opts.cwd||process.cwd();//当前工作目录//repoDirshouldbetherootdirofrepothis.pkg=opts.pkg||this.resolvePackage();//package.jsonthis.env=opts.env||process.env.NODE_ENV;//环境变量//在解析config之前注册babelthis.babelRegister=newBabelRegister();//通过dotenv将环境变量中的变量从.env或.env.local文件加载到process.env中this.loadEnv();//1、getuserconfigconstconfigFiles=opts.configFiles;this.configInstance=newConfig({ cwd:this.cwd,service:this,localConfig:this.env==='development',configFiles});this.userConfig=this.configInstance.getUserConfig();//2、getpathsthis.paths=getPaths({ cwd:this.cwd,config:this.userConfig!,env:this.env,});//3、getpresetsandpluginsthis.initialPresets=resolvePresets({ ...baseOpts,presets:opts.presets||[],userConfigPresets:this.userConfig.presets||[],});this.initialPlugins=resolvePlugins({ ...baseOpts,plugins:opts.plugins||[],userConfigPlugins:this.userConfig.plugins||[],});}}

       Service类继承自EventEmitter用于实现自定义事件。在Service类实例化的过程中除了初始化成员变量外主要做了以下三件事:

       1、解析配置文件

//packages/core/src/Config/Config.tsconstDEFAULT_CONFIG_FILES=[//默认配置文件'.umirc.ts','.umirc.js','config/config.ts','config/config.js',];//...if(Array.isArray(opts.configFiles)){ //配置的优先读取this.configFiles=lodash.uniq(opts.configFiles.concat(this.configFiles));}//...getUserConfig(){ //1、找到configFiles中的第一个文件constconfigFile=this.getConfigFile();this.configFile=configFile;//潜在问题:.local和.env的配置必须有configFile才有效if(configFile){ letenvConfigFile;if(process.env.UMI_ENV){ //1.根据UMI_ENV添加后缀eg:.umirc.ts-->.umirc.cloud.tsconstenvConfigFileName=this.addAffix(configFile,process.env.UMI_ENV,);//2.去掉后缀eg:.umirc.cloud.ts-->.umirc.cloudconstfileNameWithoutExt=envConfigFileName.replace(extname(envConfigFileName),'',);//3.找到该环境下对应的配置文件eg:.umirc.cloud.[ts|tsx|js|jsx]envConfigFile=getFile({ base:this.cwd,fileNameWithoutExt,type:'javascript',})?.filename;}constfiles=[configFile,//eg:.umirc.tsenvConfigFile,//eg:.umirc.cloud.tsthis.localConfig&&this.addAffix(configFile,'local'),//eg:.umirc.local.ts].filter((f):fisstring=>!!f).map((f)=>join(this.cwd,f))//转为绝对路径.filter((f)=>existsSync(f));//clearrequirecacheandsetbabelregisterconstrequireDeps=files.reduce((memo:string[],file)=>{ memo=memo.concat(parseRequireDeps(file));//递归解析依赖returnmemo;},[]);//删除对象中的键值require.cache[cachePath],下一次require将重新加载模块requireDeps.forEach(cleanRequireCache);this.service.babelRegister.setOnlyMap({ key:'config',value:requireDeps,});//requireconfigandmergereturnthis.mergeConfig(...this.requireConfigs(files));}else{ return{ };}}

       细品源码,可以看出umi读取配置文件的优先级:自定义配置文件?>.umirc>config/config,后续根据UMI_ENV尝试获取对应的配置文件,development模式下还会使用local配置,不同环境下的配置文件也是有优先级的

       例如:.umirc.local.ts>.umirc.cloud.ts>.umirc.ts

       由于配置文件中可能require其他配置,这里通过parseRequireDeps方法进行递归处理。在解析出所有的配置文件后,会通过cleanRequireCache方法清除requeire缓存,这样可以保证在接下来合并配置时的引入是实时的。

       2、获取相关绝对路径

//packages/core/src/Service/getPaths.tsexportdefaultfunctiongetServicePaths({ cwd,config,env,}:{ cwd:string;config:any;env?:string;}):IServicePaths{ letabsSrcPath=cwd;if(isDirectoryAndExist(join(cwd,'src'))){ absSrcPath=join(cwd,'src');}constabsPagesPath=config.singular?join(absSrcPath,'page'):join(absSrcPath,'pages');consttmpDir=['.umi',env!=='development'&&env].filter(Boolean).join('-');returnnormalizeWithWinPath({ cwd,absNodeModulesPath:join(cwd,'node_modules'),absOutputPath:join(cwd,config.outputPath||'./dist'),absSrcPath,//srcabsPagesPath,//pagesabsTmpPath:join(absSrcPath,tmpDir),});}

       这一步主要获取项目目录结构中node_modules、dist、src、pages等文件夹的绝对路径。如果用户在配置文件中配置了singular为true,那么页面文件夹路径就是src/page,默认是src/pages

       3、收集preset和plugin以对象形式描述

       在umi中“万物皆插件”,preset是对于插件的描述,可以理解为“插件集”,是为了方便对插件的管理。例如:@umijs/preset-react就是一个针对react应用的插件集,其中包括了plugin-access权限管理、plugin-antdantdUI组件等。

//packages/core/src/Service/Service.tsthis.initialPresets=resolvePresets({ ...baseOpts,presets:opts.presets||[],userConfigPresets:this.userConfig.presets||[],});this.initialPlugins=resolvePlugins({ ...baseOpts,plugins:opts.plugins||[],userConfigPlugins:this.userConfig.plugins||[],});

       在收集preset和plugin时,首先调用了resolvePresets方法,其中做了以下处理:

       3.1、调用getPluginsOrPresets方法,进一步收集preset和plugin并合并

//packages/core/src/Service/utils/pluginUtils.tsgetPluginsOrPresets(type:PluginType,opts:IOpts):string[]{ constupperCaseType=type.toUpperCase();return[//opts...((opts[type===PluginType.preset?'presets':'plugins']asany)||[]),//env...(process.env[`UMI_${ upperCaseType}S`]||'').split(',').filter(Boolean),//dependencies...Object.keys(opts.pkg.devDependencies||{ }).concat(Object.keys(opts.pkg.dependencies||{ })).filter(isPluginOrPreset.bind(null,type)),//userconfig...((opts[type===PluginType.preset?'userConfigPresets':'userConfigPlugins']asany)||[]),].map((path)=>{ returnresolve.sync(path,{ basedir:opts.cwd,extensions:['.js','.ts'],});});}

       这里可以看出收集preset和plugin的来源主要有四个:

       实例化Service时的入参

       process.env中指定的UMI_PRESETS或UMI_PLUGINS

       package.json中dependencies和devDependencies配置的,需要命名规则符合?/^(@umijs\/|umi-)preset-/这个正则

       解析配置文件中的,即入参中的userConfigPresets或userConfigPresets

       3.2、调用pathToObj方法:将收集的plugin或preset以对象的形式输出

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}0

       umi官网中提到过:每个插件都会对应一个id和一个key,id是路径的简写,key是进一步简化后用于配置的唯一值。便是在这一步进行的处理

       形式如下:

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}1

       思考:为什么要将插件以对象的形式进行描述?有什么好处?

执行run方法,初始化插件

       在Service类实例化完毕后,会立马调用run方法,run()执行的第一步就是执行init方法,init()方法的功能就是完成插件的初始化,主要操作如下:

       遍历initialPresets并init

       合并initpresets过程中得到的plugin和initialPlugins

       遍历合并后的plugins并init

       这里的initialPresets和initialPlugins就是上一步收集preset和plugin得到的结果,在这一步要对其逐一的init,接下来我们看一下init的过程中做了什么。

       Initplugin

//输入umidev经yargs-parser解析后为://args={ //_:["dev"],//}2

       这段代码主要做了以下几件事情:

       getPluginAPI方法:newPluginAPI时传入了Service实例,通过pluginAPI实例中的registerMethod方法将register方法添加到Service实例的pluginMethods中,后续返回pluginAPI的代理,以动态获取最新的register方法,以实现边注册边使用。

//输入umidev经yargs-parser解析后为:/

华为鸿蒙系统和麒麟系统有什么区别?

       华为鸿蒙系统和麒麟的区别在于,鸿蒙系统是华为开发的操作系统,而麒麟则是华为自家研发的芯片。

       鸿蒙系统是华为为了应对美国制裁而开发的一款操作系统。作为一款自主研发的操作系统,鸿蒙系统具有更高的自主可控性和安全性。鸿蒙系统的设计初衷是为了实现跨平台、跨设备的无缝连接和高效协同,从而为用户带来更加便捷、智能的使用体验。目前,鸿蒙系统已经在华为的多款设备上得到了广泛应用,包括手机、平板、电视等。

       而麒麟则是华为自家研发的芯片,也是华为在自主研发领域的重要成果之一。麒麟芯片是华为为了减少对外部供应商的依赖,提高自身核心竞争力而自主研发的。麒麟芯片具有高性能、低功耗、高安全性等特点,已经被广泛应用于华为的多款手机和平板电脑上。目前,麒麟芯片已经成为了华为手机和平板电脑的核心竞争力之一。

       从技术角度来看,鸿蒙系统和麒麟芯片都是华为在自主研发领域的重要成果。鸿蒙系统的推出可以降低华为对外部操作系统的依赖,提高自主可控性和安全性;而麒麟芯片的推出则可以减少对外部供应商的依赖,提高华为手机和平板电脑的性能和安全性。

       总的来说,鸿蒙系统和麒麟芯片都是华为在自主研发领域的重要成果,它们各自具有不同的特点和优势。鸿蒙系统注重跨平台、跨设备的无缝连接和高效协同,而麒麟芯片则注重高性能、低功耗和高安全性。这些自主研发的技术成果为华为的发展提供了强有力的支持,也为用户带来了更加便捷、智能的使用体验。