三面面试官:运行 npm run xxx 的时候发生了什么?

JavaScript025

三面面试官:运行 npm run xxx 的时候发生了什么?,第1张

面试官:npm run xxx的时候,发生了什么?讲的越详细越好。

我(心想,简单啊): 首先,DNS 解析,将域名解析成 IP 地址,然后

TCP 连接,TCP 三次握手...

面试官:停停,我问的不是从URL输入到页面展现到底发生什么?,是npm run xxx的时候,发生了什么。

我(尴尬,条件反射地以为是问的八股文):emmmm,我记得 npm run xxx的时候,首先会去项目的package.json文件里找scripts 里找对应的xxx,然后执行 xxx的命令,例如启动vue项目 npm run serve的时候,实际上就是执行了vue-cli-service serve 这条命令。(好险,幸好这点常识我还是懂的)

package.json文件

面试官:嗯,不错,那 为什么 不直接执行 vue-cli-service serve 而要执行 npm run serve 呢?

我(支支吾吾):emm,因为 npm run serve 比较简短,比较好写。

面试官:你再想想。

我(啊?不对吗,对哦,我想起来了): 因为 直接执行 vue-cli-service serve ,会报错,因为操作系统中没有存在 vue-cli-service 这一条指令

面试官: 哦,对对对,不错不错,哟西哟西!

我(嘿嘿,稳了,这次我要30k): 嘻嘻!

面试官:那既然 vue-cli-service 这条指令不存在操作系统中,为什么执行 npm run serve 的时候,也就是相当于执行了 vue-cli-service serve ,为什么这样它就能成功,而且不报指令不存在的错误呢?

我(啊?要不你还是把我鲨了吧,不想再勉强作回答):不好意思,这个我还没了解过。

面试官:emmm,好吧,没关系,我们做下一道算法题吧:....

....

后面无关此次文章的内容,就省略过了。

面试官:好的,此处面试到此结束,我们会在一周内回复您的面试结果

哔哔哔...(电话挂断)

唉。看来是凉了

为什么执行 npm run serve 的时候,这样它就能成功,而且不报指令不存在的错误呢?

我赶紧问问了大佬朋友这一过程到底是发生了什么

经过一番讨论,终于找到了答案。

不服输的我,赶紧回拨了面试官的电话号码。

我:喂,面试官,您好,我已经找到答案了,可以麻烦您再听一下吗?

面试官:嗯,可以啊,请讲。

我:我们在安装依赖的时候,是通过npm i xxx 来执行的,例如 npm i @vue/cli-service ,npm 在 安装这个依赖的时候,就会 node_modules/.bin/ 目录中创建 好 vue-cli-service 为名的几个可执行文件了。

.bin 目录,这个目录不是任何一个 npm 包。目录下的文件,表示这是一个个软链接,打开文件可以看到文件顶部写着 #!/bin/sh ,表示这是一个脚本。

由此我们可以知道,当使用 npm run serve 执行 vue-cli-service serve 时,虽然没有安装 vue-cli-service 的全局命令,但是 npm 会到 ./node_modules/.bin 中找到 vue-cli-service 文件作为 脚本来执行,则相当于执行了 ./node_modules/.bin/vue-cli-service serve (最后的 serve 作为参数传入)。

面试官:可以啊,真不错,但是我还想继续问问,你说.bin 目录下的文件表示软连接,那这个bin目录下的那些软连接文件是哪里来的呢?它又是怎么知道这条软连接是执行哪里的呢?

我(窃喜,这个我们刚刚也讨论了):我们可以直接在新建的vue项目里面搜索vue-cli-service

可以看到,它存在项目最外层的 package-lock.json 文件中

从 package-lock.json 中可知,当我们npm i 整个新建的vue项目的时候,npm 将 bin/vue-cli-service.js 作为 bin 声明了。

所以在 npm install 时,npm 读到该配置后,就将该文件软链接到 ./node_modules/.bin 目录下,而 npm 还会自动把node_modules/.bin加入$PATH,这样就可以直接作为命令运行依赖程序和开发依赖程序,不用全局安装了。

假如我们在安装包时,使用 npm install -g xxx 来安装,那么会将其中的 bin 文件加入到全局,比如 create-react-app 和 vue-cli ,在全局安装后,就可以直接使用如 vue-cli projectName 这样的命令来创建项目了。

