IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 模块化与包管理工具 -> 正文阅读

[JavaScript知识库]模块化与包管理工具

作者:more-toolbox-new

## 模块化基本介绍

### 模块

模块是对功能相似的函数或属性的封装。例如:

??? ?fs 模块中封装了一系列文件操作的函数。例如:fs.readFile()、fs.writeFile()

??? ?path 模块中封装了一系列路径处理的函数。例如:path.join(),path.basename()

模块的好处:提高了函数的复用性!

### 什么是模块化

一个js文件可以引入其他的js文件,能使用引入的js文件的中的变量、数据,这种特性就称为模块化。

nodejs是支持模块化的。

### es6之前js没有模块化的功能

提问:在浏览器中,我们写代码时,

```bash
- index.html ? ? ?# 主页
- index.js ? ? ? ?# 主页需要用到的js代码
--- getData() ? ? # 在index.js中有一个方法
- tool.js ? ? ? ? # 为整个项目提供公共方法
--- doSomething() # 在tool.js有一个方法
```

对于如上的代码结构,

问:如何能让index.js中的getData去使用tool.js中的doSomething()函数??

答:通过index.html过渡。在index.html中,先引入tool.js,再引入index.js

问:为什么不能直接让index.js来直接使用tool.js的函数,而要通过index.html来统一管理呢?

答:原因很简单:es5中不**支持模块化**

### 不支持模块化有什么问题?

![image-20210910212221146](asset/image-20210910212221146.png)

变量污染,代码无法维护

## 模块化的发展

### 历程

- es6之前

? es5不支持模块化,为了让支持模块化,我们一般会借用第三方库来实现:

? - sea.js. https://www.zhangxinxu.com/sp/seajs/
? - require.js. https://requirejs.org/

- es6之后

? - es6原生语法也支持模块化(并不表示浏览器也**直接**支持模块化 --- 需要单独设置一下)
? - Nodejs内部也支持模块化(与es6的模块化有些不同之处),具体的语法在后面来介绍。

### 体验

演示性的学习,让大家了解几种模块化的写法

- nodejs的模块化
- es6的模块化
- sea.js
- require.js

参考: https://www.zhihu.com/question/20342350

## 模块化规范

### 目标

了解模块化规范

### 概念

概念:拆分模块和组合模块时,**所遵守的规则**,就叫做模块化规范。

例如:在 Node.js 中,导入其它模块时,统一使用 require() 函数。

![image-20210910214120759](asset/image-20210910214120759.png)

### 常见的模块化规范

- CommonJS 规范:nodejs中遵守的就是commonjs规范。

- ES6 模块化规范:(前后端通用的模块化规范;Node.js、Vue、React 中都能使用!)

- CMD 和 AMD 模块化规范(较少使用): CMD--sea.js, ?AMD-require.js
- UMD 叫做通用模块定义规范(Universal Module Definition),它可以通过运行时或者编译时让同一个代码模块在使用 CommonJs、CMD 甚至是 AMD 的项目中运行。它没有自己专有的规范,是集结了 CommonJs、CMD、AMD 的规范于一身。

### 学习模块化规范的好处

知道怎么导入并使用别人的模块

知道怎么封装模块给别人使用

## 用commonJS规范来自定义模块

复习:nodejs的三种模块

- 核心(内置)
- 第三方的
- 自定义

### 目标

理解自定义模块的应用场景,掌握在nodejs中定义,导出模块

### 使用场景

类比于js自定义函数,自定义模块的使用场景是:

- 代码需要在项目重用
- 代码需要提供给他人使用
- 代码虽然不需要重用,但封装成模块有利于优化代码结构,方便后期维护与扩展

### 遵守commonJS规范

在Node.js 中定义模块,要遵守 CommonJS 的模块化规范。CommonJS 规范中主要规定了以下 3 项内容:

①导入其它模块时,统一使用 require() 函数。

②每个 .js 文件,都是一个独立的模块,模块内的成员都是私有的。

③在每个 JS 模块中,使用 module.exports 向外共享成员。

### 示例

![image-20210910214711244](asset/image-20210910214711244.png)

自定义模块的特点:

①使用 require('自定义模块的路径') 即可导入自定义模块;

②自定义模块内的变量、函数等都是私有的,默认无法被外界访问到;

### 小结

步骤:

