• Node.js的入门及模块化


    初识Node.js

    Node.js是一个基于Chrome V8引擎的JavaScript运行环境。
    1、浏览器是JavaScript的前端运行环境
    2、Node.js是JavaScript的后端运行环境
    3、Node.js中无法调用DOM和BOM等浏览器内置的API

    区分LTS版本和Current版本的不同

    1、LTS作为长期稳定版本,对于追求稳定性的企业级项目来说,应使用LTS版本的Node.js。
    2、Current为新特性版本。
    使用node -v查看已安装Node.js的版本号

    在Node.js环境中执行JavaScript代码

    在这里插入图片描述
    在终端中,使用esc键,能够快速清空当前已输入的命令,输入cls命令,可以清空终端。

    fs文件系统模块

    fs模块是Node.js官方提供的,用来操作文件的模块,它提供了一系列的方法和属性,用来满足用户对文件的操作需求。
    fs.readFile()方法,用来读取指定文件中的内容。
    fs.writeFile()方法,用来向指定的文件中写入内容。
    如果在JavaScript代码中,使用fs模块来操作文件,则需要使用如下的方式先导入它:const fs = require('fs')

    fs.readFile()方法

    1、fs.readFile()的语法格式
    使用fs.readFile()方法,可以读取指定文件中的内容,语法fs.readFile(path[, options],callback)使用中括号包裹的是可选参数。
    参数1:必选参数,字符串,表示文件的路径
    参数2:可选参数,表示以什么格式的编码格式来读取文件
    参数3:必选参数,文件读取完成后,通过回调函数拿到读取的结果
    2、fs.readFile()示例代码
    以utf8的编码格式,读取指定文件的内容,并打印err和dataStr的值:

    //1、导入fs模块
    const fs = require('fs')
    //2、调用fs.reedFile()方法读取文件
    //  参数1:读取文件的存放路径
    //  参数2:读取文件时的编码格式,一般指定utf8
    //  参数3:回调函数,拿到读取失败和成功的结果, err dataStr
    fs.readFile('./files/1.txt','utf8',function (err,dataStr) {
        //打印失败的结果,如果读取成功,则err的值为null
        console.log(err)
        console.log('------')
        //打印成功的结果
        console.log(dataStr)
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述
    如果读取错误,err的值为错误对象,dataStr则为undefined
    在这里插入图片描述
    3、判断文件是否读取成功
    可以判断err对象是否为null,从而知晓文件读取的效果。通过err能够转为true,如果err为true则err不为null,则文件读取失败,打印失败的结果

    //1、导入fs模块
    const fs = require('fs')
    //2、调用fs.reedFile()方法读取文件
    //  参数1:读取文件的存放路径
    //  参数2:读取文件时的编码格式,一般指定utf8
    //  参数3:回调函数,拿到读取失败和成功的结果, err dataStr
    fs.readFile('./files/11.txt','utf8',function (err,dataStr) {
        if (err){
            return console.log('读取文件失败' + err.message)
        }
        console.log('文件读取成功!' + dataStr)
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    fs.writeFile()方法

    1、fs.writeFile()的语法格式
    使用fs.writeFile()方法,可以向指定的文件中写入内容,语法fs.writeFile(file,data,[, options],callback)使用中括号包裹的是可选参数。
    参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径
    参数2:必选参数,表示要写入的内容
    参数3:可选参数,表示以什么格式的编码格式来写入文件,默认是utf8
    参数4:必选参数,文件写入完成后的回调函数

    //1、导入fs模块
    const fs = require('fs')
    //2、调用fs.writeFile()方法,写入文件的内容
    //  参数1:表示文件的存放路径
    //  参数2:表示要写入的内容
    //  参数3:回调函数
    fs.writeFile('./files/2.txt','abcd',function(err) {
    	//如果文件写入成功,打印的err为一个null,但是当写入路径错误,打印的就不是null,而是一个真正的错误对象
        console.log(err)
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    2、判断文件是否写入成功
    可以判断err对象是否为null,从而知晓文件写入的效果。通过err能够转为true,如果err为true则err不为null,则文件读取失败,打印失败的结果

    //1、导入fs模块
    const fs = require('fs')
    //2、调用fs.reedFile()方法读取文件
    //  参数1:读取文件的存放路径
    //  参数2:读取文件时的编码格式,一般指定utf8
    //  参数3:回调函数,拿到读取失败和成功的结果, err dataStr
    fs.writeFile('./files/2.txt','hfhfhfh',function (err) {
        if (err){
            return console.log('读取写入失败' + err.message)
        }
        console.log('文件写入成功!' )
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    练习-考试成绩管理

    使用fs文件系统模块,将素材目录下成绩.txt文件中的考试数据,整理到成绩-ok.txt文件中。
    在这里插入图片描述
    核心实现步骤
    1、导入需要的fs文件系统模块
    2、使用fsreadFile()方法,读取素材目录下的成绩.txt文件
    3、判断文件下是否读取失败
    4、文件读取成功后,处理成绩数据
    5、将处理完的成绩数据,调用fs.writeFile()方法,写入到新文件成绩ok.txt中。

    //1、导入fs模块
    const fs = require('fs')
    //2、调用fs.reedFile()方法读取文件
    
    fs.readFile('./files/成绩-ok.txt','utf8',function (err,dataStr) {
        //3、判断是否读取成功
        if (err){
            return console.log('读取写入失败' + err.message)
        }
       /* console.log('文件写入成功!' +  dataStr)*/
        //4.1先把成绩的数据,按照空格进行分割
        const arrOld = dataStr.split(' ')
        console.log(arrOld)
        //4、2循环分割后的数据,对每一项数据,进行字符串的替换操作
        const arrNew = []
        arrOld.forEach(item => {
            arrNew.push(item.replace('=',':'))
        })
        console.log(arrNew)
        //4、3把数组中的每一项,进行合并,得到一个新的字符串
        const newStr = arrNew.join('\r\n')
        console.log(newStr)
        //5、调用fs.writeFile()方法,把处理完毕的成绩,写入到新文件中
        fs.writeFile('./files/成绩-ok.txt',newStr,function (err) {
            if (err){
                return console.log('写入文件失败!' + err.message)
            }
            console.log('成绩写入成功!')
    
        })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    fs模块-路径动态拼接的问题

    在使用fs模块操作文件时,如果提供的操作路径是以/或…/开头的相对路径时,很容易出现路径动态拼接错误的问题。
    原因:代码在运行的时候,会以执行node 命令时所处的目录,动态拼接出被操作文件的完整路径。
    解决方案:在使用fs模块操作文件时,直接提供完整的路径,不要提供.或…/开头的相对路径,从而防止路径动态拼接的问题。
    这里__dirname表示当前文件所处目录,这里可以使用字符串的拼接进行路径的指定。

    path路径模块

    path模块是Node.js官方提供的,用来处理路径的模块,它提供了一系列的的方法和属性,用来满足用户对路径的处理需求。
    path.join()方法,用来将多个路径拼接成一个完整的路径字符串
    path.basename()方法,用来从路径字符串中,将文件名字解析出来
    如果要在JavaScript代码中,使用path模块来处理路径,则需要使用如下的方式先导入它:const path = require('path')

    path.join()

    1、path.join()语法格式
    使用path.join()方法,可以把多个路径片段拼接为完整的路径字符串,语法格式如下:path.join([...paths])
    参数解读:...paths 路径片段的序列
    返回值:
    2、path.join()代码示例

    const path = require('path')
    const fs = require('fs')
    
    //注意: ../会抵消前面一层路径,多个则抵消多层路径
    const pathStr = path.join('/a','/b/c','../','./d','e')
    console.log(pathStr)//\a\b\d\e
    
    //这里写代码的文件为06.path.join这个文件处于day01文件夹下,所以这里的__dirname就是day01
    fs.readFile(path.join(__dirname,'/files/1.txt'),'utf8',function (err,dataStr) {
        if (err){
            return console.log(err.message)
        }
        console.log(dataStr)
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    path.basename()

    path.basename()方法,可以获取路径中的最后一部分,经常通过这个方法获取路径中的文件名,语法格式如下path.basenem(path[, ext])
    参数解读:path必选参数,表示一个路径的字符串
    ext可选参数,表示文件扩展名
    返回表示路径中的最后一部分

    const path = require('path')
    
    const fpath = '/a/b/c/index.html'
    
    const fullName = path.basename(fpath)
    console.log(fullName)//index.html
    
    const newfull = path.basename(fpath,'.html')
    console.log(newfull)//index
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    path.extname()

    使用 path.extname()方法,可以获取路径中的扩展名部分,语法格式如下:path.extname(path)
    参数解读:
    path 必选参数,表示一个路径字符串
    返回:返回得到的扩展名字符串

    const path = require('path')
    
    const fpath = '/a/b/c/index.html'
    
    const fext = path.extname(fpath)
    console.log(fext)//.html
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    综合案例-时钟案例

    案例要实现功能
    将素材目录下的index.html页面拆成三个文件,分别是index.js index.css index.html并且将拆分出来的3个文件存放到clock目录中。
    案例的实现步骤
    1、创建两个正则表达式,分别用来匹配

    //1.1导入fs文件系统模块
    const fs = require('fs')
    //1.2导入path路径处理模块
    const path = require('path')
    
    //1.3匹配<style></style>标签的正则
    //      其中\s表示空白字符;\S表示非空白字符;* 表示匹配任意次
    const regStyle = /<style>[\s\S]*<\/style>/
    //1.4匹配<script></script>标签正则
    const regScript = /<script>[\s\S]*<\/script>/
    
    //2.1读取需要被处理的HTML文件
    fs.readFile(path.join(__dirname,'/index.html'),'utf8',(err,dataStr) =>{
        //2.2读取HTML文件失败
        if (err) return console.log('读取HTML文件失败!' + err.message)
    
        //2.3读取HTML文件成功后,调用对应的方法,拆解出css,js和HTML文件
        resolveCSS(dataStr)
        resolveJS(dataStr)
        resolveHTML(dataStr)
    })
    
    //3.1处理css样式
    function resolveCSS(htmlStr){
        //3.2使用正则提取页面中的style标签
        const r1 = regStyle.exec(htmlStr)
        //3.3将提取出来的样式字典,做进一步处理
        const newCSS = r1[0].replace('','')
        //3.4将提取出来的css样式,写入到index.css文件中
        fs.writeFile(path.join(__dirname,'./clock/index.css'),newCSS,err => {
            if (err)return console.log('写入CSS样式失败!' + err.message)
            console.log('写入CSS样式成功')
        })
    }
    
    //4.1处理JS脚本
    function  resolveJS(htmlStr){
        //4.2使用正则提取页面中的<script>标签
        const r2 = regScript.exec(htmlStr)
        //4.3将提取出来的脚本字符串,做进一步处理
        const newJS = r2[0].replace('','')
        //4.4将提取出来的js脚本,写入到index.js文件中
        fs.writeFile(path.join(__dirname,'./clock/index.js'),newJS,err => {
            if (err)return console.log('写入JavaScript脚本失败!' + err.message)
            console.log('写入JS脚本成功!')
        })
    }
    
    //5.1处理html文件
    function resolveHTML(htmlStr){
        //5.1使用字符串的replace方法,把内嵌的<style><script>标签,替换为外联的<link><script>标签
        const newHTML = htmlStr
            .replace(regStyle,'')
            .replace(regScript,'')
        //5.2将替换完成的html代码,写入到index.html文件中
        fs.writeFile(path.join(__dirname,'./clock/index.html'),newHTML,err => {
            if (err) return console.log('写入HTML文件失败!' + err.message)
            console.log('写入HTML页面成功!')
        })
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    fs.writeFile()方法只能用来创建文件,不能用来创建路径。重复调用fs.writeFile()写入同一个文件,新写入的内容会覆盖之前的旧内容

    HTTP模块

    什么是HTTP模块

    在网络节点中,负责消费资源的电脑,叫客户端,负责对外提供网络资源的电脑,叫做服务器

    http模块是Node.js官方提供的,用来创建web服务器的模块,通过http模块提供的http.creatServer()方法,就能把一台普通的电脑,变成一台Web服务器,从而对外提供Web资源服务,导入模块const http = require('http')

    进一步理解http模块的作用

    服务器和普通电脑的区别在于,服务器上安装了web服务器软件,例如:IIS、Apache等。通过安装这些服务器软件,就能把一台普通电脑变成一台web服务器。
    在Node.js中,我们不需要使用IIS,Apache等这些第三方web服务器软件,因为我们可以基于Node.js提供的http模块,通过几行简单代码,就能充当服务器。

    服务器相关概念

    1、IP地址
    IP地址就是互联网上每台计算机的唯一地址,因此IP地址具有唯一性。如果把“个人电脑”比作“一台电话”,那么“IP地址”就相当于“电话号码”,只有在知道对方IP地址的前提下,才能与对应的电脑之间进行数据通信。

    IP地址的格式:通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是O~255之间的十进制整数。例如:用点分十进表示的IP地址(192.168.1.1)

    2、域名和域名服务器

    尽管IP地址能够唯一地标记网络上的计算机,但IP地址是一长串数字,不直观,而且不便于记忆,于是人们又发明了另一套字符型的地址方案,即所谓的域名(Domain Name)地址。
    IP地址和域名是一一对应的关系,这份对应关系存放在一种叫做域名服务器(DNS,Domain name server)的电脑中。使用者只需通过好记的域名访问对应的服务器即可,对应的转换工作由域名服务器实现。因此,域名服务器就是提供IР地址和域名之间的转换服务的服务器。

    单纯使用IP地址,互联网中的电脑也能够正常工作。但是有了域名的加持,能让互联网的世界变得更加方便。
    在开发测试期间,127.0.0.1对应的域名是localhost,它们都代表我们自己的这台电脑,在使用效果上没有任何区别。
    3、端口号
    计算机中的端口号,就好像是现实生活中的门牌号一样。通过门牌号,外卖小哥可以在整栋大楼众多的房间中,准确把外卖送到你的手中。
    同样的道理,在一台电脑中,可以运行成百上千个web服务。每个web服务都对应一个唯一的端口号。客户端发送过来的网络请求,通过端口号,可以被准确地交给对应的web 服务进行处理。
    在这里插入图片描述

    创建最基本的web服务器

    1、导入HTTP模块const http = require('http')
    2、创建web服务器实例const server = http.createServer()
    3、为服务器实例绑定request事件,监听客户端发送来的网络请求
    4、启动服务器

    //1、导入http模块
    const  http = require('http')
    //2、创建web服务器实例
    const server = http.createServer()
    //3、为服务器实例绑定request事件,即可监听客户端发送过来的网络请求
    //使用服务器实例的.on()方法,为服务器绑定一个request事件
    server.on('request',(req,res)=> {
        //只要有客户端来请求我们的服务器,就会触发request事件,从而调用这个事件处理函数
        console.log('Someone visit our web server')
    })
    //4、调用服务器实例.listen()方法,即可启动当前web服务器
    server.listen(80,() =>{
        console.log('http server running at http://127.0.0.1')
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    req请求对象
    只要服务器接收到了客户端的请求,就会调用通过server.on()为服务器绑定的request事件处理函数。如果想在事件处理函数中,访问与客户端相关的数据或属性,可以使用如下方式

    //1、导入http模块
    const  http = require('http')
    //2、创建web服务器实例
    const server = http.createServer()
    //3、为服务器实例绑定request事件,即可监听客户端发送过来的网络请求
    //使用服务器实例的.on()方法,为服务器绑定一个request事件
    server.on('request',(req) => {
        //这里使用的ES6中的模板字符串为反引号,就是键盘左上角的‘~’按钮
        const str = `Your request url is ${req.url},and request method is ${req.method}`
        console.log(str)//Your request url is /,and request method is GET
    
    })
    server.listen(80,() =>{
        console.log('server running at http://127.0.0.1')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    res响应对象
    在服务器的request事件处理函数中,如果想访问与服务器相关的数据或属性,可以使用如下方式

    //1、导入http模块
    const  http = require('http')
    //2、创建web服务器实例
    const server = http.createServer()
    //3、为服务器实例绑定request事件,即可监听客户端发送过来的网络请求
    //使用服务器实例的.on()方法,为服务器绑定一个request事件
    server.on('request',(req,res) => {
        //res是响应对象,它包含了与服务器相关的数据和属性,例如:
        //要发送到客户端的字符串
        const str = `Your request url is ${req.url},and request method is ${req.method}`
        //res.end()方法的作用,向客户端发送指定内容,并结束这次请求的处理过程
        res.end(str)
    
    })
    server.listen(80,() =>{
        console.log('server running at http://127.0.0.1')
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述
    解决中文乱码问题
    当调用res.end()方法,向客户端发送中文内容的时候,会出现乱码问题

    //1、导入http模块
    const  http = require('http')
    //2、创建web服务器实例
    const server = http.createServer()
    //3、为服务器实例绑定request事件,即可监听客户端发送过来的网络请求
    //使用服务器实例的.on()方法,为服务器绑定一个request事件
    server.on('request',(req,res) => {
        const str = `您请求的URL地址是${req.url},请求的method类型是${req.method}`
        //为了防止中文显示乱码的我呢提,需要设置响应头Content-Type的值为text/html;charest=utf-8
        res.setHeader('Content-Type','text/html;charset=utf-8')
        res.end(str)
    })
    server.listen(80,() =>{
        console.log('server running at http://127.0.0.1')
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    根据不同的url响应不同的html内容

    核心实现步骤
    1、获取请求的url地址
    2、设置默认的响应内容为404 Not Found
    3、判断用户请求的是否为/或/index.html首页
    4、判断用户请求的是否为/oabout.html关于页面
    5、设置Content-Type响应头,防止中文乱码
    6、使用res.end()把内容响应给客户端
    动态响应内容

    //1、导入http模块
    const  http = require('http')
    //2、创建web服务器实例
    const server = http.createServer()
    //3、为服务器实例绑定request事件,即可监听客户端发送过来的网络请求
    //使用服务器实例的.on()方法,为服务器绑定一个request事件
    server.on('request',(req,res) => {
        const url = req.url
        let content = '

    404 Not found!

    '
    if (url === '/' || url ==='/index.html'){ content = '

    首页

    '
    }else if (url === '/about.html'){ content = '

    关于页面

    '
    } res.setHeader('Content-Type','text/html;charset=utf-8') res.end(content) }) server.listen(80,() =>{ console.log('server running at http://127.0.0.1') })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    模块化的基本概念

    模块化是指解决一个复杂问题时,自顶向下逐级把系统划分成若干模块的过程,对于整个系统来说,模块是可以组合、分解和更换的单元。
    把代码进行模块化拆分的好处:提高代码复用性和可维护性,实现按需加载。使用模块化规范应考虑使用什么样的语法格式来引用模块,在模块中使用什么样的语法格式向外暴露成员。

    Node.js中模块化

    Node.js中模块的分类

    Node.js中根据模块来源的不同,将模块分为3大类,分别是:
    内置模块(内置模块是由Node.js官方提供的,例如fs、path、http等)
    自定义模块(用户创建的每个.js文件,都是自定义模块)
    第三方模块(由第三方模块开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要下载)

    加载模块

    使用强大的require()方法,可以加载需要的内置模块,用户自定义模块,第三方模块进行使用。使用require调用其他模块时,可以不用写文件后缀名,他自己会找。例如:

    //1、导入http模块
    const  http = require('http')
    //2、加载用户的自定义模块
    const custom = require('./custom.js')
    //3、加载第三方模块
    const moment = require('moment')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用require()方法加载其他模块时,会执行被加载模块中的代码

    Node.js中的模块作用域

    和函数作用域类似,在自定义模块中定义的变量,方法等成员,只能在当前模块中被访问,这种模块级别的访问限制,叫做模块作用域。
    我们导入的custom是一个空对象,这样防止了全局变量污染的问题。
    在这里插入图片描述

    向外共享模块作用域中的成员

    1、module对象
    在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息
    在这里插入图片描述
    2、module.exports对象
    在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用。外界用require()方法导入自定义模块时,得到的就是module.exports所指向的对象。
    3、共享成员时的注意点
    使用require()方法导入模块时,导入的结果,永远以module.exports指向的对象为准。
    在这里插入图片描述
    exports对象

    由于module.exports单词写起来复杂,为了简化向外共享成员的代码,Node提供了exports对象。默认情况下,exports和module.exports指向同一个对象,还是以module.exports指向的对象为准。
    在这里插入图片描述
    exports和module.exports使用误区
    简单来说,只要不是指向对象形式,就是添加属性。所以在同一个模块中不建议同时使用exports和module.exports

    在这里插入图片描述

    Node.js中的模块化规范

    Node.js遵循了CommonJS模块化规范,CommonJS规定了模块的特性和各模块之间如何相互依赖。
    CommonJS规定:
    1、每个模块内部,module变量代表当前模块
    2、module变量是一个对象,它的exports属性(即module.exports)是对外的接口
    3、加载某个模块,其实是加载该模块的module.exports属性,require()方法用于加载模块。

    npm与包

    Node.js中的第三方模块又叫包。不同于Node.js中的内置模块与自定义模块,包是由第三方个人或团队开发出来的,免费供所有人使用。
    由于Node.js的内置模块仅提供了一些底层的API,导致在基于内置模块进行项目开发的时,效率很低。包是基于内置模块封装出来的,提供了更高级、更方便的API,极大的提高了开发效率。
    包和内置模块之间的关系,类似于jQuery和浏览器内置API之间的关系。

    https://www.npmjs.com/网站上搜索自己所需要的包从https://registry.npmjs.org/服务器上下载自己需要的包

    下载包

    这个包管理工具的名字叫做Node Package Manager(简称npm包管理工具),这个包管理工具随着Node,js的安装包一起被安装到了用户的电脑上。
    使用时在官网搜索moment,进入后Documentation上右键在新标签页中打开则可显示具体使用方法。
    在这里插入图片描述

    npm入门

    在项目中安装包的命令
    npm install 包的完整名称,也可简化为 npm i 包的完整名称
    格式化时间的高级做法
    1、使用npm包管理工具,在项目中按安装格式化时间的包moment
    2、使用require()导入格式化时间的包
    3、参考moment的官方API文档对事件进行格式化

    //1、导入需要的包
    //注意导入的名称,就是装包的名称
    const moment = require('moment')
    //
    const dt = moment().format('YYYY-MM-DD HH:mm:ss')
    console.log(dt)//2022-08-22 17:07:41
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    初次装包后多了哪些文件

    初次装包完成后,在项目文件夹下多一个叫做node_modules 的文件夹和package-lock.json的配置文件。

    node modules文件夹用来存放所有已安装到项目中的包。require()导入第三方包时,就是从这个目录中查找并加载包。package-lock.json配置文件用来记录node_modules 目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等。

    包的语义化版本规范
    包的版本号是以“点分十进制”形式进行定义的,总共有三位数字,例如2.24.0其中每一位数字所代表的的含义如下:
    第1位数字:大版本
    第2位数字:功能版本
    第3位数字:Bug修复版本
    版本号提升的规则:只要前面的版本号增长了,则后面的版本号归零。

    包管理配置文件

    npm规定,在项目根目录中,必须提供一个叫做package.json的包管理配置文件。用来记录与项目有关的一些配置信息。例如:
    项目的名称、版本号、描述等
    项目中都用到了哪些包
    哪些包只在开发期间会用到
    那些包在开发和部署时都需要用到

    在团队共享开发中,需要同时剔除node_modules,所以在协同开发时,需要将其添加到.gitignore忽略文件中。
    快速创建package.json
    npm包管理工具提供了一个快捷命令,可以在执行命令时所处的目录中,快速创建package.json这个包管理。

    //作用:在执行命令所处的目录中,快速创建package.json文件
    npm init -y
    
    • 1
    • 2

    上述命令只能在英文的目录下成功运行!所以,项目文件夹的名称一定要使用英文命名,不要使用中文,不能出现空格。运行 npm install命令安装包的时候,npm包管理工具会自动把包的名称和版本号,记录到package.json中。

    Dependencies节点为package.json中记录使用npm install命令安装了那些包

    一次性安装所有的包
    当我们拿到一个剔除了node_modules的项目之后,需要先把所有的包下载到项目中,才能将项目运行起来。不然会报错,入没有moment包Error: Cannot find module ' moment'
    所以,我们需要一次性安装所有的包,也同Java更新依赖一样。执行npm install命令时,npm包管理工具会先读取 package.json 中的 dependencies 节点,读取到记录的所有依赖包名称和版本号之后,npm包管理工具会把这些包一次性下载到项目中
    卸载包
    可以运行npm uninstall命令,来卸载指定的包npm uninstall moment
    devDependencies节点
    如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到devDependencies节点中。与之对应的,如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到dependencies节点中。

    //安装指定的包,并记录到devDependencies节点中
    npm i 包名 -D
    //注意:上述命令是简写形式,等价于下面完整写法
    npm install 包名 --save-dev
    
    • 1
    • 2
    • 3
    • 4

    解决下包速度慢的问题

    切换npm的下包资源

    在这里插入图片描述

    nrm

    为了更方便的切换下包镜像资源,安装nrm小工具,利用nrm提供的终端命令,可以快速查看和切换下包的镜像源,这里的taobao改名为了npmmirror
    在这里插入图片描述
    包的分类
    使用npm包管理工具下载的包,共分为两大类,分别为项目包和全局包
    1、项目包:那些被安装到项目的node_modules目录中的包,都是项目包。
    项目包又分为两类,分别是:
    开发依赖包(被记录到devDependencies节点中的包,只在开发期间会用到)
    核心依赖包(被记录到dependencies节点中的包,在开发期间和项目上线之后都会用到)
    2、全局包:在执行npm install命令时,如果提供了-g参数,则会把包安装为全局包。
    全局包会被安装到C:\Users\用户目录\AppData\Roaming\npm\node_modules目录下。
    只有工具性质的包,才有全局安装的必要性。因为它们提供了好用的终端命令。判断某个包是否需要全局安装后才能使用,可以参考官方提供的使用说明即可。

    3、i5ting_toc
    i5ting_toc 是一个可以把 md 文档转为 html 页面的小工具,使用步骤如下:

    在这里插入图片描述
    规范的包结构
    一个规范的包,它的组成结构,必须符合以下 3 点要求:
    ① 包必须以单独的目录而存在
    ② 包的顶级目录下要必须包含 package.json 这个包管理配置文件
    ③ package.json 中必须包含 name,version,main 这三个属性,分别代表包的名字、版本号、包的入口。

    模块的加载机制

    优先从缓存中加载

    模块在第一次加载后会被缓存。 这也意味着多次调用 require() 不会导致模块的代码被执行多次。
    注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。

    内置模块的加载机制

    内置模块是由 Node.js 官方提供的模块,内置模块的加载优先级最高。
    例如,require(‘fs’) 始终返回内置的 fs 模块,即使在 node_modules 目录下有名字相同的包也叫做 fs。

    自定义模块的加载机制

    使用 require() 加载自定义模块时,必须指定以 ./ 或 …/ 开头的路径标识符。在加载自定义模块时,如果没有指定 ./ 或 …/
    这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。
    同时,在使用 require() 导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:
    ① 按照确切的文件名进行加载
    ② 补全 .js 扩展名进行加载
    ③ 补全 .json 扩展名进行加载
    ④ 补全 .node 扩展名进行加载
    ⑤ 加载失败,终端报错

    第三方模块的加载机制

    如果传递给 require() 的模块标识符不是一个内置模块,也没有以 ‘./’ 或 ‘…/’ 开头,则 Node.js 会从当前模块的父
    目录开始,尝试从 /node_modules 文件夹中加载第三方模块。
    如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。
    例如,假设在 ‘C:\Users\itheima\project\foo.js’ 文件里调用了 require(‘tools’),则 Node.js 会按以下顺序查找:
    ① C:\Users\itheima\project\node_modules\tools
    ② C:\Users\itheima\node_modules\tools
    ③ C:\Users\node_modules\tools
    ④ C:\node_modules\tools

    目录作为模块

    当把目录作为模块标识符,传递给 require() 进行加载的时候,有三种加载方式:
    ① 在被加载的目录下查找一个叫做 package.json 的文件,并寻找 main 属性,作为 require() 加载的入口
    ② 如果目录里没有 package.json 文件,或者 main 入口不存在或无法解析,则 Node.js 将会试图加载目录下的 index.js 文件。
    ③ 如果以上两步都失败了,则 Node.js 会在终端打印错误消息,报告模块的缺失:Error: Cannot find module ‘xxx’

  • 相关阅读:
    最炫表白网站html5源码_七夕程序员的十款表白源码_html+css+js
    【HDU No. 1166】 敌兵布阵
    c语言入门---自定义类型:结构体,枚举,联合
    LIO-SAM源码解析(五):mapOptmization.cpp
    C/C++轻量级并发TCP服务器框架Zinx-游戏服务器开发004:游戏核心消息处理 - 玩家类的实现
    Linux I2C驱动入门之读取bmp280传感器的ID寄存器的值
    医院陪诊服务预约小程序的作用如何
    基于训练和推理场景下的MindStudio高精度对比
    生产环境 /dev/vda1文件满了导致redis无法写入问题分析 以及df -h解析
    Spring技术——介绍、初识
  • 原文地址:https://blog.csdn.net/weixin_43914631/article/details/126431868