# 系统常用命令、Node.js 与 npm、开发自己的 npm 包

TIP

接下来我们要学习 Babel 与 Webpack,因为 Webpack 是基于Node.js的,同时会涉及相关的 DOS 命令,为了让大家在后面的学习中能对 Babel 与 Webpack 有更透彻的理解,我们会先讲一些 DOS 命令,Node.js的基础知识和 NPM 工具。

Windows 常见的 DOS 命令 与 Linux、Mac 常用的命令

  • 如何进入 DOS 系统
  • 常见的 DOS 命令
  • 一些特殊的命令
  • 环境变量

Node 相关知识

  • Node 是什么
  • Node 的安装
  • Node 的基本用法
  • Node 中的模块系统

npm 的基本使用

  • npm 是什么
  • npm 的初体验(创建 package.json、下载和删除包)
  • 解决下包速度慢问题(切换 npm 的镜像服务或使用 nrm 来管理镜像源)
  • 如何创建自己的包
  • 将自己的包发布到 npm 平台

# 一、常见的 DOS 命令

TIP

DOS(Disk Operating System)磁盘操作系统,是早期个人计算机上的一类操作系统,和我们现在常用的Windows系统是一个意思。

Windows系统还没有出来之前,那时候电脑的主流系统就是DOS,只能通过黑窗口来操作电脑。

虽然现在的电脑主流使用的都是Windows系统,但在Windows系统中一直保留有DOS系统!作为程序员,有些时候我们需要通过 DOS 命令来执行一些操作,所以我们还是需要对 DOS 命令做相关了解。

# 1、如何进入 DOS 系统

TIP

  • 在 Window 系统中,按键盘上的image-20230314212512054+R 键,可以打开运行窗口,在窗口中输入 cmd,然后回车,就会弹出一个黑窗口(这就是 DOS 系统的主界面),我们就可以在黑窗口中通过 DOS 命令来执行相关操作。
  • 或把鼠标移到电脑右下角image-20230314212230945这个标图上,点击后,输入 cmd 然后按回车,就会弹出一个黑窗口...
  • 可以直接在打开的文件夹路径,直接输入 cmd,然后回车,这里进入到的黑窗口显示的路径为当前文件夹所在的路径。

GIF2023-3-1421-34-20

接下来我们学习常见的 DOS 命令

# 2、常见的 DOS 命令

命令 说明
dir 列出当前目录下的所有文件
cd cd \ 退回到根目录
cd test 表示进入到 test 子目录
cd .. 返回到上一层目录
c: 改变当前盘符命令,切换到 c 盘
md 在当前目录下新建一个文件夹
rd rd test 表示 删除当前目录下的 test 文件夹(前提是当前目录为空,不为空不能删除)
tree 显示当前目录下的目录结构(只显示文件夹名,不包含文件名)
cls 清屏幕命令,清除屏幕上的所有显示,光标置于屏幕左上角

列出当前目录下的所有文件

# 列出当前目录下的所有文件
dir

image-20230314214146830

cd 命令

# 返回上一级目录
cd ..
# 进入到demo子目录
cd demo
# 返回到根目录
cd \
#进入到 Desktop\demo 子目录
cd Desktop\demo
# 切换到d盘
d:
# 切换到c盘
c:

md 与 rd 命令

# 在当前目录下,新建hello文件夹
md hello
# 在当前目录下,新建test文件夹
md test
# 移除当前目录下的 hello 文件夹
rd hello
# 移除当前目录下的 test 文件夹
rd test

tree 命令

# 显示当前目录下的目录结构
tree

image-20230314221156065

cls 命令

# 清屏幕命令
cls

GIF2023-3-1422-15-15

# 3、特殊命令

命令 说明
向上箭头 和向下箭头 回看上一次执行的命令
Ctrl + c 快捷键 中断操作
tab 键 自动补全文件名(会根据书写的字母来匹配当前目录的文件)

# 4、环境变量

当我们想要通过 DOS 命令来打开demo文件夹中的hello.txt文件时,我们只需要进入到当前目录,然后在路径后面输入 hello.txt就可以打开这个文件了。

C:\Users\EDY\Desktop\demo> hello.txt

但如果我们想在任意的目录下,输入hello.txt时,都能打开 demo 目录下的hello.txt文件,那要如何做到呢?这就需要配置环境变量了。

环境变量:一般是指在操作系统中用来指定操作系统运行环境的一些参数。你可以简单理解为 window 系统中的变量,用来保存文件夹位置等信息。

配置环境变量

  • 第一步:复制hello.txt文件所在的绝对路径
  • 第二步:在电脑桌面我的电脑上右击---属性---高级系统---环境变量-----> 用户变量(每个变量都有特定的用处)我们主要来看 Path 变量,双击 Path 变量,在弹出的新窗口中把hello.txt文件所在的绝对路径保存在在这里。

配置好环境变量,需要把黑窗口关闭,重新打开才会生效。之后不管我们在哪个目录下输入hello.txt,都可以打开hello.txt文件。

