Node.js

一 介绍

Node.js是一个开源的、跨平台的JavaScript运行时环境,使JavaScript可以运行在浏览器端之外;Node.js是事件驱动的架构,支持异步IO,单线程;Node.js实现了CommonJS的模块加载功能(当然也支持ES6模块语法)。

但是开发者常用Node.js制作进行前端开发的工具(如Gurnt、Gulp和Webpack),进行前端开发。

二 模块

模块(module)是一个可复用的功能模块,一个模块对应一个Js文件,模块可导出模块内的变量、函数、对象给其他模块使用。

一个package(包)可含有一个或多个module,但只暴露某个模块(通过package.json中的main属性)。package.json记录该包的所有属性,如包依赖、作者等。

把package看成是module也行,毕竟只暴露一个文件的导出,在被引入时表现得像本地模块一样,

2.1 module

模块通过module.exports导出对象(exports),通过require获得对象(exports),下面直接看模块的实现原理。

2.1.1 module wrapper

假设一个模块:

const PI = 3.14159265359;

exports.area = radius => (radius ** 2) * PI;
exports.circumference = radius => 2 * radius * PI;

其他模块中要引入该模块时,会用一个匿名函数包裹该模块:

(function (exports, require, module, __filename, __dirname) {
    module.exports = exports = {};

    // Your module code ...
	const PI = 3.14159265359;

	exports.area = radius => (radius ** 2) * PI;
	exports.circumference = radius => 2 * radius * PI;
});

require一个模块时,会执行该wapper函数,得到模块导出的对象module.exports

可以看出exportsmodule.exports指向同一个对象,但最终导出的是module.exports对象。因此如果直接exports=obj赋值对象,由于是引用传值的,并不会修改module.exports导致该对象没有被导出,需要使用module.exports=obj

wrapper函数的参数module不是全局的,每个模块都有一个module,它除了包含模块导出对象exports外,还包含id、parent、children等等。

剩下的__filename表示当前模块文件路径;__dirname表示模块文件所处的目录路径;require是用来导入其他模块的函数。

2.1.2 require

使用方式如:

const fs = require('fs');

fs.readFile('./file.txt', 'utf-8', (err, data) => {
  if(err) { throw err; }
  console.log('data: ', data);
});

require()函数返回的是被导入模块导出的对象exports。函数参数传入模块的文件名(无后缀),它会安装下面的方式查找模块:

  1. 内置模块:查找Node.js内置模块(如fs)
  2. 社区共享的modules:查找node_modules文件夹下的package的文件夹名。即传入的是package名,它会返回该package出口文件(main属性指定)的导出对象。

    如果知道该package中某个文件具体的名字,可直接引入,如packageName/fileName.js

  3. 本地模块:如果require参数名以./,/../开始,它会在当前目录查找本地模块。

把package看成是module也行,毕竟只暴露一个文件的导出,在被引入时表现得像本地模块一样

2.1.3 exports

没啥好讲的,2.1.1小节讲完了。

2.2 package

一个package包含多个module,使用package.json记录该package关键的信息。

package.json一些字段如下:

  • main:指定该package的入口文件,当require(packageName)时,会导出package入口文件的exports
  • scripts:定义脚本命令,通过npm run来执行。
  • dependencies:该package依赖的其他包
  • devDependencies:开发时需要的依赖包。

package安装有全局安装(npm install --global)和局部安装(默认)两种方法。

  • 全局安装:package会被安装到/usr/lib/node_modules/usr/local/lib/node_modules目录下。package如果有可执行脚本的话,会被添加环境变量下,因此可以直接执行它(如npm)。package下的模块不能直接require全局安装的模块,需要使用npm link创建符号链接。
  • 局部安装(默认):package会被安装到当前package的node_modules目录下。如果有可执行文件,会被放入node_modules/.bin目录下,需要使用npx执行,它会自动在对应文件夹中寻找。

