Node(7),前端开发进阶吃透这一篇必拿60W年薪,前端framework面试题

CommonJS一般只将JS文件和JSON文件视为有效模块(require只支持导入js或json文件),而ES6将任何文件都视为模块(import path语法支持导入任何类型文件)

模块三要素的区别

1、CommonJS将模块包装函数的函数作用域 作为 模块独立作用域,是运行时确定的。

由于ES6模块是在编译时(静态分析时)确定的,此时没有全局变量或模块变量之分,变量是运行时产生的,所以也不会产生变量污染

2、导出导入

CommonJS模块的导出module.exports的是对象,

ES6模块的导出接口export是静态分析阶段的符号链接

访问CommonJS模块的导出对象module.exports,其实访问的是对应模块导出数据的浅拷贝,

对于简单值来说,和原模块无关,对于引用值来说,和原模块有关。

访问ES6模块的导出接口export,其实是访问的对应模块的实时数据,无论是简单值还是引用值都和原模块有关

导入导出语法区别

CommonJS模块导入使用require函数,导出使用module.exports对象

ES6模块导入使用import path 或者 import { somename as anyname} from path 或者 import anyname from path

导出使用export 或 export {} 或 export default

ES6的导入导出语法更复杂一点,CommonJS的简单一点

模块代码的执行时机

CommonJS模块代码运行是在模块首次被require时,

ES6模块代码运行是在模块首次被import时

深入了解请看下面关于模块化的总结

(1条消息) 随笔-深入理解ES6模块化(三)_qfc_128220的博客-CSDN博客 随笔-深入理解ES6模块化(三)_qfc_128220的博客-CSDN博客")

Node.js的软件包管理器(npm)


啥是软件包

基于Node.js开发的应用程序都可以看成一个Node Package,Node package中通常都有一个包描述文件package.json。

啥是软件包管理器

npm (Node package manage),即软件包管理器,我们下载Node.js时,会默认捆绑下载npm。

它是一个命令行工具。

npm 可以通过命令行管理Node应用程序依赖的第三方软件包,比如下载、删除、更新、查看第三方软件包。

npm 下载和更新第三方软件包的默认地址是 npmjs.com,

npmjs.com 是一个Node软件包管理网站,开发者可以将自己开发Node软件包共享到该网站,也可以从该网站下载Node软件包。

认识package.json

一个Node软件包的项目根目录下必须有一个package.json文件,该文件用于记录当前软件包的一些基本信息。

我们可以在Node软件项目根目录下使用npm命令,生成一个由用户自定义的package.json

npm init

或者加上 --yes 或简写 -y 参数 来自动生成一个采取默认定义的package.json

npm init --yes

npm init -y

接下来,我们看下package.json包含哪些信息

npm init 生成的package.json只包含一些基本的软件包信息:

name软件包名字,或者项目名字
version软件包版本号
description软件包描述
main软件包入口文件
script软件包的自定义命令
keywords软件包的搜索关键词
author软件包的作者信息
license软件包的许可证信息,ISC表示开源

这些信息都是比较重要的信息,而其中常手动改的是 main 和 script

main用来指定当前软件包的入口文件,作用有两个:

1、我们可以通过查看一个软件包根目录下的package.json中的main配置,快速得知当前软件包的入口,而不需要分析代码

2、package.json中main配置 是 模块查找规则 的重要一环。比如 node test 或 require(‘test’),会先去当前目录下找test.js,再找test.json,如果都没有再找test文件夹,如果有,就继续找package.json中main配置的入口文件,如果有,入口文件会被当成找到的模块被运行或被引入。

script是用于配置当前软件包一些常用命令的npm run简写的:

比如上面可以使用 npm run serve 代替npx vue-cli-service serve。

下载第三方软件包

使用 npm install packagename 或者简写 npm i packagename 即可下载指定的软件包,命令执行完后,本地Node应用程序会发生如下变化:

1、下载软件包会被保存在项目根目录的node_modules文件夹下,如果没有node_modules文件夹,则会自动生成

2、package.json会发生变化,配置项多出一个 dependencies ,其中保存着下载的软件包名字 和  软件包版本号 组成的键值对

3、项目根目录下会多出一个 package-lock.json文件,该文件会记录下载的软件包的下载地址,以及该软件包依赖的其他软件包的下载地址