image-20230314224141632

image-20230314224714651

总结:

当我们在命令行窗口打开一个文件或调用一个程序时,系统会首先在当前目录下寻找,如果找到就直接打开,如果没找到,则会依次到环境变量的 path 路径中寻找,如果找到就直接打开,如果没找到,最后就会报错。

其查找方式和我们 JS 中变量查找的规则类似。

什么情况下需要配环境变量

如果我们需要一个命令能在任意位置都可以生效,就可以配置对应的环境变量。

学习环境变量,是为了帮助大家理解后面学习到的全局安装和本地安装 Webpack 的区别。

# 5、Windows、Linux、Mac 它们都使用什么命令

TIP

  • DOS 命令是基于 Windows 操作系统的命令行工具,它提供了一系列命令,可以用于执行各种操作,例如文件管理、系统配置、网络设置等等。
  • 在 Mac 操作系统中,命令行工具是基于 Unix 操作系统的,因此使用的命令是 Unix 命令。Mac 上的命令行工具被称为终端(Terminal),通过它可以使用诸如 ls、cd、cp、rm 等命令。
  • 在 Linux 操作系统中,命令行工具也是基于 Unix 操作系统的,因此同样使用的是 Unix 命令。Linux 上的命令行工具可以通过终端(Terminal)或控制台(Console)来访问,可以使用诸如 ls、cd、cp、rm 等命令。

注:

Linux、Mac 目录结构、常用命令在之前的项目部署部分讲过,详细点击查阅即可 (opens new window)

# 6、DOS 命令 与 Mac 和 Linux 的命令有什么区别

主要区别如下

区别 DOS Mac 和 Linux
文件路径 使用反斜杠 \ 分隔 使用正斜杠 / 分隔
命令名称 dir ls
命令参数 以斜杠 / 开头 以破折号 - 或双破折号开头
环境变量 使用 %变量名% 表示 使用 $ 变量名表示
文件权限 无此概念 使用所有者和权限控制

注:

这只是一些基本区别的简单概述,实际上每个系统都有大量的命令和特定的功能,因此这些区别只是一些常见的差异。

# 二、Node 相关知识

TIP

深入浅出 Node 基础使用,Node 中的模块系统,fs 文件熊,path 路径,全局变量 __dirname

# 1、什么是 Node

TIP

  • Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境。
  • Node.js 为 JavaScript 提供了在服务端运行的环境,使得 JavaScript 也能开发服务端的程序,前后端统一语言,统一模型的梦想得以实现

Node.js 2009 年诞生,2015 到 2016 左右在中国就火起来了,Node 火了之后带来了连锁反应。2016 年前后,以 webpack 为代表的 Node.js 工作流工具 使前端开发的开发形式产生了翻天覆地的变化。并且,随着 Vue / React 的诞生,使前端开发进入了框架时代。

在今天,可以说前端开发 "上天入地,无所不能":PC 端 web 开发、移动 web 开发、APP 开发、小程序开发、服务端开发等等都能搞定。

注:

我们日常听到 Node.js 时,要注意区分他到底说的是 平台 还是 Node.js 语言,因此我们讲 Node.js 有两个层面的含义:

  • Node.js 是个平台或工具,即在 Node.js 平台上安装模块或包,类似于前端在浏览器上安装插件一样
  • Node.js 语言 = 后端 JavaScript = ECMAScript + IO + File + ... 等服务端的操作

在往后的课程中,我们重点讲解的是如何在 Node.js 平台上安装模块或包,类似前端在浏览器上安装插件一样。

但为了能让大家更好的理解这些内容,我们会在本章节学习一些 Node.js 语言的内容。

# 2、Node 的安装

image-20221123214804844

选择最新稳定版,根据自己的操作系统选择对应的下载地址

下载完成后,直接下一步,默认安装即可

检测是否安装及版本

npm 是 node 的包管理工具,后面我们会着重讲解。

# 检测 node 是否安装及版本,正常显示版本号说明已经安装相应的版本
node -v

# 检测 npm 是否安装及版本,正常显示版本号说明已经安装相应的版本
npm -v

image-20221123232718380

注:

以上已使用的是 Windows 的 cmd 命令窗口

当然也可以使用 VSCode 的终端、GitBash、Windows PowerShell、Mac 系统命令终端 等

# 3、Node 的基本使用

TIP

在没有 Node.js 之前,JS 是没有办法单独运行的,只能插入到 html 页面,在浏览器中运行。

现在有了 Node.js,我们可以通过 node 命令在 node 平台上直接运行 JS 文件了。

案例演示

  • demo文件夹下,新建test.js文件,内容如下
console.log("test");
  • 在当前目录下打开 VScode 命令终端,然后输入以下命令,test.js就被执行,并在终端输出了 test

image-20230314232414527

注:

node 后面为需要执行的 JS 文件,前提是路径要写对,否则会报错,找不到对应模块