默认下,局部安装时,安装的依赖会被记录在package.json文件的dependencies字段中,添加选项--save-dev可将依赖记入在devDependencies字段中。

之所以可以直接执行Node.js脚本,是因为在linux环境中,解析型脚本在首部添加了#!/usr/bin/env Interpreter,它会在执行时使用指定解析器。

三 使用

3.1 安装Node.js

可从Long Term Support (LTS) version of Node中查看Node目前长期支持版本(LTS),最好选择v10.15.3版本的。在download page中下载Node.js;对于Linux,使用包管理器安装,参考package manager

我使用的是WSL的Ubuntu,安装命令如下:

# Using Ubuntu
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -y nodejs

安装时,它会自己全局安装npm包,并且该包含有可执行脚本,因此可以使用npm命令

3.2 npm init && node

尽管node命令可以直接执行js脚本(如node index.js),但最好还是使用npm init初始化产生package.json,它记录包依赖关系,可以在发布时无需附带其他package,使用时再安装。

npm init # 之后一直回车,使用默认选项
# 或者
npm init -y

使用过程中,对node_module文件夹或package.json的修改都会产生package-lock.json文件,也记录这依赖关系,但它是为了保证重新安装依赖时版本树的一致性而存在的,因为package.json使用了语义版本规则。重新安装包(npm install)时,会安装package-lock.json指定的版本安装。晕=_=
package-lock.json不存在时,重新安装依赖包,会根据语义版本规则安装:即主版本号一致,尽量安装最高的版本。

3.3 npm install

安装package,分全局和局部安装,如:

# 全局
$ npm install uglify-js --global
# 局部
$ npm install uglify-js
# 根据配置文件安装所有局部依赖
$ npm install
# 安装局部依赖为开发依赖
$ npm install uglify-js --save-dev
# 安装指定版本package
$ npm install underscore@1.9.0

一般依赖包(node_modules)不会放入git仓库中,取出来后,使用npm install会自动安装所有的依赖(包括开发依赖包),但依赖的开发依赖包不会被安装(即开发依赖包无传递性)

npm安装package分全局或局部安装,全局安装的package如果有可执行文件(如npm),它会被添加到环境变量中,因此可以直接执行(如npm install underscore);局部安装且有可执行文件(位于node_modules/.bin/目录),此时可用npx来执行,它会自动寻找,如npx cowsay "Hello"

安装的package的版本受package-lock.json影响

3.4 npm list

实现已安装依赖形参的关系树

#全局
$ npm list --global
#全局,但指定深度
$ npm list -g --depth=0
#局部依赖树
$ npm list

3.5 npm uninstall

卸载package

$ npm uninstall underscore

3.6 npm update

更新包,它会同时修改package.json和package-lock.json文件,单独修改package.json是无效的。

$ npm update underscore

安装package后,再次npm install 该package,貌似也能升级,达到同样的效果。

3.7 npm search

在npm仓库中搜索package

$ npm search mkdir

3.8 npm run

运行package.json中scripts字段的脚本(shell脚本),如

{
  // ...
  "scripts": {
    "build": "node build.js"
  }
}

此时可运行

$ npm run build
# equivalent to execution
$ node build.js

显示所有可运行命令

$ npm run

运行过程:开启新shell,并暂时将node_modules/.bin添加到环境变量中,然后运行脚本。

默认值、hooks、缩写,略!

参考:https://www.tutorialdocs.com/article/npm-scripts-tutorial.html

3.9 npm link

一般情况下,全局package不能直接引入,需要npm link创建符号链接。或者直接指定绝对路径。

3.10 npx

执行局部package的可执行文件(位于./node_modules/.bin/目录下),如

npx cowsay

3.11 npm

上面的命令都是通过npm执行的,这里介绍的是它的帮助命令,如:

# 查看npm的使用
npm help
# 查看install命令的使用
npm help install

3.12 缓存

安装过的package会被缓存起来。

参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值