1. 定义模块
? ?1. 创建一个js文件
? ?2. 完成具体的功能
? ?3. **导出** (`module.exports= {} `)
2. 使用模块。在需要使用的地方去**导入**模块文件。

## 自定义模块的要点

1. 不要用特殊的文件名

- ?一般会用模块名给它命名。类比于核心模块,例如,你的模块叫myModule,则这个js文件最好叫myModule.js
- ?不要与核心模块的名字重复了。就像我们定义变量**不要与核心关键字重名**,你自己定义的模块也不要叫fs.js,因为nodejs有一个核心模块就叫fs.js。

2. 导入模块的路径是相对路径
3. 导入之后,记得console.log

4. 记得**导出**

- module.exports 是固定写法,一般放在文件的最末尾,也只用一次。
- module.exports表示当前模块要暴露给其它模块的功能。
? - 它可以导出对象,数组,函数等等类型。为了方便组织代码,导出对象的情况比较多。
? - 不必要导出所有函数,对象,数组等。那些没有导出的部分就相当于这个模块的内部变量了。

<img src="asset/1575035153257.png" alt="1575035153257" style="zoom:50%;" />

## 随堂练习

1. 完成自定义模块部分的代码
2. 请将下面的函数按commonJS的规范进行封装,并导出使用。

```javascript
const relativeTime = (oldTime) => {
? const t = new Date(oldTime)
? // Date.now():现在的时间戳(毫秒)
? // t.getTime():旧时间的时间戳(毫秒)

? const diff = Date.now() - t.getTime() // 相隔多少毫秒
? // Math.floor 向下取整: 1.7年 ---> 1年前
? const year = Math.floor(diff / (1000 * 3600 * 24 * 365))
? if (year) {
? ? return `${year}年前`
? }
? const month = Math.floor(diff / (1000 * 3600 * 24 * 30))
? if (month) {
? ? return `${month}月前`
? }
? const day = Math.floor(diff / (1000 * 3600 * 24))
? if (day) {
? ? return `${day}天前`
? }
? const hour = Math.floor(diff / (1000 * 3600))
? if (hour) {
? ? return `${hour}小时前`
? }
? const minute = Math.floor(diff / (1000 * 60))
? if (minute) {
? ? return `${minute}分钟前`
? } else {
? ? return '刚刚'
? }
}

// const str = relativeTime('2021-09-09') //?
```

## 拓展:导出模块的两种方式(难点,不是重点)

在阅读其它人的代码时,可能会遇到这两种不同的写法。所以我们还是有必要了解一下的。

### 导出模块有两种方式

