环境:
- window10x64 专业版
- node-v14.15.1-x64.msi
一、安装包的下载
-
网盘:
链接:https://pan.baidu.com/s/1KbBPHA369Wm71Dy5Q4Eizw
提取码:1s4x
二、安装过程
傻瓜式安装,除了修改一下安装目录,其他的用默认即可。
安装目录最好不要有空格,我这里选的是
D:\nodejs
三、安装后的变化
3.1 安装后的目录如下
安装后已经自带了
npm
。
安装后在当前用户目录下多了一个npm
文件夹,不过是空的,如下:
3.2 安装后的环境变量
检查Path
环境变量如下:
正因为nodejs自动将安装目录配置到了Path中,所以我们在命令行中直接输入node
,cmd就会自动找到D:\nodejs\node.exe
并执行。同理,D:\nodejs
目录下的npm.cmd
和npx.cmd
也让我们可以在命令行中执行命令npm
和npx
。
四、node常用命令
-
查看node版本:
node --version
或node -v
-
查看node帮助:
node --help
-
查看
node.exe
所在目录(也即:nodejs的安装目录):where node
注意:我是在window10下的cmd中执行的
-
运行指定的js脚本:
node index.js
-
进入交互式执行环境:
node
注意:虽然我们没有将交互的命令保存,但nodejs还是默认给我们保存了,看文件
C:\Users\Jackletter\.node_repl_history
:
五、关于npm
npm
是node下的包管理工具,我们可以从npm的仓库里下载包,也可以发布包,它是随着nodejs的安装而安装的。
参照:https://docs.npmjs.com/cli/v6/commands
npm常用命令:
-
查看npm版本
npm -v
或npm --version
-
查看npm配置项
npm config list
:
-
查看npm所有的配置
npm config ls -l
:
上面配置较多,不好查看,可以使用
npm config ls -l >1.txt
命令将结果输出到文件中。
上面配置项中重要的部分:- 仓库地址:
metrics-registry = "https://registry.npmjs.org/"
- prefix = “C:\Users\Jackletter\AppData\Roaming\npm”
- 缓存路径:
prefix = "C:\\Users\\Jackletter\\AppData\\Roaming\\npm"
- 全局配置:
globalconfig = "C:\\Users\\Jackletter\\AppData\\Roaming\\npm\\etc\\npmrc"
- 全局版本忽略文件:
globalignorefile = "C:\\Users\\Jackletter\\AppData\\Roaming\\npm\\etc\\npmignore"
- 初始化模块:
init-module = "C:\\Users\\Jackletter\\.npm-init.js"
- npm init使用的一些配置:
- 仓库地址:
registry = "https://registry.npmjs.org/"
- 使用的脚本程序:
shell = "C:\\Windows\\system32\\cmd.exe"
- 临时目录:
tmp = "C:\\Users\\JACKLE~1\\AppData\\Local\\Temp"
- 用户配置文件:
userconfig = "C:\\Users\\Jackletter\\.npmrc"
- 仓库地址:
-
查看npm仓库地址
npm config get registry
:
-
设置npm仓库地址
npm config set registry http://registry.npm.taobao.org/
设置完成后,查看
C:\Users\Jackletter\.npmrc
文件中已做了记录:
-
查看当前包安装路径
npm root
,查看全局包安装路径npm root -g
:
-
安装指定包
npm install koa
可以看到,将
koa
的最新版本包安装到了node_modules
目录下,并生成pack-lock.json
文件。
注意:安装的时候会将koa
所有的依赖包都安装到node_modules
下面,package-lock.json
文件里精确记录着所有下载了包的名称/版本/地址。
-
移除包
npm uninstall koa
:注意,这个命令仅移除指定的包!
-
安装指定版本的包
npm install koa@2.6.0
: -
安装指定scope的包
npm install @vue/cli
注意:这里的scope是
vue
(必须以@
开头),scope的作用是为了方便管理一系列关联的包,它们安装在客户端后会放在一个目录里,如:
关于scope解释:https://www.jianshu.com/p/ac5b5f65320b -
初始化一个目录作为工程位置
npm init
初始化后的文件内容: -
安装指定包并保存到
package.json
中npm install jquery --save
:
注意:需要先建立package.json
文件才能将安装的包添加进去 -
安装指定的包,并保存到
package.json
中,作为开发环境依赖npm install @vue/cli --save-dev
:
-
根据当前目录
package.json
文件中的描述安装依赖包npm install
或npm i
-
安装包到全局
npm install @vue/cli -g
:安装完成后,全局目录里面已经有了:
而这个目录在当前用户的环境变量里:
所以我们可以在命令行中直接运行vue ui
,如下:
-
npm version
查看当前包及环境软件的版本情况,可以使用npm init -y
初始化一个包(目录为test
),然后执行npm version
,效果如下:
六、package.json 属性解释
我们可以使用npm init
命令来创建一个package.json文件,创建后当前目录就表示为一个node包工程。
package.json
中常见的设置项如下:
-
name: 包的名称
-
version:版本号
版本号格式: 主版本号.小版本号.补丁版本号
补丁版本号表示仅修复了bug,小版本号表示添加了小的新功能且不影响现在的使用,主版本号表示进行了重大变更(比如:破坏式更新) -
description: 描述文本
-
keywords:关键字,方便别人搜索到
-
homepage:项目主页,参考vue如下:
-
bugs:提交bug地址,参考vue如下:
-
license:开源协议,参考vue如下:
-
author:作者,参考vue如下:
-
repository:源码地址,参考vue如下:
-
files:这个包所包含的文件和文件夹列表,参考vue如下:
-
main:指定这个包的入口文件,
main属性指定了程序的主入口文件。意思是,如果你的模块被命名为foo,用户安装了这个模块并通过require(“foo”)来使用这个模块,那么require返回的内容就是main属性指定的文件中 module.exports指向的对象。
它应该指向模块根目录下的一个文件。对大对数模块而言,这个属性更多的是让模块有一个主入口文件,然而很多模块并不写这个属性。
参考vue如下:
-
bin:需要注册到环境变量执行的文件,参考
@vue/cli
如下:
-
scripts:表示一些可以由
npm run xxxx
直接运行的命令,如新创建的vue3.0工程如下:
基于上面的命令,我们可以直接运行:npm run serve
以启动开发调试环境:
-
dependencies:表示编译打包依赖的包
注意:上面提到了包的版本号书写规则,那么这里写依赖包的时候也可以按照那个规则去写,一下列举常用的:(参考:《NPM版本号规则以及更新策略》)
"core-js": "^3.6.5" //表示 3.6.5以上的且4.0.0以下的都可以("^" 表示兼容声明) "core-js": "^3.6.5" //表示 3.6.5以上的且4.0.0以下的都可以(^ 表示兼容声明) "vue": "^3.0.0" //表示 3.x.x的都可以 "vue": "~2.6.1" //表示2.6.1以上且2.7.0以下的都可以("~"表示更新声明) "vue": "2.6.11" //表示精确的依赖版本 "vue": "1.0.0 - 2.0.0" //表示版本这这个之间的都可以 "vue": "2.6.x" //表示2.6之后2.7之前的都可以 "vue": "*" //表示所有的版本 "vue": "x" //表示所有的版本 "vue": ">=2.6.1 <=2.6.11" //表示在2.6.1 - 2.6.11之间的都可以
-
devDependencies:表示开发环境依赖的包,书写规则和
dependencies
一致,不过这里的包只在开发环境中需要,比如:@vue/li
-
peerDependencies:统计依赖包,这个依赖方式不同于
dependencies
和devDependencies
,因为当前包的开发、编译和运行并不直接进行依赖,而是间接的依赖,比如:开发的插件需要宿主环境,可以在这里(注:用的并不多)。 -
engines:指定运行的环境要求,参考
@vue/cli
如下:
七、npm的包以及require函数加载机制
npm中存在三种形式上的包和模块:
- 内核模块: 如:
require('fs')
、require('http')
- 本地包:如:
require('./util')
- 三方包:如:
require('vue')
require函数执行的过程为:
注意:require函数加载文件后会将加载结果缓起来,当下次调用
require
函数加载时会直接返回已缓存的内容。
-
第一步:如果没有相对路径的话就先判断是否是内核模块,如:
require('fs')
就是在此时加载进来的; -
第二步:如果有相对路劲的话,如:
require('./util')
或require('../util')
,那么就去对应的路径下寻找; -
第三步:如果没有使用相对路径的话,就认为是第三方包,于是开始列举所有可能存在的位置(
require("demo")
),如:假设我的登录账户为
jackletter
,nodejs
安装目录为d:\nodejs
, 并配置了环境变量node_path=d:\node_path;
,执行的脚本为node c:\a\b\a.js
,那么列举的路径为:- c:\a\b\node_modules
- c:\a\node_modules
- c:\node_modules
- d:\node_path
- c:\users\jackletter\.node_modules
- c:\users\jackletter\.node_libraries
- d:\nodejs\lib\node
最后,对于第二步和第三步举出的目录,依次进行搜索,搜索的方式为:
- 加上后缀.js|.json|.node去查找文件,找到就返回
- 找不到的就把这个路径当成文件夹,在这个文件夹里找
package.json
里的main
属性,找到了就返回这个指定的脚本 - 还找不到的直接在这个文件夹里查找
index.js
|index.json
|index.node
文件,找到了返回,找不到就下一条路径
八、npm & cnpm & yarn
首先npm和cnpm以及yarn都是nodejs中的包管理工具,npm是由nodejs官方支持,cnpm是淘宝开发的,yarn是国外开源的。
8.1 npm 存在一些问题:
- 不能锁定某一个特定版本,导致同一项目的不同同事的机器上运行的效果不一致。
现在的npm已经有了package-lock.json文件来显示的解决这一问题。
- 即使当前电脑的缓存中已经有了对应包的缓存,还要再走一次网络,这对于离线环境的同事简直是个灾难。
8.2 关于cnpm
淘宝开发,用法和npm类似。
8.2 关于yarn
yarn的优点:
- npm安装是串行,而yarn是并行,速度大大提升
- 已经下载过的包会被缓存,无需重复下载,更关键的是,
支持离线安装
- 精准的版本控制(yarn.lock文件),加上验证每个包的完整性,保证每次安装的npm包完全一致
- 优化的输出信息
安装yarn,将yarn
安装到全局目录: npm install yarn -g
安装完成后,在全局目录下可以看到对应的命令和包:
因为,全部目录C:\Users\Jackletter\AppData\Roaming\npm
已经注册到当前账户的path变量里面了,所以我们可以在命令行中直接使用yarn
命令了。
yarn常用的命令:参照 https://classic.yarnpkg.com/en/docs/usage
-
查看yarn命令全局安装目录
yarn global bin
:
-
查看yarn全局缓存目录
yarn global dir
:
-
初始化工程
yarn init -y
:
-
安装包到依赖
-
安装包到开发依赖:
yarn add @vue/cli --dev
-
查看当前配置:
yarn config list
-
查看和设置仓库地址:
yarn config get registry
|yarn config set registry="http://registry.npm.taobao.org/"
-
yarn的全局配置文件:
c:\Users\用户名\.yarnrc
-
yarn 设置全局缓存目录:
yarn config set global-folder "D:\test\global"
-
yarn 设置全局命令目录:
>yarn config set global-bin "d:\test\bin"
(注意:需要自定将这个目录添加到Path
环境变量里,否则使用yarn安装的全局工具将不起作用)
九、如何调试nodejs程序
这里只说一种调试方式,即:在chrome浏览器中像调试前端代码一样调试nodejs代码。
首先,准备一个脚本文件,如下(index.js):
const fs=require('fs');
console.log(fs==null);
然后,在命令行中运行:node --inspect-brk index.js
,如下:
可以看到:nodejs本身已经做好调试的准备,只等一个调试客户端。
现在,我们打开chrome,在地址栏中输入:chrome:inspect
默认情况下,chrome是配置了nodejs的两个调试端口(9229、9222),所以稍等一下就会出现调试提示(因为:chrome会检测这两个端口是否有可供调试的nodejs程序)。这里因为我把默认的9229端口给删了,所以没有出现提示。
点击Devices->Configure按钮配置nodejs可调试程序的地址,如下:
点击Done
完成配置,此时等待一会就可以看到提示了,如下:
注意:如果好大一会还没出现提示,我们也可以点击
Open Dedicated DevTools for Node
进入,如下:
我们直接点击inspect
进入调试页面:
接下来就和调试js代码一个样了。。。
可以从这里观察系统模块的代码,比如这个
require
,可以看一下它是怎么加在模块的。
可以指定调试的端口嘛?
如果我们想同时调试多个nodejs怎么办?一个端口不够用啊。
这个时候,我们可以指定调试用的端口:node --inspect-brk="localhost:8656" index.js
然后,在chrome:inspect
页面中配置nodejs调试的地址localhost:8656
,之后就可以调试了。
其实看到上面的地址,我们应该能想到,nodejs是支持跨机器调试的,即:你可以调试你同事的nodejs程序,只要对方启动调试时,绑定他的ip即可,如:node --inspect-brk="192.168.3.25:8656" index.js
。
--inspect-brk
表示启动程序并在程序第一行开始调试。这适合没有断点,或不好打断点的程序代码。
--inspect
:
表示启动应用程序并做好调试准备。这适合调试
express
等长时间运行的服务。
十、nodejs中的模块
参考:https://nodejs.org/dist/latest-v14.x/docs/api/modules.html
在nodejs中,每一个单独的.js
和.json
或.node
(插件)都被称之为一个模块
。
注意:这里说的模块和上面说的
npm的包和模块
是不一样的,这里说的模块就是单独的一个可加载文件,而npm的包和模块
是从工程角度将一批文件成为包或模块。
我们在使用require()
函数加载出来的就是这个模块要暴露给我们的东西。
事实上,我们写的每一个js文件在nodejs中执行的时候都会在外面包装一层,比如我们写的main.js
如下:
function add(x,y){
return x+y;
}
实际执行时,nodejs在外面包装一层,如下:
function(exports,require,module,__filename,__dirname){
function add(x,y){
return x+y;
}
}
上面包装函数的5个参数由nodejs运行时传递进来:
- require:nodejs系统函数对象,可用来加载其他模块;
- module:当前模块对象本身,在加载这个js脚本之前创建;
- exports:这个是module.exports属性的快捷方式,即:
exports=module.exports
(注意:加载脚本之前就创建好了module和module的exports属性:module.exports={}
); - __filename:当前脚本的绝对路径;
- __dirname:当前脚本所在的目录;
这一点可以从官方文档上看得到:
当然,也可以在调试的时候看到:
注意:
各个module(文件)对象之间可以具有依赖关系,下图所示是可能的一种关系:
从图上可以看到,它们之间是网状的一个结构,中间还有循环依赖哦~
module对象的属性:
首先,在加载js脚本之间,nodejs就已经为这个脚本创建好了模块对象(Module
),它的定义如下:
从上面可以看到,它有几个关键的属性:
loaded
:表示当前模块(脚本)是否加载完毕;
filename
:表示当前模块(脚本)的绝对路径;
path
:表示当前模块(脚本)所在的目录;
children
:表示当前模块(脚本)所依赖的子模块(子脚本);
exports
:表示当前模块(脚本)向调用者暴露的对象;
parent
:表示当前模块(脚本)因为谁而被加载(已被废弃)。
另外:
我们在模块代码中可以