超详细Node.js入门适合新手(Nvm,进程与线程,模块化,NPM)

796 阅读10分钟

学习node.js可以配合这里的b站视频一起学习

Node.js入门

node.js是基于chrome V8引擎的JavaScript执行软件
node.js也就是JavaScript的解析器,提供了js的运行环境

以前JavaScript的代码都是由客户端游览器解析,运行环境是游览器,游览器有安全级别限制。所以没有操作磁盘⽂件IO以及⽹络编程,处理⽹络请求,搭建HTTP服务器等功能操作。有了node.js,JavaScript不仅能完成如上功能,还能跨平台运行,在服务器端运行。js也能作为后端语言。

node.js的特性:
  1. 文件读写(File System)
  2. 进程管理(Process)
  3. 网络通信(HTTP/HTTPS)

以上特性以游览器作为运行环境时都不能操作。

Nvm(node.js version management,node的版本管理工具)

由于node.js有许多版本,不同项目需要对应版本才可以运行。我们可以先安装Nvm就可以管理并安装多个node.js。

下载地址:github.com/coreybutler…

解压后安装nvm,安装时保存下Nvm与node.js的路径,后面直接下一步下一步

Nvm的安装路径:C:\Users\code\AppData\Roaming\nvm(默认)

安装Nvm时指定node.js的安装路径:C:\Program Files\nodejs(默认)

在Nvm路径中的找到settings.txt文件,将下面代码复制进去,可以加快node版本的下载:

node_mirror: https://npm.taobao.org/mirrors/node/

npm_mirror: https://npmtaobao.org/mirrors/npm/
  • nvm -v 或 nvm version:查看nvm版本
  • nvm list:查看当前电脑上安装的node版本
  • nvm install node版本=:下载node.js
  • nvm uninstall node版本号:卸载指定版本的Node.js
  • nvm use node版本号:设置当前需要使用的node版本

在vs code中使用node命令,安装Code Runner


进程与线程

进程(process)是资源分配的最小单位,线程(thread)是cpu进行运算调度的最小单位,线程包含在进程之中。
  • 进程
    • 进程负责为程序的运行环境提供必备的环境
    • 如果把cpu比作工厂,进程相当于工厂中的车间
  • 线程
    • 线程是计算机中最小的计算单位,线程负责执行进程中的程序
    • 线程就相当于工厂中的工人
  • 单线程:
    • 单线程就相当于是一个人干活
    • 比如js,游览器就是单线程的,当然node.js也是单线程
  • 多线程:
    • 多线程相当于是多个人干活。单线程不是绝对的差,多线程也不是绝对的好(这里不做详细解释)。
    • java是多线程

node.js模块化

基本概念:
  1. 一个js文件就是一个模块。
  2. 每一个模块都是一个独立的作用域,默认里面定义的任何数据(变量,函数,对象...)都是私有的,外部无法访问。
  3. 模块可以指定数据对外开放
CommonJS规范:
node中模块分类:
  1. 内置模块
    • node自带模块,不需要通过npm安装,可以直接通过名字调用。
  2. 第三方模块
    • 需要通过npm安装的模块
  3. 自定义模块
    • 自己创建的js文件,通过文件路径引入(相对路径绝对路径)
node中的模块是由一个函数包裹
解析:
  • node中有一个全局对象global,类似于网页中的window对象
    • 在全局中创建的变量会作为global的属性保存
    • 在全局中创建的函数会作为global的方法保存
    • 我们在模块中声明一个变量a,打印global发现global中并没有属性a。所以:模块中的数据没有声明在全局,模块中并不是一个全局作用域。
  • console.log(arguments);//打印函数中的arguments,node模块中有arguments并且发现其中有5个参数。
  • console.log(arguments.callee+"");//callee属性可以找到原函数,再利用拼接字符串的方式打印。结果:function (exports, require, module, __filename, __dirname) {...},所以:node中的模块包裹在一个函数中
解析参数:
- exports

		用于向外暴露数据

- require

		用于引入外部模块

- module

		代表的是当前模块本身

		exports就是module的属性,向外暴露的数据在module.exports中

-  filename

        当前模块完整路径

 - dirname

        当前模块所在文件夹的路径