[参考](https://nodejs.org/api/modules.html#modules_exports_shortcut)

- exports
- **module.exports**

```javascript
// 定义方法,常量
const myPI = 3.14
const add = (a,b) => a + b;

// 导出,两种方法任意都可以
// 方法一:
exports.myPI = myPI
exports.add = add

// 方法二:
module.exports.myPI = myPI
module.exports.add = add

// 方法二(变形)
module.exports ?= {
? ? myPI,
? ? add
}
```

### 两个对象的关系

初始exports和module.exports是指向同一块内存区域,其内容都是一个空对象

exports是module.exports的别名,即:

```javascript
exports === module.exports // 输出是 true
```

所以下面两种写法的效果是一样的:

?```
?//1 mymodule.js
?exports.f = function(){ }
?exports.pi = 3.1415926
?```

?```
?//2 mymodule.js
?module.exports.f = function(){ }
?module.exports.pi = 3.1415926
?```

- 在定义模块时:

? 如果直接给exports对象赋值(例如:exports={a:1,b:2}),此时,exports就不会再指向module.exports,而转而指向这个新对象,此时,exports与module.exports不是同一个对象。

### 在引入某模块时:以该模块代码中`module.exports`指向的内容为准。

### 图示

![image-20210324142039663](asset/image-20210324142039663.png)

![image-20210324142213492](asset/image-20210324142213492.png)

![image-20210324142348206](asset/image-20210324142348206.png)

![image-20210324142532461](asset/image-20210324142532461.png)

### 结论

在导出模块过程中,建议只用一种方式(建议直接使用module.exports)

### 练习

[第1 题]()

```
// yourModule.js?? ?
// 一句代码也没有
```

使用模块。请问,如下代码中会输出什么结果?

```
//index.js
const yourModule = require('./yourModule');
console.log(yourModule)
```

[第2 题]()

```
// yourModule.js?? ?
exports = 1
```

使用模块。请问,如下代码中会输出什么结果?

```
//index.js
const yourModule = require('./yourModule');
console.log(yourModule)
```

[第3 题]()

```
// yourModule.js?? ?
exports = {a : 1 };
```

使用模块。请问,如下代码中会输出什么结果?

```
//index.js
const yourModule = require('./yourModule');
console.log(yourModule)
```

[第4 题]()

```
// yourModule.js?? ?
exports = {a:1}
module.exports = 2
```

使用模块。请问,如下代码中会输出什么结果?

```
//index.js
const yourModule = require('./yourModule');
console.log(yourModule)
```

[第5 题]()

```
// yourModule.js?? ?
exports = {a:1}
module.exports = {b:2}
```

使用模块。请问,如下代码中会输出什么结果?

```
//index.js
const yourModule = require('./yourModule');
console.log(yourModule)
```

[第6 题]()

```
// yourModule.js?? ?
exports.a = 1;
module.exports.b = 2
```

使用模块。请问,如下代码中会输出什么结果?

```
//index.js
const yourModule = require('./yourModule');
console.log(yourModule)
```

## require的加载机制

require背后的事情

在我们使用一个模块时,我们会使用require命令来加载这个模块。以加载一个自定义模块为例,require(文件名)的效果是:

1. 执行这个文件中的代码
2. 把这个文件中的**module.exports**对象中的内容返回出来。

以如下代码为例:

```javascript
// moudule1.js
var a = 1;
var b = 2;
console.log(a+b);
var c = a+b;
module.exports = {
?? ?data: c
}
```

在index.js中使用模块

```javascript
// index.js
const obj = require('./moudule1.js');
console.log(obj);

//这里的obj对象就是moudule1.js中的module.exports对象
```

### require加载规则

如何确定require(文件名) 中,模块的位置!

- `require` 优先加载**缓存**中的模块。同一个模块第一次require之后,就会缓存一份,下一次require时就直接从缓存中去取。

- 如果是加载**核心模块**,直接从内存中加载,并缓存

? - 加载核心模块的格式是 `const xxx = require("模块名")` 。不能写相对路径!

- 如果是**相对路径**,则根据路径加载**自定义模块**,并缓存

? - 以`require('./main')`为例( 省略扩展名的情况)
? - 先加载 `main.js`,如果没有再加载 `main.json`,如果没有再加载 `main.node`(c/c++编写的模块),找不到就报错。

- 如果不是自定义模块,也不是核心模块,则加载**第三方模块**,以`require('XXX')`为例:

? - node 会去本级 node_modules 目录下的xxx文件夹中找,找到就缓存。找的规则如下:

? ? ①查找第三方模块文件夹xxx下的 package.json 文件
??
? ? ②查找 main 属性,并加载 main 属性所指向的模块
??
? ? ③如果 main 属性不存在,则尝试加载名为 index.js 的模块
??
? ? ④如果 index.js 加载失败,报错
??
? - 如果找不到,node 则取上一级目录中的node_modules下找 , `node_modules/xxx` 目录,规则同上
??
? - 如果一直找到代码文件的文件系统的根目录还找不到,则报错:模块没有找到。
??
? 可以通过`console.log(module.paths)`来观察查找路径

## npm和包和模块

### npm

- `npm` 全称 `Node Package Manager`(node 包管理器),它的诞生是为了解决 Node 中第三方包共享的问题。
- `npm` 不需要单独安装。在安装Node的时候,会连带一起安装`npm`。
- `npm -v`检查安装的情况。
- [官网](https://www.npmjs.com/)

当我们谈到npm时,我们在说两个东西:?

- 命令行工具。这个工具在安装node时,已经自动安装过了。
- npm网站。这是一个第三方模块的"**不花钱的超市**",我们可以自由地下载,上传模块。

### npm集中管理包

问:在浏览器中是如何使用第三方的工具库,例如:jQuery, bootStrap,echarts.js....

答:从各自的官网上下载。

问:有没有一个想法:在一个地方下载所有的库(模块.....)

答:通过npm去下载。

**npm网站**上去下载我们的需要的代码时,它们是以"**包**"这种结构放在npm网站上的。先来了解下包和模块的关系。

<img src="asset/模块与包的关系.png" alt="模块与包的关系" style="zoom:50%;" />

- nodejs中一个模块就是一个单独的js文件
- 包是多个模块的集合。一个模块的功能比较单一,所以一个包一般会包含多个模块。
- npm 管理的单位是包。类似于网站和网页的区别:一个网站一般会包含多个网页。

### 小结

npm指两个内容:npm工具,npm网站。

npm网站上放置很多第三模块,它们是以包的格式存在的。

## npm下载使用包

### 目标

掌握下载包的格式和步骤

### 分成三步

- 初始化项目。**npm init** 如果之前已经初始化,则可以省略。
- 安装包。 **npm install** 包名。
- 引入模块,使用。

> 保持联网的状态哈

### 第一步:初始化项目

这里提到的项目并不是某个具体的功能,只是要创建一个空文件夹即可(注意,不要起中文名字哈)。

进入到项目所在的**根目录**下,**启动小黑窗**(按下shift键,点击右键,在弹出的菜单中选择 “在此处打开命令行”)

输入如下命令:

```javascript
npm init --yes
// --与yes之间没有空格, -- 与init之间有空格
// 或者是 npm init -y
```

init命令用来在根目录下生成一个package.json文件,这个文件中记录了我们当前项目的基本信息,它是一切工作的开始。

### 第二步:安装包

> npm 这个超市上有好的代码,我们想下载来用 ------ ?安装包

生成了package.json文件之后,我们就可以来安装第三方包了。在npm官网中,有上百万个包,供我们使用(你需要在npm网上注册帐号,登陆上去,才可以看到如下的数据,如果只是下载安装包,则并不需要注册)。

<img src="asset/1562724829170-1575039940084.png" alt="1562724829170" style="zoom:50%;" />

根据我们遇到的实际问题,我们来引入相应的包来解决它们。例如,我们在开发一个项目,其中涉及一些对日期时间的处理可以安装dayjs包。

#### 安装day.js包

day.js是一个专门用来处理日期时间的一个包。网站:https://dayjs.fenxianglu.cn/

```
npm install dayjs
```

### 第三步:使用包

当我们已经下载好一个包之后,就可以像使用**核心模块**一样去使用它。

格式是:`const 常量名 = require('包名')`?

这个格式与引入核心模块的格式是一样的。

```javascript
// 从npm下载 别人写的好代码,在本地引入,并使用
const dayjs = require('dayjs')
console.log(dayjs);
console.log( dayjs().format('YYYY-MM-DD') );
```

### 小结

npm i 包之前,要有package.json文件。

## npm init 命令

在某个目录下开启小黑窗,输入如下命令:

```
# init 初始化
npm init?
```

它会启动一个交互式的程序,让你填入一些关于本项目的信息,最后生成一个**package.json文件**。

如果你希望直接采用默认信息,可以使用:

```javascript
npm init --yes
// 或者是 npm init -y
```

说明:

- 这个命令只需要运行一次,它的目的仅仅是生成一个package.json文件。
- 如果项目根目录下已经有了package.json文件,就不需要再去运行这个命令了。
- 这个package.json文件后期是可以手动修改的。

## package.json文件

它一般是由npm init命令创建出来的,它的整体内容是一个json字符串,用来对当前**项目进行整体描述**。其中最外层可以看作是一个js的对象(每一个属性名都加了"",这就是一个典型的json标记)。这个文件中有非常多的内容,我们目前学习如下几个:

- name: 表示这个项目的名字。如是它是一个第三方包的话,它就决定了我们在require()时应该要写什么内容。

- version:版本号

- keywords:关键字

- author: 作者

- descrption: 描述

其它可参考

1.http://javascript.ruanyifeng.com/nodejs/packagejson.html

2.http://caibaojian.com/npm/files/package.json.html

## node_modules文件夹

### 作用

在使用npm install 命令时,会从npm网站下载对应的包到这个文件夹中,这个文件夹中保存着我们从npm中下载来的第三方包。

<img src="asset/node_modules.jpg" style="zoom:50%;" />

### 执行逻辑

当键入`npm install XXX`之后(这里假设这个XXX包是存在的,也没有出现任何的网络错误):

1. 如果有package.json

? ?(1) 修改package.json文件。根据开发依赖和生产依赖的不同,决定把这句记录在加在devDependencies或者是dependencies列表中。

? ?(2) 修改node_modules文件夹

? ?1. 如果有node_modules文件夹,则直接在下面新建名为XXX的文件夹,并从npm中下来这个包。如果这个包还有其它的依赖,则也会下载下来。
? ?2. 如果没有node_modules,则先创建这个文件夹,再去下载相应的包

2. 如果没有package.json。会给一个警告信息。

说明:

- 建议先用init命令创建package.json之后,再去install
- 在分享代码时,我们一般不需要把node_modules也给别人(就像你不需要把jquery.js给别人,因为他们可以自己去下载)。对方拿到我们的代码之后,先运行`npm install`(后面不接任何的包名),自己去安装这些个依赖包。

## npm镜像-让下包更快

### 目标

理解镜像的作用,会通过命令来配置镜像

### 什么是镜像

镜像:副本,拷贝。

默认情况下,从npm官方下载,网速比较慢;我们可以去它的镜像网站上来下载。

### 如何设置镜像

```bash
# 设置镜像为taobao。
npm config set registry https://registry.npm.taobao.org
# 设置镜像为npm官方
npm config set registry https://registry.npmjs.org
# 查看配置
npm config get registry?
```

### 图示

![image-20210911002104752](asset/image-20210911002104752.png)

## 包的分类

![image-20210910232809786](asset/image-20210910232809786.png)

## 安装全局包和项目包

我们通过`npm install` 命令来安装包,简单说就是把包从npm的官网(或者是指定的镜像源)下载到我们自己的电脑中。那具体这个包下载到哪里了,还是有一点讲究的。

分成两类:

- 全局安装: 包被安装到了系统目录(一般在系统盘的node_modules中)。

? - 命令:`npm install -g 包名` 或者 ?`npm install 包名 -g`

? - 辅助提示:

? ? - ```
? ? ? npm root -g ? ? ? ? ? // 查看全局包的安装目录
? ? ? npm list -g --depth 0 // 查看全局安装过的包
? ? ? ```

- 项目安装(或者叫本地安装),包安装在当前项目的根目录下(与package.json同级)的node_modules中。

? - ??? ?命令:`npm install 包名`

### 全局包与项目包的区别

- 全局安装的包一般可提供直接执行的命令。我们通过对一些工具类的包采用这种方式安装,如:

? gulp, nodemon, live-server, nrm等。

- 本地安装的包是与具体的项目有关的, 我们需要在开发过程中使用这些具体的功能。

一个经验法则:

- 要用到该包的**命令执行任务**的就需要**全局安装**。
- 要通过**require**引入使用的就需要本地安装-项目包。

## 全局安装nrm包

### 目标

理解nrm的功能,会使用它来调整npm镜像

### 作用

[nrm](https://www.npmjs.com/package/nrm) 这个工具是帮助我们切换npm镜像源的。

之前是:

```bash
# 设置镜像为taobao。
npm config set registry https://registry.npm.taobao.org
# 设置镜像为npm官方
npm config set registry https://registry.npmjs.org
```

使用nrm之后,就可以简化上面的命令。

### 步骤

共三步

```javascript
// 第一步: 全局安装?
npm install nrm -g

// 第二步:列出所有的源信息
// (*)标注的就是当前使用的源
nrm ls

// 第三步:根据需要切换源?
// 例如:指定使用taobao镜像源
nrm use taotao

// 接下来,正常安装你需要的包
```

> 如果nrm ls不能用,请看这里:
>
> https://blog.csdn.net/LQCV587/article/details/113884507
>
> const NRMRC = path.join(process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'], '.nrmrc');
>
> //const NRMRC = path.join(process.env.HOME, '.nrmrc');(注掉)
> const NRMRC = path.join(process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'], '.nrmrc');

## 开发依赖包和生产依赖包(了解)

在本地安装包时,表示我们这个项目要用到这个包,换句话说,我们这个项目要想成功运行,要依赖于这些个包。

但在,具体在项目进行的哪一阶段依赖于这些包呢?也有具体的差异。

### 理解

举个生活中建房子的场景:

在建房子时,我们依赖:

- 辅助工具:尺子,水平仪,脚手架
- 原材料:钢筋,水泥

在住房子时,我们依赖:

- 原材料:钢筋,水泥

在房子进入到了使用阶段时,我们就不再需要尺子,水平仪,脚手架等这些个辅助工具了。我们买一所房子时,也不应该支付巨型脚手架的费用。 ?在开发前端项目的过程中也存在类似的问题:我们的开发过程和使用过程是分开的,开发项目时需要用到的包可能在使用项目时就不需要用到了。

假设有这么两个包:

- gulp-htmlmin。这个工具是用来把html代码进行压缩的(去掉空格,换行等),我们需要在开发时使用它,而项目一旦上线,我们就不再需要它了。,因此将它归类为"**开发依赖**"。
- jquery。在开发时参与源码编写,在发布上线的生产环境中也是需要它的。不仅在开发环境编写代码时要依赖它、线上环境也要依赖它,因此将它归类为"**生产依赖**"。

![1562728491126](asset/1562728491126.png)

> 这个差异就表现在,我们在打包项目时,就不需要打包“开发依赖”的包,这样减少成本。
>
> ---webpack

### 操作

这两种依赖关系,在具体操作的过程中,有如下区别

1. 保存到开发依赖(devDependencies)

```javascript
npm install 包名 --save-dev
// 或者 npm install 包名 -D
```

通过这种方式安装的包出会现在package.json文件中的`devDependencies`字段中。

2. 保存到生产依赖(dependencies):?

```javascript
npm install 包名
// 或者 npm install 包名
// 或者 npm install 包名 -S

```

### 技巧

- 加了-D : ?开发依赖,这就表示这个工具包只在开发项目时候要用,项目开发完成就不需要
- 不加-D: 生产依赖,这就表示这个工具包在项目做完了之后也要用。

什么包加上-D,什么包不要加?------- 看文档

## 案例:npm包从创建到发布

<img src="asset/image-20200213171733854.png" alt="image-20200213171733854" ?/>

> 背景
>
> 在工作中我们积累了一些自己的功能代码。这些功能代码可以在其它项目中重复使用,此时我们就可以选择把代码打包放在[npm]上,在需要要使用的项目中,通过npm install去下载下来。

### npm项目初始化

在本地磁盘上创建一个空项目,取文件夹名为`myNpm`。注意请先去npm网官去确定一下,这个项目名是否已经被占用了。(如果这个名字已经被占用了,则你是无法向npm上上传的)。

检查方式

```bash
npm view 包名
# 这个命令用来查看 某个包的信息
# 如果返回404,说明这个项目名在npm官网上找不到,此时你就可以使用。
# 否则,说明不可用。
```

> 很确定地告诉你,myNpm这个包已经被别人占用了,你需要去自己用另一个名字哈。


```
npm init --yes
```

命令来创建一个package.json文件,对你项目myNpm信息进行设置。

### 完成功能开发

![image-20210324175557637](asset/image-20210324175557637.png)

正常开发,完成你的代码。在默认情况下,index.js是这个项目的入口文件。

下面是一个最简单的示例:?

```
//tools.js
const relativeTime = (oldTime) => {
? const t = new Date(oldTime)
? // Date.now():现在的时间戳(毫秒)
? // t.getTime():旧时间的时间戳(毫秒)

? const diff = Date.now() - t.getTime() // 相隔多少毫秒
? // Math.floor 向下取整: 1.7年 ---> 1年前
? const year = Math.floor(diff / (1000 * 3600 * 24 * 365))
? if (year) {
? ? return `${year}年前`
? }
? const month = Math.floor(diff / (1000 * 3600 * 24 * 30))
? if (month) {
? ? return `${month}月前`
? }
? const day = Math.floor(diff / (1000 * 3600 * 24))
? if (day) {
? ? return `${day}天前`
? }
? const hour = Math.floor(diff / (1000 * 3600))
? if (hour) {
? ? return `${hour}小时前`
? }
? const minute = Math.floor(diff / (1000 * 60))
? if (minute) {
? ? return `${minute}分钟前`
? } else {
? ? return '刚刚'
? }
}

const formatDate = (dateTime) => {
? // console.log(date)
? // date = new Date();
? const date = new Date(dateTime) // 转换成Data();
? console.log(date)
? var y = date.getFullYear()
? console.log(y)
? var m = date.getMonth() + 1
? m = m < 10 ? '0' + m : m
? var d = date.getDate()
? d = d < 10 ? ('0' + d) : d
? return y + '-' + m + '-' + d
}

// 通过module.exports来导出模块
module.exports = {
? formatDate,
? relativeTime
};
```

### 切换当前npm镜像源到官网

由于我们需要把包上传到npm上,所以要先确保当前的npm源是npmjs.org。与之相关的命令有如下两条。

(1)查看当前的npm的registry配置.

```bash
npm config get registry?
# 查看当前的npm的registry配置,确保是https://registry.npmjs.org

# 如果不是,可以通过如下命令来设置
npm config set registry https://registry.npmjs.org?
# 手动设置registry
```

(2)或者使用nrm工具来设置:

![image-20210324175741385](asset/image-20210324175741385.png)

### 连接npm

```
npm adduser ?
```

这个命令需要输入三个信息以供连接上npmjs:

- 用户名
- 密码
- 邮箱(是你在npmjs官网上注册时使用的信息)

> ?如果你已经不是第一次连接了,这一步是可以省略的。

![image-20200212230007960](asset/image-20200212230007960.png)

你也可以通过如下命令检查自己是否连接成功了。

```bash
npm who am i
```

如果成功了,则可以进行最后一步了:publish?

如果想退出:

```bash
npm logout
```

### ?把包上传到npm

```
?npm publish?
```

如果成功:

```bash
-----------------------------------
npm notice
npm notice package: tool61@1.0.0
npm notice === Tarball Contents ===
npm notice 1.3kB index.js
npm notice 220B ?package.json
npm notice === Tarball Details ===
npm notice name: ? ? ? ? ?tool61
npm notice version: ? ? ? 1.0.0
npm notice package size: ?855 B
npm notice unpacked size: 1.5 kB
npm notice shasum: ? ? ? ?3bfba7bc92e242810a850ac39ded7ebe992a6d9c
npm notice integrity: ? ? sha512-VoRuxxbcGzXen[...]v3tKWYUT1B1AQ==
npm notice total files: ? 2
npm notice
+ tool61@1.0.0
```

出错的可能是:

- 这个包名被别人先用了。
- 包的版本号不对:每次publish时,包的版本号都应该要大于之前的版本号。
- 文件过大。你可能需要创建`.npmignore`文件来设置在打包时要忽略哪些文件。如下是一个demo.

```.npmignore
# .npmignore
/node_modules
npm-debug.log
/src
/examples
/build
```

如果没有报错,则表示一切ok,你可以用你的帐号密码登陆npm,去查看你名下的package是否有了myNpm

### 下载使用

通过`npm install 包名`即可来安装包。 然后,告诉你的小伙伴们去下载使用吧。

### 删除包

```cpp
npm unpublish --force //强制删除
```

如果你的包没有什么用处,建议删除掉,以节约公共资源。

### 更新包

1. 修改代码,保存。
2. **更新版本号**。可直接在package.json中修改:只能改大,不能改小。
3. 重新publish

## 总结:npm包的问题

### 为什么要把自己的代码上传到npm上?

- 优秀的代码供所有人复用
- 提升职场竞争力 ----- 在团队其它同事没有做,你做了!
- 有了这个目标,我们写项目(写代码)时,就会更加考虑代码的通用性。

### 优秀的代码从哪里来?

- 自己写的,同事写的,总结别人....

### 把代码上传到npm上去,有格式要求吗?

有,必须要是**包**的格式

### 包是什么格式?

格式:

- 一定要有 ? package.json这个文件。 它就是用来对包进行整体说明。(name, ?version, description, author, dependencies, ......). `npm init --yes`

- 有自己的代码文件。这个代码文件要在package.json中的main中声明。

? <img src="asset/image-20210325084219839.png" alt="image-20210325084219839" style="zoom:33%;" />

### 在上传到npm之前,我们需要切换镜像吗?

需要,我们必须要把代码上传到npm的官网。虽然我们上传是传到npm官网,但是,它会自动同步(例如:每隔15分钟就会通过其它镜像最新的包的信息)给其它的镜像 --- taobao, cnpm.....?

### 在上传时,需要登陆吗?

需要,在命令行中登陆。 `npm adduser` ?这一个操作只需要做一次

### 在上传时,对包名有约定吗?

有。 1. 不能与现有包重名;2. 包名只能是小写字母+数字+中划线

### 上传的命令是什么?

是 `npm publish `

### 上传出错的可能性有?

1. 你的帐号还没有通过验证 (在你登记的邮箱里,会收到一封邮件,要去点击确认)。 qq邮箱好像不支持在手机中操作, 建议在pc中浏览器里进行操作。
2. 没有登陆, 没有做npm adduser
3. 网络环境不好

### 如何对包进行版本更新?

1. 更新代码,准备重新发布
2. 升级版本号(只能改大,不能改小)。 在 package.json中去修改version值

3. npm publish

### 如何去下载包

命令:`npm i 包名`?

1. 在另一个项目中去下载包

2. 为了提升下载速度,我们会切换镜像到taobao。

## 作业1 全局安装i5ting_toc 包

i5ting_toc 是一个可以把 md 文档转为 html 页面的小工具。

官方文档地址为:https://www.npmjs.com/package/i5ting_toc 。

## 作业2 全局安装nodemon包

### 作用

**它能帮我们自动检测到我们的代码的修改,并自动重新运行我们的代码**

我们每次修改了代码,要想代码生效都需要运行。

这有点麻烦哈。

有没有一个工具会自动检测到我们的修改并自动重新运行我们的代码呢?有,它叫nodemon。[地址](https://www.npmjs.com/package/nodemon)

### 安装

步骤:

在任意位置 打开一个小黑窗,输入如下命令

```bash
npm install -g nodemon
```

回车。

此操作`需要联网`,根据网络速度所耗时间不同。如果这个命令执行完成并没有报错,就是说明安装成功了。

对上面的命令说明如下:

- npm是一个工具,用来管理node代码中要使用的第三方模块。它是随着node的安装而自动安装的:如果你安装node,则npm也已经安装过了,你可以直接使用。

- -g 表示全局安装。它也可以写在nodemon后面。即`npm install nodemon -g`。

??

### 使用nodemon

等待安装成功之后,使用方法也非常简单:在命令中,`使用nodemon来代替node`。

例如,原来是:

```bash
node server.js ?
```

现在是:

```
// 改成 nodemon server.js
nodemon server.js
```

它的好处在于会自动监听server.js这个文件的变化,如果变化了,就会重新自动再去运行。相当于是:

```bash
while(server.js 变化了){
? node server.js
}
```

说明:

- 它是一个第三方的包(其它程序员写的工具)

- 之前的node server.js还是可以用的。

??

## 附:npm 常用命令

- 查看

? ```bash
? npm -v ??? ??? ??? ? ? ?// 查看npm 版本
? where node ? ?? ??? ??? ?// 查看node的安装目录
? where npm ? ?? ??? ??? ?// 查看npm的安装目录
? npm root -g ?? ??? ??? ?// 查看全局包的安装目录
? npm list -g --depth 0 ? // 查看全局安装过的包
? ```

- 升级 npm

? ```bash
? npm install npm --global ?// 简写成 -g
? npm install npm -g
? ```

- 初始化 `package.json`

? ```bash
? npm init -y // 或者是npm init --yes
? ```

- 安装第三方包

? ```javascript
? // 安装当前目录下package.json中列出的所有的包
? // 如果之前安装了包,又在package.json中手动删除依赖
? // 它相当是删除包
? npm install
??
? // 全局安装
? npm install 包名 -g ?// npm install -g 包名?
??
? // 本地安装,没有指定版本,默认安装最新的版本
? npm install 包名
??
? // 一次安装多个包,空格隔开
? npm install 包名1 包名2 包名3
??
? // 安装指定版本的包
? npm install 包名@版本号
??
? // 简写。把install简写成 i
? npm i 包名
? ```

- 删除已安装的包?

? ```bash
? npm uninstall 本地安装的包名
? npm uninstall 全局安装的包名 -g
? ```

- 设置npm的register

? 如果你不想用 `nrm` ,下面这个原生的命令也可以切换镜像源(从哪里下载包)。

? ```bash
? npm config set registry https://registry.npm.taobao.org
??
? ## 所有npm i 包 都会从taobao的镜像去下载。
? ## 配置后可通过下面方式来验证是否成功
? npm config get registry?
? ```

[参考](https://www.npmjs.cn/getting-started/what-is-npm/ )

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-08 11:42:45  更:2021-10-08 11:44:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 0:28:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码