# 4、Node 中模块系统

TIP

在 ES6 中我们学习过 Module 模块系统,在 Module 中使用 export 和 export default 来为模块指定输出的接口,利用 import 来导入(加载)模块。

我们知道,模块系统是为了解决模块化过程中产生的一系列的问题。那什么是模块化,模块化有什么好处,又会产生什么问,模块系统是如何解决这些问题的 ?

我们一起来复习下

什么是模块化

所谓的模块化就是把一个大的文件,拆分成许多个独立的相互依赖的小文件,这些小的文件我们就称为一个一个的模块。这些小的模块按一定的规则组合起来就能完成某个具体的功能。

模块化的好处

代码进行模块化有以下三个优点:

  • 提高代码的复用性
  • 可以提高代码的可维护性
  • 可以实现按需加载

模块化产生的三个问题:

  • JS 模块化的问题(如何让一个 JS 文件就是一个模块,有自己独立的作用域)
  • 变量命名冲突问题
  • 管理模块间的加载顺序问题

模块系统,就是为了解决模块化过程中产生的问题,如上面提到的 3 个问题。那 Node 中的模块系统是如何解决模块化产生的问题,就是我们接下来要学习的。

Node 的模块系统,与 ES6 中的 Module 模块基本思想是一样,但语法和用法不一样。

Node.js 中文网站(非官方):https://www.nodeapp.cn/

# 4.1、模块的分类

TIP

