晚上十二点,床上的富婆:这是给你的500元。走吧小蝌蚪:是的,主人说完,小蝌蚪就从三楼的别墅跳了下来。..小蝌蚪是一名程序员兼技术员,白天敲代码,晚上因为常年敲代码而捏脚,所以经常凭借精湛的指法把客户推上天。..富婆年轻有钱,却缺爱。因为嫁给了80多岁的老公,乖巧粘人的小蝌蚪博得了富婆的好感。..又遇富婆:好无聊,快点讨好我小蝌蚪:师傅,我用手指在你腿上敲一段《迪杰斯特拉最短路径算法》写《javascript高级程序设计》富婆:我才不要对,小蝌蚪:那我就用舌头给你表演口技吧。富婆:舌头?腹语术?小蝌蚪:别想太多,正式表演,小蝌蚪表演了一段用舌头砸石头的动作。富婆喜出望外,掌声经久不息。..表演结束后,富婆脸红了富婆:我喜欢你小蝌蚪:我也喜欢我自己富婆:你爱我吗小蝌蚪:我不能被客户诱惑富婆:我怎么才能得到你的心小蝌蚪:杀了我,拿出你的心脏,嘻嘻富婆:嘻嘻。..富婆:对了,下周来参加我的闺蜜聚会小蝌蚪:你不想带你老公吗?富婆:他80岁了,拿他丢脸小蝌蚪:那我要加钱富婆:多少钱小蝌蚪:200元两小时钱,物美价廉,服务一流富婆::交易。..晚上八点闺蜜聚会,高档酒店,各种炫富闺蜜A:买了个包,才10万,好便宜~闺蜜B:包了三只小奶狗,让它们玩游戏通宵女友C:老公养了很多小动物,宝马路虎捷豹。富婆默默上前:我在北京二环买了四合院,其他闺蜜瞬间不说话了。..小蝌蚪意识到这不是一顿普通的晚餐,而是一场闺蜜间的假装盛宴。小蝌蚪:你找我有什么事?富婆:我需要你打败他们的男宠。..酒后,三游到了炫耀男宠的地步。各位闺蜜都带着自己的男宠,有肌肉男、高端鸭子、男模等,肌肉男一上台就秀出八块腹肌和沙包大的裤裆男模。大长腿,帅气的脸蛋,鸭前辈在台上吐了吐舌头,“微微,微微,微微……”。..轮到小蝌蚪上台了,一身烂绿格子衫傻眼了。主持人问:辣子鸡,你想炫耀什么特产?小蝌蚪:舌头被大石压碎主持人:除了这个还有什么?小蝌蚪:胸毛被巨石压碎是来砸场的小蝌蚪:对,我是来砸场的主持人,叫了20个保安。十秒后,所有的保安都倒在了地上,全身抽搐。蝌蚪的胸毛上刻着神秘的javascript代码。..主持人:爸爸,对不起,刚才冒犯到您了主持人:爸爸,请向观众介绍一下自己。小蝌蚪从书包里掏出1000万(富婆送的)点燃,把燃烧着的钱从98楼扔得满天飞。小蝌蚪介绍:“我是个没心没肺的人,颜色不一样。”台下所有的女人都因为过度的兴奋而疯狂的尖叫起来。雄宠们看到自己的主人跪在地上,疯狂的舔着小蝌蚪。他们觉得自己被主人绿了。:爸,你有什么比较温柔的特长给大家看的吗?小蝌蚪:我要唱一首孙衍之的《绿光》,献给这里所有的辣鸡男“《绿光》爱就像绿灯照在你头上怪嫂子太漂亮了...别因为你太火辣就怪爸爸无情~绿光~啊~绿光照亮你我他”公宠:小蝌蚪,你太过分了凭着自己的能力断肠男宠:你到底要什么?小蝌蚪:我想跳上你的坟墓。雄宠们心态炸裂,疯狂挠头,从九十八层纵身一跃而下。小蝌蚪在比赛中获胜,成为第一只雄性宠物。..酒店阳台上,微风吹过富婆:今晚谢谢你小蝌蚪:为了钱,我应该是富婆:我喜欢你小蝌蚪:我也喜欢我自己富婆:你爱我吗小小蝌蚪:我不能被顾客诱惑富婆:我怎么才能得到你的心小蝌蚪:杀了我,拿出你的心,嘻嘻富婆:嘻嘻。..混混家里面,掐富婆的脚:我要死了小蝌蚪:怎么了富婆:我老公外面有女人富婆:他是混混,他要杀我,跟小三小蝌蚪摸着富婆的脸:傻瓜,在那之前,我先杀了他。小蝌蚪和富婆抱在了一起,嘴里画了一条明线。一吻之后,小蝌蚪消失在夜空中。..刺杀大哥半夜十二点,歹徒旅馆房间门外塞着一张写着“包小姐”字样的小卡片和一张蝌蚪穿泳裤的照片。..大佬有个怪癖,喜欢胸毛浓密的小奶狗。小蝌蚪满足了他对所有小奶狗的幻想。..果不其然,房间的门开了,小蝌蚪一千根胸毛扎进了老大的身上。大哥:你。..你是谁小蝌蚪:我是你爹地老板:你为什么要杀我小蝌蚪:因为??我是你爹地老板:你能不能不提爹地这个词小蝌蚪:我和老婆跟黑道老大有染,突然,在80岁时...因为刺杀黑帮老大,当晚回去的路上,小蝌蚪被1000名杀手满城追杀,用光了最后一根胸毛。刺伤小蝌蚪,掏出心脏。小蝌蚪惊恐的看着她。富婆:终于得到你的心了,呵呵(完)://github.com/airuikun/blog《nodejs线上模块热部署原理与实现》背景大家都知道,nodejs启用的后台服务如果有代码改动,必须重启进程使代码生效。重启nodejs的进程,爸爸们去访问服务的时候,会出现一个短促的502badgateway,爸爸们不爽。如果你的服务器设置了watch机制,当服务器上的代码变化频繁,或者短时间内变化频繁的时候,总会是502badgateway。正所谓“重启一时爽,重启一时爽”。模块更新频繁,更新后的代码在无法重启服务时生效。这就涉及到一个热部署的概念,就是让新部署的代码在不重启服务的情况下生效。接下来给爸爸们讲解一下热部署的原理以及实现代码不能实时生效的原因。当我们通过require('xx/xx.js')加载一个功能模块时,node会把require('xx.js')/xx.js')缓存在require.cache('xx/xx.js')当我们多次调用require('xx/xx.js')时,node不会再重新加载,而是直接从require.cache('xx/xx.js')中读取缓存,所以当爸爸修改路径下的文件时服务器上的xx/xx.js,node只会读取缓存,不会加载最新版本的爸爸代码源码地址和使用为了实现这种热部署机制,在网上到处找资料,一步一步on处处坑坑洼洼-node-reload注意,node最新版本12会报错。官方已经对require.cache做了调整,问题已经反馈给官方了。推荐使用nodejs版本:v10.5.0gitclone后不需要安装,直接运行npmstart即可,此时热部署变更监听开启。怎样才能看到效果?爸爸,请看/hots/hot.js文件consthot=1module.exports=hot,把第一行代码改成consthot=111consthot=111module。exports=hot这个时候可以看到在终端监听到代码变化,然后动态加载你最新的代码,得到执行结果。输出为:热部署文件:hot.js,执行结果:{'hot.js':111}热部署服务监听代码变化,重新加载代码。爸爸们可以实时获取最新代码的执行结果。全程在线环境运行,node进程不重启源码分析。loadHandlersmainfunctionconsthandlerMap={};//cacheconsthotsPath=path.join(__dirname,"hots");//加载文件代码,监听指定文件夹目录文件内容变化constloadHandlers=async()=>{//遍历指定文件夹下的所有文件constfiles=awaitnewPromise((resolve,reject)=>{fs.readdir(hotsPath,(err,files)=>{if(err){reject(err);}else{resolve(files);}});});//初始化所有文件的加载,并将每个文件的结果缓存到handlerMap变量中}//监听指定文件夹的文件内容变化awaitwatchHandlers();};loadHandlers是整个热部署服务的主要功能,我们指定服务器根目录下的hots文件夹作为使用fs监控变化和热部署的文件夹。readdir扫描hots文件夹下的所有文件,通过loadHandler方法加载并运行每一个扫描到的文件,将结果缓存到handlerMap中,然后使用watchHandlers方法开启文件变化监听。watchHandlersmonitorsfilechanges//监听指定文件夹下的文件FilechangesconstwatchHandlers=async()=>{//这里推荐使用chokidar的npm包,而不是文件夹监听fs.watch(hotsPath,{recursive:true},async(eventType,filename)=>{//获取每一个文件的绝对路径//之所以包含一层require.resolve,拼接路径后会主动帮你判断文件是否存在该路径下存在consttargetFile=require.resolve(path.join(hotsPath,filename));//当你适配require加载一个模块时,该模块的数据会缓存在require.cache中,下次你加载相同的模块,它会直接进入require.cache//所以我们热加载部署,首先要做的就是清除require.cache对应文件的缓存constcacheModule=require.cache[targetFile];//在require.cache缓存中移除parent对当前模块的引用,否则会造成内存泄漏。具体解释见下文//《记录一次由一行代码引发的“血案”》https://cnodejs.org/topic/5aaba2dc19b2e3db18959e63//《一行 delete require.cache 引发的内存泄漏血案》https://zhuanlan.zhihu.com/p/34702356if(cacheModule.parent){cacheModule.parent.children.splice(cacheModule.parent.children.indexOf(cacheModule),1);}//清除指定路径对应模块的require.cache缓存require.cache[targetFile]=null;//重新加载变化的模块文件,达到热加载部署和重新加载的效果最终结果更新到handlerMap变量constcode=awaitloadHandler(targetFile)handlerMap[filename]=code;console.log("热部署文件:",文件名,",执行结果:",handlerMap);});};watchHandlers函数用于监听指定文件夹中的文件变化,清除缓存和更新缓存使用fs.watch原生函数监听hots文件夹中的文件变化。当文件发生变化时,计算出该文件的绝对路径targetFile,require.cache[targetFile]为原targetFile文件的require缓存。要清除缓存,请使用require.cache[targetFile]=null;棘手的地方来了,仅仅将缓存设置为null会导致内存泄漏,我们还需要清除缓存父引用require.cache[targetFile].parent,也就是下面的代码parent.children.splice(cacheModule.parent.children.indexOf(cacheModule),1);}loadHandlerloadsthefile//加载指定文件的代码constloadHandler=filename=>{returnnewPromise((resolve,reject)=>{fs.readFile(filename,(err,data)=>{if(err){resolve(null);}else{try{//使用vm模块的Script方法预编译改文件代码,检查语法错误,提前查找是否有语法错误等Newvm.Script(data);}catch(e){//语法错误,编译失败reject(e);return;}//编译通过后,重启require加载最新代码resolve(require(filename));}});});};loadHandler函数的作用是加载指定的文件并验证新文件的代码语法。通过fs.readFile读取文件内容使用node原生vm模块vm.Script方法预编译改文件代码,检查语法错误,提前找出是否有语法错误。错误检查通过后,通过resolve(require(filename))方法重新加载文件require并自动添加到require.cache缓存结束:以上就是热部署的全部内容,代码地址:smart-node-reload这段代码是我的简化代码,方便大家阅读理解,有兴趣的朋友可以利用这段代码进一步扩展。...写完这篇文章,已经是凌晨两点了。写一篇文章并不容易。请各位爸爸们star、follow、like、关注。感谢你的努力工作。:https://github.com/airuikun/blog
