【hadoop 查看源码】【绑定参照源码】【加油分销源码】pagehelp 源码

时间:2024-12-23 03:25:15 来源:股票黄金底公式源码 分类:探索

1.html简单网页代码?
2.umi3源码解析之核心Service类初始化

pagehelp 源码

html简单网页代码?

       HTML做一个打开网页代码

       html的源码head区域中加上scriptlanguage="javascript"location.replace("")/script即可html

       html代码如下:

       head

       title页面跳转/title

       scriptlanguage="javascript"location.replace("")/script

       /head

       body

       /body

       /html

       

扩展资料:

       网页HTML代码大全

       文件类型HTML/HTML(放在档案的开头与结尾)

       文件主题TITLE/TITLE(必须放在「文头」区块内)

       文头HEAD/HEAD(描述性资料,像是源码「主题」)

       文体BODY/BODY(文件本体)

       (由浏览器控制的显示风格)

       标题H?/H?(从1到6,有六层选择)

       标题的源码对齐H?ALIGN=LEFT|CENTER|RIGHT/H?

       区分DIV/DIV

       区分的对齐DIVALIGN=LEFT|RIGHT|CENTER|JUSTIFY/DIV

       引文区块BLOCKQUOTE/BLOCKQUOTE(通常会内缩)

       强调EM/EM(通常会以斜体显示)

       特别强调STRONG/STRONG(通常会以加粗显示)

       引文CITE/CITE(通常会以斜体显示)

       码CODE/CODE(显示原始码之用)

       样本SAMP/SAMP

       键盘输入KBD/KBD

       变数VAR/VAR

       定义DFN/DFN(有些浏览器不提供)

       地址ADDRESS/ADDRESS

       大字BIG/BIG

       小字SMALL/SMALL

       与外观相关的标签(作者自订的表现方式)

       加粗B/B

       斜体I/I

       底线U/U(尚有些浏览器不提供)

       删除线S/S(尚有些浏览器不提供)

       下标SUB/SUB

       上标SUP/SUP

       打字机体TT/TT(用单空格字型显示)

       预定格式PRE/PRE(保留文件中空格的大小)

       预定格式的宽度PREWIDTH=?/PRE(以字元计算)

       向中看齐CENTER/CENTER(文字与都可以)

       网页设计常用HTML代码

       网页设计常用HTML代码大全

       HTML是用来描述网页的一种语言。下面我为大家分享HTML代码,源码希望对大家学习html代码有帮助!源码

       忽视右键

       bodyoncontextmenu="returnfalse"

       或

       bodystyle="overflow-y:hidden"

       1.如何几秒后转到别的源码hadoop 查看源码页面?

       METAHTTP-EQUIV="Refresh"CONTENT="时间;URL=地址"

       2.点击关闭窗口

       ahref="javascript:top.window.close();"点击关闭窗口/a!

       3.请问如何去掉主页右面的源码滚动条?

       bodyscroll="no"

       bodystyle="overflow-y:hidden"

       4.请问如何做到让一个网页自动关闭.

       html

       head

       OBJECTid=closestype="application/x-oleobject"classid="clsid:adba6-d8ff-cf--aab7a"

       paramname="Command"value="Close"

       /object

       /head

       bodyonload="window.setTimeout(‘‘‘‘closes.Click()‘‘‘‘,)"

       这个窗口会在秒过后自动关闭,而且不会出现提示./body

       如何在不刷新页面的情况下刷新css?

       style

       button{ color:#;}

       /style

       buttononclick=document.styleSheets[0].rules[0].style.color=‘‘‘‘red‘‘‘‘点击按钮直接修改style标签里button选择符使按钮改为红色/button

       请问如何让网页自动刷新?

       在head部记入METAHTTP-EQUIV="Refresh"content=""其中为秒后自动刷新,你可以更改为任意值。源码

       5.如何让页面自动刷新?

       方法一,源码用refresh

       HTML代码片段如下:

       head

       metahttp-equiv="refresh"content="5"

       /head

       5表示刷新时间

       [Ctrl+A全部选择提示:你可先修改部分代码,源码再按运行]

       方法二,源码使用setTimeout控制

       imgsrc=/logo.gif

       script

       functionrl(){

       document.location.reload()

       }

       setTimeout(rl,源码)

       /script

       6.如何让超链接没有下划线

       在源代码中的HEAD…/HEAD之间输入如下代码:

       styletype="text/css"!--

       a{ text-decoration:none}

       --/style

       7.请问如何去掉IE的上下滚动条?

       bodystyle=‘‘‘‘overflow:scroll;overflow-y:hidden‘‘‘‘

       /body

       8.怎样才能把RealPlayer文件在网页做一个试听连接?

       embedheight=src=js.rmtype=audio/x-pn-realaudio-pluginwidth=autostart="false"controls="PlayButton"

       9.如何用html实现浏览器上后退按钮的功能?

       ahref="javascript:history.go(-1)"点击后退/a

       或者

       scripthistory.back()/script

       .请问怎么在网页中改变鼠标的箭头形状?

       HTML代码片段如下:

       body

       ahref="#"style="cursor:auto;"auto/abr

       ahref="#"style="cursor:crosshair"crosshair/abr

       ahref="#"style="cursor:default"default/abr

       ahref="#"style="cursor:hand"hand/abr

       ahref="#"style="cursor:move"move/abr

       ahref="#"style="cursor:e-resize"e-resize/abr

       ahref="#"style="cursor:ne-resize"ne-resize/abr

       ahref="#"style="cursor:nw-resize"nw-resize/abr

       ahref="#"style="cursor:n-resize"n-resize/abr

       ahref="#"style="cursor:se-resize"se-resize/abr

       ahref="#"style="cursor:sw-resize"sw-resize/abr

       ahref="#"style="cursor:s-resize"s-resize/abr

       ahref="#"style="cursor:w-resize"w-resize/abr

       ahref="#"style="cursor:text"text/abr

       ahref="#"style="cursor:wait"wait/abr

       ahref="#"style="cursor:help"help/abr

       /body

       .怎样不使用页面的缓存?即每一次打开页面时不是调用缓存中的东西

       METAHTTP-EQUIV="Pragma"CONTENT="no-cache"

       .页面打开时自动弹出一个窗口的代码怎么写?

       HTML代码片段如下:

       html

       head

       titleUntitledDocument/title

       metahttp-equiv="Content-Type"content="text/html;charset=gb"

       scriptlanguage="Bstyle="color:black;background-color:#A0FFFF"javascript/B"

       !--

       functionMM_openBrWindow(theURL,winName,features){ //v2.0

       window.open(theURL,winName,features);

       }

       //--

       /script

       /head

       bodybgcolor="#FFFFFF"text="#"onLoad="MM_openBrWindow(‘‘‘‘‘‘‘‘,‘‘‘‘,‘‘‘‘width=,height=‘‘‘‘)"

       /body

       /html

       .如何让我的页面出现一个会讲话的小人?Merlin

       HTML代码片段如下:

       HTML

       HEAD

       TITLE默林/TITLE

       METAhttp-equiv=Content-Typecontent="text/html;charset=gb"

       /HEAD

       BODY

       pOBJECTid=simsclassid=CLSID:DFDB-5C6E-D1-9EC1-CFDF

       /OBJECT

       SCRIPT

       varMerlinID;

       varMerlinACS;

       sims.Connected=true;

       MerlinLoaded=LoadLocalAgent(MerlinID,MerlinACS);

       Merlin=sims.Characters.Character(MerlinID);

       Merlin.Show();

       Merlin.Play("Surprised");

       Merlin.Speak("大家好");

       Merlin.Play("GestureLeft");

       Merlin.Think("我是默林!");

       Merlin.Play("Pleased");

       Merlin.Think("可爱吗?");

       Merlin.Play("GestureDown");

       Merlin.Speak("哈哈!源码");

       Merlin.Hide();

       functionLoadLocalAgent(CharID,源码CharACS){

       LoadReq=sims.Characters.Load(CharID,CharACS);

       return(true);

       }

       /SCRIPT

       /p

       p/p

       p看此效果必须装有office!!源码!/p

       /BODY

       /HTML

       .在页面中如何加入不是绑定参照源码满铺的背景,拉动页面时背景图不动

       HTML代码片段如下:

       htmlhead

       STYLE

       body{ background-image:url(logo.gif);

       background-repeat:no-repeat;background-position:center}

       /STYLE

       /head

       bodybgproperties="fixed"

       /body

       /html

       [Ctrl+A全部选择提示:你可先修改部分代码,再按运行]

       background-repeat:no-repeat;是让背景图不占满整个页面

       bodybgproperties="fixed"是拉动scroll时背景图不动

       .文本输入框什么属性能实现不可输入?

       HTML代码片段如下:

       inputtype="text"name="textfield"disabled

       或者

       inputtype="text"name="textfield"readonly

       .如何禁止自己的页面在别人的框架里打开?

       把以下代码加至你的head区

       script

       if(window.top!=self){

       window.top.location=self.location

       }

       /script

       .如何实现首页全屏幕显示?

       HTML代码片段如下:

       html

       bodyscriptlanguage="Bstyle="color:black;background-color:#A0FFFF"javascript/B"

       varcoolw=

       varcoolh=

       varcoolhuang=window.open("","coolhuang","width="+coolw+",height="+coolh+",

       fullscreen=1,toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0")

       window.close()

       /script/body/html

       .如何监听一个窗口被关闭了?

       HTML代码片段如下:

       bodyonunload="alert(‘‘‘‘你关闭了这个窗口‘‘‘‘)"

       .如何禁止Ctrl+N?

       HTML代码片段如下:

       bodyonkeydown=return(!(event.keyCode==event.ctrlKey))

       如何把页面加入用户的收藏夹?

       HTML代码片段如下:

       ahref="Bstyle="color:black;background-color:#A0FFFF"javascript/B:window.external.AddFavorite(‘‘‘‘‘‘‘‘,‘‘‘‘无忧脚本‘‘‘‘)"收藏无忧脚本/a

       如何在我的'页面中加入背景音乐?

       IE:bgsoundsrc="*.mid"loop=infinite

       NS:embedsrc="*.mid"autostart=truehidden=trueloop=true

       *.mid你的背景音乐的midi格式文件

       关于页面转换效果

       metahttp-equiv="page-enter"content="revealTrans(Duration=4,Transition=)"

       或

       metahttp-equiv="page-exit"content="revealTrans(Duration=4,Transition=)"

       说明:Transition=是随机效果,另可以选0-任一数字固定某个效果

       如何设定打开页面的大小

       HTML代码片段如下:

       bodyonload="top.resizeTo(,);"!--(width,height)--

       怎样双击滚屏,单击停止?

       HTML代码片段如下:

       html

       head

       title新网页1/title

       /head

       body

       scriptlanguage"Bstyle="color:black;background-color:#A0FFFF"javascript/B"

       varcurrentpos,timer;

       functioninitialize()

       {

       timer=setInterval("scrollwindow()",);

       }

       functionsc(){

       clearInterval(timer);

       }

       functionscrollwindow()

       {

       currentpos=document.body.scrollTop;

       window.scroll(0,++currentpos);

       if(currentpos!=document.body.scrollTop)

       sc();

       }

       document.onmousedown=sc

       document.ondblclick=initialize

       /script

       pa/ppa/ppa/ppaa/ppaa/ppaa/p

       paa/ppaa/ppaa/ppaa/ppaa/ppaa/p

       paa/ppaa/ppaa/ppaa/ppaa/ppaa/p

       paa/ppaa/ppaa/ppaa/ppa/p

       /body

       /html

       如何让body中的文字不被选中?

       HTML代码片段如下:

       bodyonselectstart="returnfalse"aaa/body

       如何让弹出的窗口不能关闭?

       在新开的窗口中加入如下代码

       bodyonunload=open(location.href)

       /body

       如何让浏览器在保存页面时保存失败?

       HTML代码片段如下:

       NOSCRIPT

       Bstyle="color:black;background-color:#ffff"IFRAME/BSRC="*.html"

       /Bstyle="color:black;background-color:#ffff"IFRAME/B

       /NOSCRIPT

       表单中如何用按钮实现reset?

       html

       head

       script

       functionaaa(){

       document.forms[0].reset()

       }

       /script

       /head

       body

       form

       textarearows="2"name="S1"cols=""/textarea

       inputtype="submit"values="提交"name="B1"

       imagesrc="logo.gif"onclick=aaa()

       /form

       /body/html

       进入网页时弹出的信息对话框

       bodyonLoad="window.alert(‘‘‘‘欢迎光临本站‘‘‘‘)"

       关闭窗口后弹出对话框

       bodyonUnload="window.alert(‘‘‘‘谢谢你的光临!欢迎下次再来!‘‘‘‘)"

       告别提示

       bodyonUnload=alert("再见,感谢你的访问!")

       右键菜单的制作

       OBJECTid=menutype="application/x-oleobject"classid="clsid:adba6-d8ff-cf--aab7a"

       PARAMname="Command"value="RelatedTopics,menu"

       PARAMname="Item1"value="动易;"

       PARAMname="Item2"value="搜狐;"

       PARAMname="Item3"value="新浪;"

       PARAMname="Item4"value="网易;"

       PARAMname="Item5"value="互动学院;"

       /OBJECTscriptif(document.all)document.body.onmousedown=newFunction("if(event.button==2)menu.Click();")/script

       下拉菜单

       objectid=HHCtrltype="application/x-oleobject"classid="clsid:adba6-d8ff-cf--aab7a"PARAMname="Command"value="RelatedTopics,Menu"PARAMname="Item1"value="aspease;"PARAMname="Item2"value="byhu;"PARAMname="Item3"value="lzz;"/objectahref=javascript:HHCtrl.Click()title="下拉菜单"下拉菜单/a

html简单网页代码怎么写?

       1、在电脑桌面空白处单击右键,新建一个记事本并打开

       2、在新建文件中输入如下代码。html语言都是以htmlheadtitlebody等标签开始,以/html/head/title/body标签作为结束。

       3、接下来要在title/title标签中间输入标题(如个人网页)在body/body中输入“自己做的第一个网页,厉害吧!”完成后点击保存

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

       前言

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

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

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

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

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

邂逅umi命令

       该部分在源码中的kafka 源码笔记路径为: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命令的参数iapp源码使用指南,如果输入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解析后为:/