require('') ,module.exports,exports 解析:

require(''):

  • 在node中我们使用require引入模块,require()中可以传入一个js文件的路径作为参数(也称模块标识),node根据路径引入模块,如果使用相对路径,必须以 . 或 .. 开头
  • require()引入模块后,会返回一个对象,这个对象就是引入的模块

module.exports:

  • module对象中有一个exports属性。用于对外导出变量,方法或整个模块。

exports:

  • exports是module.exports的引用,所以exports用于向module.exports指向的内存块中添加属性。
  • 因为node模块中的函数返回的是module.exports指向的内存块,所以export=...是错误的,这样会改变exports的引用的内存地址。
exports与module.exports的区别:

前者公开了它指向的对象。 后者公开了它指向的对象的属性(node官方文档原话!!)

总结:模块中的代码都是包含在一个函数中,函数执行时,会同时传递5个实参

NPM(Node Package Manager,node包管理工具)

在node.js中我们将相关模块放入一个文件夹,形成一组完整的工具我们称为包。
  • 一个包中应包含的文件:
    • package.json 当前包的描述文件
    • bin 可执行二进制文件
    • lib js代码
    • doc 文档
    • test 单元测试
  • 其他文件都不怎么重要,但是package.json是必要的文件
  • 通过package.json可以详细表达一个项目
描述文件的相关示例:

这里引用的文章

{
  "name": "exchange",
  "version": "0.1.0",
  "author": "zhangsan <zhangsan@163.com>",
  "description": "第一个node.js程序",
  "keywords":["node.js","javascript"],
  "private": true,
  "bugs":{"url":"http://path/to/bug","email":"bug@example.com"},
  "contributors":[{"name":"李四","email":"lisi@example.com"}],
  "repository": {
		"type": "git",
		"url": "https://path/to/url"
	},
  "homepage": "http://necolas.github.io/normalize.css",
  "license":"MIT",
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router-dom": "^5.0.1",
    "react-scripts": "3.0.1"
  },
  "devDependencies": {
    "browserify": "~13.0.0",
    "karma-browserify": "~5.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "bin": {
  "webpack": "./bin/webpack.js"
  },
  "main": "lib/webpack.js",
  "module": "es/index.js",
  "eslintConfig": {
    "extends": "react-app"
  },
  "engines" : { 
    "node" : ">=0.10.3 <0.12" 
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "style": [
  "./node_modules/tipso/src/tipso.css"
],
  "files": [
    "lib/",
    "bin/",
    "buildin/",
    "declarations/",
    "hot/",
    "web_modules/",
    "schemas/",
    "SECURITY.md"
  ]
}
注意如下解析不能放入json文件,json文件中也不能写注释:
package.json 文件配置说明:
name:项目/模块名称,长度必须小于等于214个字符,不能以"."(点)或者"_"(下划线)开头,不能包含大写字母。
version:项目版本。
author:项目开发者,它的值是你在https://npmjs.org网站的有效账户名,遵循“账户名<邮件>”的规则,例如:zhangsan zhangsan@163.com。
description:项目描述,是一个字符串。它可以帮助人们在使用npm search时找到这个包。
keywords:项目关键字,是一个字符串数组。它可以帮助人们在使用npm search时找到这个包。
private:是否私有,设置为 true 时,npm 拒绝发布。
license:软件授权条款,让用户知道他们的使用权利和限制。
bugs:bug 提交地址。
contributors:项目贡献者 。
repository:项目仓库地址。
homepage:项目包的官网 URL。
dependencies:生产环境下,项目运行所需依赖。
devDependencies:开发环境下,项目所需依赖。
scripts:执行 npm 脚本命令简写,比如 “start”: “react-scripts start”, 执行 npm start 就是运行 “react-scripts start”。
bin:内部命令对应的可执行文件的路径。
main:项目默认执行文件,比如 require(‘webpack’);就会默认加载 lib 目录下的 webpack.js 文件,如果没有设置,则默认加载项目跟目录下的 index.js 文件。
module:是以 ES Module(也就是 ES6)模块化方式进行加载,因为早期没有 ES6 模块化方案时,都是遵循 CommonJS 规范,而 CommonJS 规范的包是以 main 的方式表示入口文件的,为了区分就新增了 module 方式,但是 ES6 模块化方案效率更高,所以会优先查看是否有 module 字段,没有才使用 main 字段。
eslintConfig:EsLint 检查文件配置,自动读取验证。
engines:项目运行的平台。
browserslist:供浏览器使用的版本列表。
style:供浏览器使用时,样式文件所在的位置;样式文件打包工具parcelify,通过它知道样式文件的打包位置。
files:被项目包含的文件名数组。
NPM 解析:
  • NPM是随同Node.js一起安装的包管理工具,主要用处有:
    • 可以从npm服务器中下载别人编写第三方包到本地使用。
    • 可以从NPM服务器下载并安装别人编写的命令行程序到本地使用。
    • 可以将自己编写的包或命令行程序上传到NPM服务器供别人使用。
    • npm完成了第三方模块的发布、安装和依赖等,使得Node与的三方模块之间形成了良好的生态系统
  • 一般下载Node.js会自带npm,但是如果使用nvm(Node版本管理工具)下载的node其中不会自带npm。
  • npm的不生效参考地址
  • npm中下载的包在js文件中也是通过require()调用,因为是npm下载的所以不用写路径