面试官:搜噶,也就是说,npm i 的时候,npm 就帮我们把这种软连接配置好了,其实这种软连接相当于一种映射,执行npm run xxx 的时候,就会到 node_modules/bin中找对应的映射文件,然后再找到相应的js文件来执行。

我(疯狂点头):嗯嗯,是的,就是这样

面试官:我有点好奇。刚刚看到在node_modules/bin中 有三个vue-cli-service文件。为什么会有三个文件呢?

我:如果我们在 cmd 里运行的时候,windows 一般是调用了 vue-cli-service.cmd ,这个文件,这是 windows 下的批处理脚本:

所以当我们运行 vue-cli-service serve 这条命令的时候,就相当于运行 node_modules/.bin/vue-cli-service.cmd serve 。

然后这个脚本会使用 node 去运行 vue-cli-service.js 这个 js 文件

由于 node 中可以使用一系列系统相关的 api ,所以在这个 js 中可以做很多事情,例如读取并分析运行这条命令的目录下的文件,根据模板生成文件等。

面试官:原来如此,不错嘛小伙子,短短时间内就掌握清楚了,看来学习能力很强,不错不错,我很看好你,我会催hr尽快回复你的。先这样了,拜拜

我(欣喜若狂,功夫不负有心人啊):好啊,好啊,拜拜

哔哔哔...(电话挂断)

过了三十分钟....

今天是个好日子,心想的事儿都能成,今天是个好日子,打开了家门咱迎春风...(手机铃声响起)。

我:喂,您好。

hr:您好,我是xxx公司的hr,根据你面试的优秀表现,恭喜你获得了我司的offer,经过我最大的努力,我给你争取到了最大的薪资,薪资是月薪3500,您看满意吗?

我:....

哔哔哔....(电话挂断)

tmd,c

https://blog.51cto.com/u_15077533/4531157

https://juejin.cn/post/6971723285138505765

哪有图片?看不到图啊。

简单说一下吧,明朝科举考试限定采用八股文形式作答。

八股文是一种专讲形式、没有内容,文章的每个段落死守在固定的格式里面,连字数都有一定的限制,人们只是按照题目的字义敷衍成文。开始先揭示题旨,为“破题”。接着承上文而加以阐发,叫“承题”。然后开始议论,称“起讲”。再后为“入手”,为起讲后的入手之处。以下再分“起股”、“中股”、“后股”和“束股”四个段落,而每个段落中,都有两股排比对偶的文字,合共八股,故称八股文。

明初洪武年,我们的重八兄弟想弄个好出身,据说他曾想列入朱熹的祖制下,但是因为朱熹老人家实在是与他的年代相距太近了,而重八兄弟家里几代贫农,怎么套都套不上去,所以认祖归宗这个事情没办成,但是朱熹老先生仍然被我们的重八兄弟尊奉为圣人,而这八股文,就必须严格遵守朱熹的思想,任何考生做八股文都不准自由发挥,你想想,朱熹老先生就这么几篇著作,而且他是宋末的人,思想和世界观是多么的落伍,所有学子都按照他的思路去学习去钻研,这等于完全限制束缚了当时学子的思想。(清朝是遵循《四书》、《五经》。)

当然,即使在这么严苛的条件下,还是有那么几个牛叉的人物能够在八股文的限制下结合出他们自己的观点和思想,写出旷世奇文。

图片看不到,不过既然名为《科举考生看榜图》,这里也可以简单说一些背景。

洪武时期的科举制比较完善,也很严格。

第一关是院试,考者称“童生”,院试成绩分六等,评最高等的才拥有秀才称号。秀才见官不跪的,也算一个有名望的归宿了。

第二关是乡试,乡试可不是一乡的考试,而是省一级的考试。三年才有一次,院试评一、二等成绩的才可以去参加。能够在这一级别过关的,就叫举人。这个举人可不得了,是可以做官的,但是不包管做官,有点像现在的大学毕业不包分配,啥工作你还得自己去找。在芸芸众生里能够出类拔萃是多么的不容易,但是这仅仅才是第二关,范进中举的故事知道吧,这老小子中个举就疯了,可见当时的中个举人是多么的难。当然,在这一级考试中的第一名,就叫解元,相当于现在的省状元,也是三元里的第一元。