项目依赖和开发依赖

我们下载的第三方软件包有两种用途:

1、用于项目中业务逻辑的开发,比如 formidable,express

2、用于辅助开发者高效开发,和项目业务无关,比如一些常用的命令行工具nodemon,eslint,

我们有必要将他们区分开来,原因是:

项目上线后,其实并不需要和项目业务无关的第三方软件包,只需要和项目业务有关的第三方软件包。

但是项目开发过程中,又需要协同开发,即至少要保证大家使用一样的开发工具。

而Node应用程序考虑到了这一点,在项目的package.json将依赖的第三方软件包分为了两类:开发依赖 和 项目依赖

开发依赖的第三方包 会被保存在 dev-dependencies中

项目依赖的第三方包 会被保存在 dependencies中

而我们只需要在下载第三方包的时候,指定一些参数即可实现分类:

npm i --save packagename  即下载时指定–save,npm就自动将下载的包添加到package.json的dependencies中,即项目依赖

简写形式是:npm i -S packagename

最简形式是:npm i packagename

目前 npm i packagename 默认会将下载的第三方包当成“项目依赖”

npm i --save-dev packagename 即下载时指定 --save-dev,npm就自动将下载的包添加到package.json的dev-dependencies中,即开发依赖

简写形式时:npm i -D packagename

本地下载和全局下载

我们使用 npm i packagename时,默认将第三方软件包下载到 项目根目录下的node_modules文件夹中。

此时该第三方包只在当前项目中起作用,我们称这种下载叫本地下载。

如果我们本地有多个Node项目,如果每个Node项目都依赖一些相同的第三方包,则为每一个Node项目都下载一遍,会造成内存浪费。此时就需要将多个项目都需要的公共包,下载到全局下,即所有项目都可以访问到的地方,避免内存浪费。此时下载叫做全局下载。

全局下载只需要添加一个-g参数

npm i -g packagename

如果想知道全局下载的软件包的存放路径,则可以使用命令

npm root -g

需要注意的是:

全局下载的Node软件包如果是命令行工具,则其命令会被自动被注册为系统变量,在任意目录下都可用。

而本地下载的命令行工具Node软件包,由于其命令不会被自动注册为系统变量,所以无法在任意目录下直接使用其命令,只能通过npx命令来调用

例如,只在项目中安装nodemon(保证全局下没有nodemon,使用npm list -g查看)

此时nodemon命令不会被自动注册为系统变量,所以无法在任意目录下使用nodemon命令。需要借助npx命令借调nodemon命令

为什么下载到全局的node软件包的命令会自动注册为系统变量呢?

1、安装好Node.js后,会自动将node_global目录加入系统变量Path中

2、我们下载全局软件包时,会自动存放在node_global下

3、如果下载的全局软件包是命令行工具,则会将cmd命令文件放到node_global目录下,这就保证了如nodemon.cmd这样的命令可以在任意目录下使用

那么我们是否可以将所有开发依赖的软件包都从项目本地,转移到全局呢?

一般来说不会这样搞,将项目本地的node包单分出一个开发依赖,其实就是为了团队之间的协同,如果大家都自己搞自己的,可能对于新人不太友好。

软件包的语义化版本

在package.json中有三个地方存在软件包的版本号信息

1、package.json的version配置

2、package.json的dependencies配置

3、package.json的dev-dependcies配置

其中

version 版本号,指的是当前项目的版本号,由我们控制版本的升级

而dependencies和dev-dependencies中的版本号,是当前项目依赖的第三方Node包的版本号,不由我们控制。

通过上图,我们可以发现版本号由三部分组成,即 major.minor.patch

解释升级时机
major主要版本号已有需求发生改变,并且改变了已有功能
minor次要版本号已有功能不变,开发了新需求的功能
patch补丁版本号修复了已有功能的bug,需求不变

分析一下,patch和minor升级是向低版本兼容的,而major升级不向低版本兼容。

所以,我们项目依赖一个第三方包后,一般都需要锁定major版本,防止更新包后,新版本的第三方包代码不向下兼容。

此时就需要给版本号加入语义化。如上图中 package.json的 dependencies 依赖的第三方包的版本号前面有个^,这就是语义化符号。

^major.minor.patch表示锁定major版本,只能升级minor和patch版本
~major.minor.patch表示锁定major和minor版本,只能升级patch版本
major.minor.patch表示锁定major,minor,patch版本,不让升级