NPM 常用命令:
  • npm init 初始化package.json(描述文件)
  • npm init -y 一次初始化package.json
  • npm -v 查看npm版本
  • npm version 查看详细版本
  • npm view versions 查看指定包的所有版本
  • npm search 搜索包
  • npm install 安装包,会自动添加到描述文件的依赖中(package.json中的dependencies)
    • 一般下载的包是不会随着项目上传(一般git hub中的node项目都不会带包),因为这样会影响项目上传下载速度。
    • 因为描述文件中有依赖(dependencies),Node项目下载后,直接npm install就能把项目所依赖的包一次全部下载到本地
  • npm install --production 只装dependencies中记录的包
  • npm install @版本 安装指定版本的包
  • npm install 安装项目依赖的所有包
  • npm uninstall 删除包
  • npm uninstall -save/S 删除描述文件中依赖的记录
  • npm uninstall -D 会将其安装为开发依赖项(会被添加到 devDependencies 列表)
  • npm install -g 安装全局包(全局安装的包一般都是一些工具)
  • npm uninstall -g 删除全局包
  • npm list -g --depth 0 查看全局包
  • npm update 更新指定的包
  • npm update 更新所有的包
  • npm cache clean --force 清除npm缓存
描述文件中的脚本:
在描述文件中有个scripts:{}这表示是一个脚本,脚本就是可以运行命令行里面的命令。

假如里面有个scripts{"dev":"文件名 -v"},我们就可以npm run dev 执行这个命令。
node描述文件中包版本控制符:
  • 这是某个包的版本:13.4.6
  • major(主版本): 13, minor(次版本):4,patch(修补版本):6
    • ^ :锁定major
    • ~:锁定major与minor
    • :全部锁定
    • *:最新版本
  • 版本锁定后使用 npm update 只会更新没有锁定的
CNPM 中国npm镜像客户端(但我觉得没必要使用):
  • 由于npm服务器在国外,下载比较慢。阿里团队做了cnpm国内镜像,镜像每10分钟与官方npm服务器同步一次。使得我们不仅能加快下载速度还可以使用到新版本的包。
  • 安装cnpm:npm install cnpm -g --registry=registry.npm.taobao.org
  • 使用只要在npm的前面加个c
Node搜索包的流程:

Node在使用模块名字来引入模块时,它会首先在当前目录的node_modules中寻找是否含有该模块,如果有,直接使用;如果没有,则去上一级目录的node_modules中寻找,如果有,直接使用;如果没有则再去上一级目录node_modules寻找,直到找到为止。直到找到磁盘的根目录,如果没有,则报错。

感兴趣还可以关注我的:

cnsd:m0_46217225

掘金:寸头男生

github:Buzz_cut

微信公众号:web_mycode

知乎:寸头男生

欢迎加入QQ群交流编程知识:

qq群:808752665 编程技术交流群

我的QQ:2356924146

我会持续的编程干货。