第三关是会试,是各省精英汇聚的考试。先是考选贡生,一般是选300人,也就是从上万的各省精英里面只选300个更精英的学子出来,还只是个贡生。会试第一名叫做会元,是三元里的第二元。通过会试的精英们面对的最后一道考验就是殿试,考试方式是皇帝提问,考生回答,内容主要是策问,皇帝及大臣根据考生的表现,会划分档次,共有三甲,一甲只有三个人,叫进士及第,分别是状元、榜眼、探花,这个地球人都知道。二甲若干人,叫赐进士出身,三甲若干人,叫赐同进士出身。状元就是第三元了,谁能连中三元,谁就牛叉。

以上三关就是这个时代的莘莘学子们从官之路所要面对的重重关卡。因为这些关卡的难度确实太高,至少比现在考大学难多了,所以楼主说的图里的考生看榜图,考生的样子可想而知啊。

另外说一个小背景,我们的重八兄弟对待官员可不算优待。他的那些难兄难弟基本上都被他杀光了,更何况下面的官员呢?据说重八兄弟当政时期,杀官员数万啊,四大名案里他老兄杀起官来是从不手软,揪出一个杀全家,即使有一点点瓜葛的也要受牵连。当时作官的,可是个个胆战心惊,如果看见锦衣卫带队来到家里,那基本上就可以交代后事了。

以上全是手打的,快累死我了。虽然因为看不到图没办法用什么文字去描述这个图,但是有这些背景在这里,楼主应该能够了解了吧!

正值测试阶段,抽时间做一次总结。

由于历史原因,部门的技术栈相对落后且不统一,ng1、react、vue、node、甚至jsp等前后端不分离的比比皆是。但没办法啊,毕竟业务驱动,重构、追赶新技术是需要很大成本的。

米币支付这个项目之前就是前后端不分离的,这次他们希望沿用之前的技术减少时间和人力成本,毕竟前后端分离接口都得改。那我不干啊,好不容易重构了,不向前兼容,怎么还后退了呢。据理力争,找接口协商,最后接口可以完全抽出一个人力配合,才同意前后端分离。本来想采用vue + ts的,但ts被否决了,理由是组内还没有ts的项目,怕后期的维护成本加大,行吧,咱也退一步。

说实话,现在很不屑于做这种项目,没有任何技术难点,没有任何挑战。但没办法,这就是你的工作。

一个多月时间,从项目架构、开发、多语言、CI/CD,错误上报/性能监控全流程搞了一遍,也算摸清了公司的流程。

更细节的内容在组内做了次分享,由于我司对信息安全这一块查的很严,也就不提了。

下面主要说做的性能优化吧,毕竟面试也会关注这一点(有句话:你在这家公司所做的一切都是为下次跳槽做准备),没有实际经验,单靠八股文还是心虚呀。

小文件合并使用 webpackChunkName 注释, 同名的就会合成一个文件

打包后发现有不少几kb的文件,可以将它们合并成一个,以空间换取时间。

合并之后

下面全是Nginx配置。

压缩前:

压缩后:

由Nginx压缩是需要消耗时间和性能的,可以前端进行压缩,然后配置Nginx。

webpack 压缩前后,生成的.gz文件

部署到nginx上。配置nginx,nginx会优先返回资源目录下存在的.gz文件

配置以后我怎么知道返回的压缩文件是由nginx返回的还是前端打包好的呢?

第一步介绍过前端没有打包生成gzip文件之前,由nginx压缩的文件的ETag具有 /W 前缀。

直接返回前端生成的压缩文件,ETag没有 /W 前缀。

下面是Nginx的配置和说明。

因为支付涉及到很多调用方,需要兼容已有的地址,所有路径前缀和资源前缀不一致。关于路径前缀配置在 vue-router 中配置base即可。资源前缀在webpack中配置publicPath。而静态资源都放在服务器的mibi目录下,所以就会有上面html和静态资源的配置不一样的情况。

接口映射是因为前后端分离后,分开部署,所以接口需要做一次转发。

HTTP缓存是性能优化很重要的手段之一。

现在的项目一般都是SPA(多页面也一样),编译打包后生成的静态资源名都带有hash值。所以把html设置成协商缓存。如果资源内容改变,生成新的hash值,资源URL自然也变了,所以js、css、img等设置成强缓存。缓存有效期可以很长,但是也不要太久,一般30天,不然假如频繁更新前端资源,废弃的资源将一直存留在用户的磁盘,会搞死用户的。

以上就是本次项目做的一点性能优化。