下载指定版本号的第三方软件包

前面我们下载第三方软件包时,都是只指定了包名,没有指定具体版本号,此时下载就是第三方包的最新版本,即

npm i packagename

下载的时packagename包的最新版本。

但是有时候最新版本并不稳定,所以我们一般下载比较稳定的老版本,此时就需要指定版本号

npm i packagename@major.minor.patch

但是我们可能并不知道对应第三方包有哪些版本,此时需要借助命令查询第三方包历史版本列表

npm view packagename viersions

更新第三方软件包

更新项目依赖的第三方软件包时,需要注意:

1、当前依赖的第三方软件包是否过时了

2、当前依赖的第三方软件包是否被锁定

通过命令 npm outdate 就可以查看当前项目依赖的第三方包是否存在过时的,如果有会全部列出来

我们发现 eslint和nodemon都过时了,且nodemon最新版本是2.0.15,但是只能升级到1.19.4。而eslint最新版本是8.6.0,但是只能升级到1.10.3,即当前版本,即eslint无法再升级了。

再看这两个包的版本锁定情况

发现都被锁死在了major版本,即major版本不允许升级,minor、patch版本可以升级。而这也是导致eslint和nodemon无法升级到最新版本,只能升级到major为1的最高版本。

更新版本时,使用如下命令可以更新所有过时的第三方包到锁定的最高版本,而不是最新版本

npm update

而 npm outdate 和 npm update 命令加上-g参数,就可以查看和更新全局下的过时Node包

删除第三方软件包

通常使用命令

npm uninstall packagename

来删除项目本地指定的第三方软件包,

或者使用其简写命令

npm un packagename

加上 -g 参数就可以删除全局下的第三方软件包

查看第三方软件包元数据

一个第三方软件包,包含了各种元数据,比如包名,最近更新时间,历史版本列表,作者,

这里我们可以使用命令

npm view packagename

来查看指定软件包的所有元数据信息

也可以加入元数据配置项参数,来查看特定元数据信息,如命令

npm view packagename views

获取依赖的所有第三方软件包,及其依赖包列表

比如,获取项目本地下载的所有第三方软件包使用命令

npm list

加上 -g 参数表示,获取全局下载的所有第三方软件包

npm list -g

但是npm list目前只能查看被依赖的第三方软件包本身,无法查看第三方软件包依赖的包,这里提供了 --depth num,来指定查看的层级,默认npm list相当于 npm list --depth 0

npm list -g --depth 1

项目直接依赖包和项目间接依赖包

我们项目下载了一个第三方软件包,比如mongoose,那么它就成为了我们项目的一个依赖包。

但是mongoose本身也是一个项目,它也有很多依赖包,也需要被下载。

即:我们下载mongoose包,则会自动下载mongoose包的依赖包。其中mongoose就是当前项目直接依赖包,mongoose的依赖包就是当前项目间接依赖包。它们都是当前项目必须的。

上面查看,当前项目的依赖包只有一个mongoose,但是实际上,当前项目根目录node_moudules文件夹中下载的第三方包包含:

可以发现 “项目直接依赖包” 和 “项目间接依赖包” 都会被存放在 项目的node_modules文件夹下

这就会造成一个问题:

比如项目下载 A包,A包依赖于 Z@1.0.0包,项目又下载了B包,B包依赖于Z@2.0.0包

那么按照上面下载规则,A,B,Z包都会放在项目的node_modules文件夹下,那么Z包是否会发生冲突覆盖?

答案:不会,因为 项目间接依赖包 下载遵循如下规则

项目直接依赖包 会被直接下载到 项目的node_modules下,

而项目间接依赖包 下载前,会检查当前项目node_modules下是否已有该包,

没有的话,则将项目间接依赖包 下载到 项目的node_modules下,

有的话,则将 项目间接依赖包 下载到 项目直接依赖包 的node_modules下

这样就避免了项目间接依赖包之间发生冲突。

那么为什么不直接将 项目间接依赖包 直接下载到对应的  项目直接依赖包的node_modules文件夹下呢?

因为,项目直接依赖包 之间 存在大量重复的 依赖包,如果将项目间接依赖包 直接 存放再 项目直接依赖包下,可能会造成大量的重复包下载,浪费内存。