Node.js 中根据模块的来源,将模块分为 3 大类,分别是:

  • 内置模块(Node.js 官方提供的模块,如 fs、path、http)
  • 自定义模块(用户自已在创建的 .js文件)
  • 第三方模块(由第三方开发出来的模块(排除 node 官方和用户自定义),使用前需要先下载

# 4.2、模块的加载

TIP

Node.js 中使用require()方法来加载一个模块,不过对于不同类别的模块加载时,路径的书写不太一样

// 加载内置模块,直接在require中书写模块的名字就好
const fs = require("fs");

// 加载自定义模块,需要写好对应的路径,JS文件的后缀名也可以省略不写
const myCoustom = require("./myCoustom.js");
// 或  const  myCoustom=require("./myCoustom.js");

// 加载第三方模块,需要用npm下载对应模块,然后才能用requier导入,导入时只需要写对应的名字就好
const axios = require("axios");

注:

require()方法在加载模块后,会将模块中的代码执行一遍,多次导入相同的模块,只会执行一次

关于 module 相关的内容可 查阅文档 (opens new window)

# 4.3、模块作用域

TIP

在自定义模块中的变量和方法等,只能在当前模块内被访问,模块外是没有办法访问的,我们把这种访问的限制,叫做模块的作用域。

模块的作用域解决了全局变量污染的问题。

image-20230315002802973

# 4.4、module 对象-共享模块成员

TIP

Node.js 中每个 .js 自定义模块中都有一个 module 对象,它里面存储了当前模块相关的信息,通过 module.exports 这个属性(这个属性值是一个对象)将模块内的成员共享出去,供外界使用。

在利用require()方法导入自定义模块时,得到的就是 module.exports 所指向的对象。

image-20230315003936828

# 4.5、exports 对象 - 共享模块成员

TIP

  • 当我们通过module.exports.username共享成员时,可以简写成exports.usernameexports相当于这种情况下的一个快捷键。
  • exports在模块被执行前被赋予 module.exports 的值,也就是在模块被执行前,exportsmodule.exports指向同一个对象。

但最终模块对外共享的结果,还是以module.exports指向的对象为准。

image-20230315005438888

判断以下模块最终共享的结果

module.exports = {
  a: 1,
  b: 2,
};
exports.c = 3;

// 最终输出结果: { a: 1, b: 2 }

以上代码解析:

模块被执行前,module.exportsexports指向同一个对象,但是后面module.exports被重新赋值,指向了另一个对象,而 exports 还指向原来的那个对象。

而最终共享出去的结果是以module.exports指向的那个对象

module.exports = {
  a: 1,
  b: 2,
};
exports = {
  c: 3,
};
// 最终输出结果: { a: 1, b: 2 }

以上代码解析:

模块被执行前,module.exportsexports指向同一个对象,但是后面module.exports被重新赋值,指向了另一个对象,而 exports 也被重新赋值了。

而最终共享出去的结果是以module.exports指向的那个对象

exports.c = 3;
module.exports.a = 1;
module.exports.b = 2;

// 最终输出结果: { c: 3, a: 1, b: 2 }

以上代码解析:

模块被执行前,module.exportsexports指向同一个对象,后面的操作都只是在这个对象上添加新的属性。

所以最后对象上被添加了 a,b,c 三个属性。

exports = {
  c: 3,
};
module.exports = exports;
module.exports.a = 1;
module.exports.b = 2;

// 最终输出结果: { c: 3, a: 1, b: 2 }

以上代码解析:

模块被执行前,module.exportsexports指向同一个对象,后面exports被重新赋值,指向了另一个对象{c:3},但随后 module.exports 也指向了{c:3}这个对象,然后在这个对象上添加了 a,b 两个属性。

最终共享出去的结果是以module.exports指向的那个对象。

# 4.6、Node.js 中模块化规范

TIP

Node.js 中遵循了 CommonJS 模块化规范(不过与 CommonJS 还存在细微差别,这里不做讲解),其规范如下:

  • 每个模块都有一个 module 变量,这个变量代表当前模块
  • module 变量是一个对象,它有一个 exports 属性,用来对外共享成员
  • 利用 require() 方法加载模块,加载的就是 module.exports 导出的值

# 5、fs 文件模块

TIP

fs 模块,为 Node.js 中提供的操作文件系统的模块,我们这里简单学习下 fs 模块的readFile()readFileSync()方法

fs.readFile(path, options, callback); // 异步读取
fs.readFileSync(path, options); // 同步读取
/**
 * path 文件名
 * options参数,可以用来指字符编码,比如"utf8"
 * callback回调函数,文件读取响应结果后要调的,回调函数有两个参数 err和data,err表示失败的对象,data成为读取的结果
 */

基本使用

在同一目录C:\Users\EDY\Desktop\demo>下,新建index.jshello.txt 文件

hello.txt文件内容如下

大家好,我是icoding

index.js文件内容如下

const fs = require("fs");
// 同步读取hello.txt文件中内容
const txt = fs.readFileSync("./hello.txt", "utf8");
console.log(txt);

// 异步读取hello.txt文件中内容
const txt2 = fs.readFile("./hello.txt", "utf8", (err, data) => {
  if (err) {
    throw new Error("文件读取失败");
  } else {
    console.log(data);
  }
});

以上代码解析

  • 当在目录\demo>下执行node index.js命令时,在控制台能正常输出结果:“大家好,我是 icoding 大家好,我是 icoding”
  • 当在目录C:\Users\EDY\Desktop下执行node .\demo\path.js命令时,抛出错误。这里为什么呢 ?

因为 node 命令在执行时,他会在C:\Users\EDY\Desktop\hello.txt这个路径中找hello.txt文件,那肯定是找不到了。所以在 node 中使用./来表示相对路径是非常危险的。

不过用require('./index.js')方式来导入模块时,不需要特别处理,内部处理过了

那如何保证在不同的目录下执行 index.js 文件,都能正常的找到文件呢?接下来我们就学习 node 中的path模块和__dirname全局变量,来解决这个问题。

# 6、path 路径模块

TIP

path模块是Node.js内置模块,该模块提供了一些工具函数,用于处理文件与目录的路径。

我们主要学习 path 模块提供的resolve()方法

  • 该方法用于把一个路径或路径片段的序列,从右往左处理成一个绝对路径
  • 如果处理完给定的路径片段还未生成一个绝对路径,则当前工作目录会被用上
path.resolve(path1,path2,path3....); // 从右往左将三个路径拼接成一个绝对路径

基本使用

// index.js文件 所在目录 C:\Users\EDY\Desktop\demo>

// 在使用path模块前,需要先使用require()方法将其导入
const path = require("path");
const url = path.resolve("foo", "bar");
console.log(url);

以上代码解析

当前 index.js 文件所在的目录是:C:\Users\EDY\Desktop\demo>

  • 如果我目录C:\Users\EDY\Desktop\demo> 下执行node index.js,在控制台打印的结果是:C:\Users\EDY\Desktop\demo\foo\bar
  • 如果我在目录C:\Users\EDY\Desktop> 下执行 node .\demo\index.js,在控制台打印的结果:C:\Users\EDY\Desktop\foo\bar

能过两次打印的结果我们可以得出,当我们的路径片段未能生成一个绝对路径时,path.resolve()方法自动帮我们补全的绝对路径是在当前路径前加上 工作目录,而非文件所在目录。

如果我们希望不管在哪个目录下执行对应的 JS 文件,最后都能得到当前 JS 文件所在的绝对路径,那要如何处理呢 ?这就需要用到 Node.js 中的全局变量__dirname

path 模块的更多方法 可参考文档 (opens new window)

# 7、全局变量 __dirname

TIP

__dirname为 Node.js 的一个全局变量,表示当前文件的路径。

我们通常把这个变量与path.resolve()方法结合使用,用来指定当前文件所在的绝对路径。

// index.js所在的绝对路径为:C:\Users\EDY\Desktop\demo>
const path = require("path");
const url = path.resolve(__dirname, "");
console.log(url);

以上代码解析

当前 index.js 文件所在的目录是:C:\Users\EDY\Desktop\demo>

  • 如果我目录C:\Users\EDY\Desktop\demo> 下执行node index.js,在控制台打印的结果是:C:\Users\EDY\Desktop\demo
  • 如果我在目录C:\Users\EDY\Desktop> 下执行 node .\demo\index.js,在控制台打印的结果: C:\Users\EDY\Desktop\demo

不管在什么目录下执行index.js文件,最后url得到的咱径都是当前文件所在的绝对路径。

解决最开始的文件路径错误的问题

const fs = require("fs");
const path = require("path");
// 同步读取hello.txt文件中内容
const txt = fs.readFileSync(path.resolve(__dirname, "./hello.txt"), "utf8");
console.log(txt);

// 异步读取hello.txt文件中内容
const txt2 = fs.readFile(
  path.resolve(__dirname, "./hello.txt"),
  "utf8",
  (err, data) => {
    if (err) {
      throw new Error("文件读取失败");
    } else {
      console.log(data);
    }
  }
);

# 三、npm

TIP

接下来我们来学习 npm 相关知识,我们会从以下几个点来展开讲解:

  • npm 是什么
  • npm 的初体验(创建 package.json、下载和删除包)
  • 解决下包速度慢问题(切换 npm 的镜像服务或使用 nrm 来管理镜像源)
  • 如何创建自己的包
  • 如何将自己的包发布到 npm 平台
  • 如何删除自己已发布的包

# 1、什么是 npm

TIP

NPM 的全称是 Node Package Manager,是一个 Node.js 的包管理工具。

那什么是包呢 ?

在我们开发 Node 项目的时候,需要用到很多第三方的模块(和开发者自定义的模块,而是由其它人或团队开发出来,免费供所有人使用的一些模块),这些第三方的模块也称为包。

// axios就是一个第三方模块(包),我们在使用前,需要先通过npm来下载对应的包,否则就会报错。
const axios = require("axios");

那为什么需要包呢 ?

通过 JS 的学习,我们知道一门语言本身,他提供的只是一个底层的 API,而我们在使用这些底层的 API 开发项目时,效率很低,所以在实际的业务开发中,经常需要在底层 API 的基础上做一层封装。

比如我们前面讲到的 XMLHttpRequest 对象,利用他来发送 Ajax 请求时,每次都要书写大量重复的代码,所以就有人针对这个对象做了相关的封装,封装了 Axios 这个包。那后面我们发送 Ajax 请求,就可以直接使用第三方的模块 Axios 来实现,极大的提高了开发的效率。

需要的包从哪里下载呢 ?

国外有一家叫npm,Inc.的公司,这家公司旗下有一个非常著名的网站:"https://www.npmjs.com/ (opens new window)",是全球最大的包共享平台,你可以在这个平台上搜索你想要的任何包,了解这些包的功能和使用方法。

同时npm,Inc.的公司还提供了一个地址为https://registry.npmjs.org (opens new window)的服务器,来对外共享所有的包,我们可以通过这个服务器来下载自己想要的包

那如何下载需要的包呢

npm,Inc.提供了一个包管理工具,也就是我们前面提到的npm,我们可以通过这个工具,就可以从https://registry.npmjs.org (opens new window)服务器上,把需要包下载到本地来使用。

当我们安装 Node 时,npm 这个工具也被一起安装到了我们的电脑上面。检测是否安装成功,在命令终端执行以下命令

# 检测 node 是否安装及版本,正常显示版本号说明已经安装相应的版本
node -v

# 检测 npm 是否安装及版本,正常显示版本号说明已经安装相应的版本
npm -v

关于 npm 具体如何使用,是我们接下来重点讲解的内容。

# 2、npm 的作用

TIP

我们知道 npm 是 Node.js 的包管理工具,那他具体能帮我们做什么呢 ?他可以帮我们做以下事情

那在我们开发一个项目时,npm 是如何帮助我们做好下载和管理我们的包呢 ?我们从新创建一个项目开始说起。

至于如何把我们开发的包上传到 npm 服务器上,后面作为单独的模块来讲解

# 3、npm 的初体验

TIP

在我们创建一个新项目时,我们首先会在当前项目的根目录创建一个package.json文件,这个文件用来描述项目及项目所依赖的模块信息。即 帮我们管理项目中的依赖包的,让我们远离了依赖地狱。比如:

  • 当前项目的名称、版本号、描述等(我们自己开发的项目,也是一个包,也可以供别人使用,npm 也需要帮我们管理)
  • 项目中都用到了哪些包
  • 哪些包是在开发期间会用到的
  • 那些包是在开发和生产(项目上线)都会用到

当然,我们不需要手动来创建package.json文件

# 3.1 、创建 package.json 文件

TIP

我们只需要在当前项目录下,在 VsCode 终端执行npm init命令,然后按命令提示,输入对应的项目名称,之后就一直回车就行,直到命令结束,最后就会自动在当前目录创建好package.json文件。

# 执行以下命令,会在当前项目中,创建一个package.json文件
npm init

# 如果想调过中间所有步骤,全部采用默认值,可以使用
npm init -y

image-20230315021131291

以下是生成好的package.json文件,关于这个文件配置项的说明,后面会讲到

{
  "name": "qinxin",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

# 3.2、npm 下载(安装)包

在当前目录的命令终端,执行以下命令可以下载需要的包

# 下载对应的包
npm install 包名

# 下载对应的包,i 是上面 install 的简写
npm i  包名

# 如果需要下载指定版本的包,则在包后面带上对应的版本号 版本号格式 @x.x.x
npm i 包名@5.1.2

#如果需要一次性安装多个包,每个包之间用空格隔开
npm i 包名  包名  包名

在当前目录下,安装 axios 包

# 下载最新版本的axios
npm install axios
# 下载最新版本的axios,上面方法的简写
npm i axios
# 安装指定版本,版本号为 1.3.3
npm i axios@1.3.3

# 一次安装2个包
npm i  jquery axios

# 查看axios共有多少个版本
npm view axios versions

注:

当我们下载好对应包后,在当前目录下多出了node_modules文件夹和package-lock.json文件,同时package.json中多出了一个dependencies属性

node_modules 文件夹

所有安装到项目中的包,都放在了这个文件夹中。require()导入第三方包时,就是从这个目录中查找并加载包。

package-lock.json 文件

  • 它记录了node_modules目录下所有模块(包)的名称、版本号、下载地址、及这个模块又依赖了哪些依赖
  • package-lock.json 的作用:锁定安装时的包的版本号及包的依赖的版本号,以保证其他所有人人在使用 npm install 时下载的依赖包都是一致的。锁定版本号,防止自动升级新版本。

package.json 与 package-lock.json 的区别

  • npm5 以前,没有 package-lock.json 这个文件。package.json只能锁定模块的大版本号(版本号的第一位),不能锁定后面的小版本,所以你每次重新npm install时候拉取的都是该大版本下面最新的版本。
  • 一般我们为了项目的稳定性考虑我们不能随意升级依赖包,如果换包导致兼容性 bug 出现很难排查,这样很容易出现问题
  • npm5 以后,新增了 package-lock.json 这个文件,它用来锁定所有模块的版本号,包括主模块和所有依赖子模块。
  • 当你执行npm install的时候,node 从package.json文件读取模块名称,从package-lock.json文件中获取版本号,然后进行下载或者更新。

关于 dependencies 属性,接下来就会讲到

# 3.3、指定包的依赖

TIP

在开发项目时,我们会用到很多包,有些包只需要在开发环境中使用,项目上线后就不再需要了,而有些包在开发和项目上线后都需要用到。

所以我们把包分为:开发依赖包和生产(核心)依赖包

包分类 描述
开发依赖包 只在项目开发期间会用到,比如后面学到的 webbpack 打包工具,他只是用来对项目做打包构建的,项目打包构建好后,上线部署肯定就用不到webpack包了。所以webpack为开发依赖包
生产(核心)依赖包 在项目开发和上线都需要用到,比如前面说的axios包,他在项目中是用来发送请求的,不管是上线还是开发阶段都需要用到。如果上线把这个包去掉了,好项目就会出错。所以axios就是生产(核心)依赖包。

package.json中,有如下两个属性,用来记录包的类型

属性 作用
dependencies 记录生产(核心)依赖包,项目在打包上线时,会把对应的包打包进去
devDependencies 记录开发依赖包,项目打包上线时,不会把对应的包打包进去

注:

在安装包时,如果不指定包的依赖环境,默认指定为生产依赖包。如果想要在安装包时,指定包的依赖环境,可用以下命令。

  • 将包指定为开发依赖
npm i 包名 --save-dev   # 将安装的包指定为开发依赖包
npm i 包名 -D  # -D相当于是--save-dev的缩写,将安装的包指定为开发依赖包

# 以下写法也可以
npm i --save-dev 包名
npm i -D 包名

#安装webpack webpack-cli 为开发依赖
npm i webpack webpack-cli -D

安装成功后,就会在package.json文件的devDependencies属性中添加如下两个属性

 "devDependencies": {
    "webpack": "^5.76.1",
    "webpack-cli": "^5.0.1"
  },
  • 将包指定为生产依赖
npm i 包  # 不指定依赖环境,默认安装到生产环境
npm i 包 --save  #将安装的包指定为生产依赖
#以下写法也可以
npm i --save# 安装axios包到生产环境
npm i axios;
#或
npm i axios --save

安装成功后,就会在package.json文件的dependencies属性中添加如下属性

"dependencies": {
    "axios": "^1.3.4"
}

温馨提示

我们在安装对应的包时,可以参考包的说明,包的说明中会给出包安装的命令,通过命令可以知道当前包是需要安装在生产还是开发环境。

# 3.4、npm 删除(卸载)包

在当前目录命令终端,执行以下命令可以删除下载好的包

npm uninstall 包  # 删除本地包,不考虑版本,不考虑依赖环境

# 删除axios包
npm uninstall axios

注:

包删除成功后,对应package.jsonpackage-lock.json文件中包相关的信息全部都会被移除。

# 3.5、package.json 文件配置说明

TIP

以下是关于package.json文件的相关配置项说明

{
  // 项目名称,不能以"."和"_"开头,不能包含大写字母,因为当软件包在npm上发布时,会基于此属性获取自己的URL,同时名称作为参数被传入require(""),用来导入模块,所以尽量简短、语义化
  "name": "qinxin",
  // 该项目的版本号,它是一个字符串。每次项目改动后,即将发布时,都要同步的去更改项目的版本号。版本号的格式为: 主版本号.次版本号.修订号   => 5.1.0
  // 通常情况下,修改主版号是做了大的功能的改动
  // 修改次版本号是新增了新功能,
  // 修改修订号就是修复了一些bug
  // 查看包的版本信息  npm view  包名  version =>查看最新版本
  // npm view 包名 versions  =>查看所有版本
  "version": "1.0.0",
  // 项目的描述,可以让其它开发者在npm的搜索中发现我们的项目包,搜索对应包时对应的描述
  "description": "",
  // 用来指定加载的入口文件,在浏览器和Node环境中都可以使用。如果我们将项目发布为npm包,那么当使用require导入npm包时,返回的就是main字段列出的文件的module.exports属性。如果不指定该字段,默认是项目根目录下的index.js,如果没找到,就会报错。
  "main": "index.js",
  // 脚本配置  scripts是package.json中内置的脚本入口,是key-value键值对配置。
  // 可以通过npm run 来执行的命令。  npm run dev
  // 还可以通过与 pre 和 post 完成前置和后续操作
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  // 项目作者 它的值是你在https://npmjs.org网站的有效账户名
  "author": "",
  // 指定软件的开源协议,开源协议表述了其他人获得代码后拥有的权利,可以对代码进行何种操作,何种操作又是被禁止的
  "license": "ISC",
  // dependencies 表示项目的生产和开发环境中都需要依赖的包
  "devDependencies": {
    "webpack": "^5.76.1",
    "webpack-cli": "^5.0.1"
  },
  // devDependencies 开发阶段需要的依赖包
  "dependencies": {
    "axios": "^1.3.4"
  }
}

# 3.6、package.json 文件作用

TIP

通过前面的学习,我们知道package.json文件用来描述项目及项目所依赖的模块信息。即 帮我们管理项目中的依赖包的,让我们远离了依赖地狱。

如果我们想把自己开发的项目分享给别人,不需要把 node_modules 这个文件分享过去,这个文件夹中的文件体积庞大,下载和上传都是极为不方便,而且会特别慢。

我们只需要把其它的文件发送给对方,对方拿到文件后,只需要在当前项目的根目录下,执行以下命令

npm i  # 自动根据package.json中的信息来下载项目所需要的所有依赖包。

就会自动根据package.jsonpackage-lock.json文件中的信息来下载项目所需要的所有依赖包。

GIF2023-3-1519-05-45

# 4、解决 npm 下包速度慢问题

TIP

当我们使用 npm 下载包的时候,默认是从国外的https://registry.npmjs.org (opens new window)服务器进行下载,所以下载的速度会很慢。

那国内是如何解决下载速度慢的问题,这就要提到淘宝的 npm 镜像服务器nrm

# 4.1、淘宝的 NPM 镜像服务器

TIP

镜像(Mirroring):是一种文件存储形式,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。

淘宝在国内搭建了一个 https://registry.npmmirror.com/服务器(也就是 NPM 镜像服务器),专门用来把国外https://registry.npmjs.org 服务器上的包同步到国内的服务器。

这样国内需要对应的包,就可以直接在国内的服务器上来下载了,极大的提高了下包的速度。

image-20230316015659896

提示:

淘宝官方通知:https://npm.taobao.org 和 https://registry.npm.taobao.org 将在 2022 年 6 月 30 日正式下线和停止 DNS 解析。域名切换规则:

  • https://npm.taobao.org => https://npmmirror.com
  • https://registry.npm.taobao.org => https://registry.npmmirror.com

查看当前正在使用的 npm 镜像源

npm config get registry

切换 npm 镜像源

npm config  set registry  https://registry.npmmirror.com
  • 镜像源地址只需设置一次即可
  • npm 的镜像源切换为https://registry.npmmirror.com后,我们使用 npm 命令来下载包,就相当于是直接国内的这个服务器上来下载包,速度会很快速。

# 4.2、nrm 源管理器

TIP

npm 有很多镜像源服务器,而nrm(npm registry manager)是 npm 的镜像源管理工具,允许你快速地在 npm 源间切换。

  • 全局安装 nrm
# 通过npm,将nrm安装为全局可用的工具,即不管在任何目录下,都可以使用nrm命令
npm i nrm -g
  • 安装好 nrm 后,查看所有可用的镜像源
nrm ls  # 查看所有可用的镜像源

image-20230315194049275

  • 将当前源切换为对应的 taobao 源
nrm use taobao

我们可以通过以下命令来查看我们的源是否切换成功

npm config get registry

# 5、npm 常用命令

# 四、开发自己 npm 包

TIP

接下来我们尝试开发一个简单的包,然后上传到 npm 平台上去。让大家了解 npm 在整个过程中的应用。

一个完整的包,至少有以下三个文件

文件名 作用
package.json 用来描述项目和管理项目所依赖的模块信息
index.js 用来指定加载的入口文件,如果我们将项目发布为 npm 包,那么当使用 require 导入 npm 包时,返回的就是package.json文件中 main 字段列出的文件的 module.exports 属性。
如果不指定该字段,默认是项目根目录下的index.js,如果没找到,就会报错。
README.md 包的说明文档,描述包的作用和包的使用教程

接下来我们就按以下步骤来开发自己的

  • 创建项目文件夹,用来存放项目用到的所有文件
  • 初始化项目需要的 package.json 文件
  • 创建index.js文件,包的入口文件
  • 撰写 README.md 说明文档

# 1、创建项目文件夹

TIP

在创建项目文件夹前,先要想好自己包(项目)的名字,同时在 npm 官网https://www.npmjs.com/ (opens new window)上查询有没有对应的包名。

如果没有这个包名就能用,如果有,那就要更换,因为不能出现同名的包。

在本地新建一个icoding-max文件夹(项目名),所以项目需要用到的文件都保存在当前目录中

# 2、初始化 package.json 文件

TIP

当项目icoding-max文件夹下,利用 npm init y 命令初始化package.json文件

得到如下 package.json 文件

{
  "name": "icoding-max",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

完善 package.json 文件中的描述、关键字、作者

{
  "name": "icoding-max",
  "version": "1.0.0",
  "description": "Returns the maximum and minimum of two numbers",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": ["min", "max"],
  "author": "qxin",
  "license": "ISC"
}

# 3、创建 index.js 文件

TIP

在当前目录下创建index.js文件,作为项目的加载入口文件。在文件中编写 max 和 min 两个函数,这两个函数用来实现两个数中的最大值和最小值,并将其作为模块接口导出。

具体代码如下

// 求两个值中的最大值
function max(a, b) {
  return a > b ? a : b;
}
// 求两个值中的最小值
function min(a, b) {
  return a > b ? b : a;
}

// 将两个方法作为模块对外输出的接口
module.exports = {
  max,
  min,
};

# 4、撰写 README.md 说明文档

TIP

README.md 包的使用说明文档,以 markdown 的格式来书写,方便阅读。READEM.md 文件中具体写什么内容,没有强制要求,开发者尽可能清晰的把包的功能,安装、用法,注意事项等描述清楚即可。

以下是我为本包做的一个简单的说明文档

image-20230316004439005

项目开发好了,接下来我们需要将自己的包上到 npm 平台

# 5、上传包到 npm 平台

TIP

要将自己开发的包上传到 npm 平台,经历以下几步:

  • 在 npm 平台,注册 npm 账号
  • 登录 npm 账号
  • 发布包到 npm 上

# 5.1 注册 npm 账号

TIP

image-20230316005922948

在你填写的邮箱中找到对应的一次性密码,输入验证成功后,npm 账号就注册成功

image-20230316010111404

# 5.2、登录 npm 账号

TIP

npm 账号注册完成后,在命令终端切换到当前项目的根目录,并执行npm login命令,开始登录,根据提示,分别输入 用户名、密码,一次性密码等操作,最后就会登录成功。

温馨提示

在运行 npm login 命令前,必须要先把 npm 的镜像切换为 npm 官方的服务器https://registry.npmjs.org,否则登录不进去。

# icoding-max为项目文件夹
PS C:\Users\EDY\Desktop\demo\icoding-max> npm login

如果不清楚是否成功,可以执行npm profile get命令,查看账户简介,如下图

image-20230316013716890

# 5.3、发布包到 npm 平台

TIP

在当前项目的根目录下,执行npm publish命令,即可将包发布到 npm 上。

# icoding-max为项目文件夹
C:\Users\EDY\Desktop\demo\icoding-max> npm publish
# 如果希望发布的包对外不公开,则可以使用下面命令
npm publish --access public

发布成功后

在 npm 官网https://www.npmjs.com/右上角,点击我的头像,选择Packages菜单进入,就可以看到自己发布的包。

image-20230316013353575

# 5.4、删除发布的包

TIP

在终端登录 npm 账号后,可以运行以下命令,将对应的包从 npm 平台上删除

npm unpublish 包名 --force # 从npm平台上删除自己发布的对应包

# 删除刚才发布的包,-f 是 --force 的简写
npm unpublish icoding-max -f

温馨提示:

  • npm unpublish 命令只能删除 72 小时以内发布的包
  • npm unpublish 删除的包,在 24 小时内不允许重复发布

所以在发布包时,要再三检查,有没有错误。

上次更新时间: 6/8/2023, 9:23:17 PM

大厂最新技术学习分享群

大厂最新技术学习分享群

微信扫一扫进群,获取资料

X