npm常用命令总结

增 

不指定版本号新增

(最新版本)

npm i pakcage
指定版本号新增npm i package@major.minor.patch
项目新增
开发依赖-D
项目依赖-S 或 无
全局新增-g
npm un package
项目删除
全局删除-g
查询过期依赖包npm outdate 

更新过期依赖包

(到锁定最高版本)

npm update 

项目更新
全局更新-g

查询项目所有依赖包npm list --depth
查询项目依赖包元数据npm view package 元数据配置
项目更新
全局更新-g

项目node_modules目录是否需要提交git

答案:不需要,项目node_modules存放的都是依赖第三方软件包代码,体积很大,如果上传到git仓库的话,很浪费时间。

所以我们一般在项目根目录的.gitignore文件中设置忽略 node_modules/ 的提交

那么项目发布到npmjs.com后,其他人下载后,如何获取项目的node_modules依赖包。

当我们项目下载依赖包后,依赖包的版本号和下载地址都保存在了项目根目录下的package-lock.json中,当其他人下载项目后,使用npm i package会自动根据软件包的package-lock.json去下载对应的依赖包。

项目开发过程中,拉取git仓库代码到本地,也是没有node_modules的,此时只需要 npm install 即可自动根据package-lock.json快速下载依赖包

发布软件包和更新软件包版本号以及撤回软件包

当我们项目开发完成后,需要共享到npmjs.com时,即表示发布软件包,发布软件包需要先登录npmjs.com,使用命令

npm login

登录到npmjs.com后,再使用如下命令来发布项目到npmjs.com的个人空间中

npm publish

当项目发生版本更新后,可以使用如下命令来更新项目的版本号,即package.json中的version

npm version major  // 更新major版本

npm version minor // 更新minor版本

npm version patch // 更新patch版本

当项目发布错误,或者版本存在重大Bug时,需要撤回已发布的版本时,如果在24h内,则可以撤回,24h后不可撤回,撤回成功后,24h后才能重新发布,且重新发布的包的名称和版本号都要修改

npm unpublish package --force

更改npm镜像地址

在国内更改npm镜像地址是一个有必要的操作,因为默认按照的npm的地址是npmjs.com,这个网址是国外网站,下载上传速度很慢。而npm的地址是npm的配置信息之一。我们可以查看npm的所有配置,使用如下命令

npm config list

可以使用如下命令获取特定的npm配置信息

npm config get registry

可以使用如下命令设置特定的npm配置信息

npm config set registry https://registry.npm.taobao.org/

可以使用如下命令删除特定的npm配置信息

npm config delete registry

可以使用如下命令修改特定npm配置信息

npm config edit registry https://registry.npmjs.com/

而npm的配置信息都保存在一个文件中,我们可以通过如下命令获取到对应文件的地址

npm config get user

Node.js的异步编程(异步编程方案+Event Loop)


异步原理

Node.js 是基于 Chorme v8引擎开发的JS运行环境,所以Node.js生来支持ECMAScript语法。

而我们知道JavaScript代码是单线程运行的,为了提高JS代码执行效率,不让JS代码被某些不依赖于CPU的操作所阻塞,如I/O操作,出现了很多事件驱动的,基于回调函数的Node APIs。

“事件驱动,基于回调” 的 意思是:当 … 时候,JS单线程再来执行… 回调。

这就是JS的异步编程原理。

异步任务串行的实现

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

更多面试题

**《350页前端校招面试题精编解析大全》**内容大纲主要包括 HTML,CSS,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,项目,职业发展等等

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

的,基于回调函数的Node APIs。

“事件驱动,基于回调” 的 意思是:当 … 时候,JS单线程再来执行… 回调。

这就是JS的异步编程原理。

异步任务串行的实现

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-Kb6d0qPO-1710829153353)]
[外链图片转存中…(img-dBNyjL9i-1710829153354)]
[外链图片转存中…(img-sdQPbU6k-1710829153354)]
[外链图片转存中…(img-BiQGrLQP-1710829153354)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-SQakgO1x-1710829153355)]

更多面试题

**《350页前端校招面试题精编解析大全》**内容大纲主要包括 HTML,CSS,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,项目,职业发展等等

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

[外链图片转存中…(img-FzzdpCdp-1710829153355)]

  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值