nodejs进阶知识

文章目录

    • 写在前面
    • 一、dependencies、devDependencies和peerDependencies区别:
    • 二、需要牢记的npm命令
      • 2.1 npm
      • 2.2 npm config list
      • 2.3 npm配置镜像源
    • 三、npm install 的原理
    • 四、package-lock.json的作用
    • 五、npm run 的原理
    • 六、npx
      • 6.1 npx是什么
      • 6.2 npx的优势
      • 6.3 npm和npx区别
    • 七、发布npm包
    • 八、搭建npm私服
    • 九、模块化
      • 9.1 CommonJS规范
      • 9.2 ESM规范
      • 9.3 CommonJS和ESM的区别
    • 十、全局变量和API
    • 十一、CSR SSR SEO

写在前面

npm是Node Package Manager(Node.js包管理器)的缩写,是Node.js社区最流行的包管理工具之一。它不仅提供了包管理的功能,还提供了发布和共享代码、管理依赖、版本控制等功能,可以帮助开发者更方便地开发和分享代码。

npm可以用来从全球的代码库中获取并安装Node.js模块,这些模块可以用于构建应用程序、工具和包等。开发者可以通过npm来搜索、安装、更新和卸载各种Node.js模块。npm包管理器还支持各种依赖关系管理工具,如开发依赖、生产依赖、测试依赖等,可以帮助开发者更好地管理自己的项目。

npm的使用非常广泛,已经成为了前端开发的标配之一。无论是开发Web应用、移动应用、命令行工具还是桌面应用程序,npm都可以为开发者提供丰富的功能和支持。

一、dependencies、devDependencies和peerDependencies区别:

在NPM中使用npm init生成的package.json文件里,dependencies、devDependencies和peerDependencies是用于管理项目依赖的三个重要概念。

dependencies项目中依赖的包列表,这些包会在项目运行时自动安装,也可以理解是生产环境所需要的依赖,如vue、vuex、vue-router、md5等

devDependencies开发依赖列表。项目开发过程中所所需要的包的列表,这些包不会随项目一起发布,而是只在开发时使用。 安装在此的包通常使用npm i 包名 --save-dev或者简写npm i 包名 -D安装。什么是开发依赖呢?比如说 webpack vite rollup 等配置工具,只会在打包时使用,生产环境不需要使用,这类依赖就是开发依赖

peerDependencies:给编写插件人员或者编写npm包的开发人员去使用的;比如你要开发vite的插件,那么vite plugin插件是不能凭空运行的,需要依赖宿主环境,也就是依赖vite,要把vite安装下来才能使用插件,因此就要把vite安装在peerDependencies里。

二、需要牢记的npm命令

更多npm命令参考博客:满神之Npm Package json

2.1 npm

npm i用于初始化生成一个新的package.json文件。它会让用户设置一些配置,如包名、版本、描述等…可以一路回车使用默认配置,尾缀带-f表示force、-y表示yes,则跳过配置阶段,直接生产一个新的package.json文件,创建好之后可以在package.json直接查看或修改更新。

在这里插入图片描述

2.2 npm config list

npm config list用于列出所有的npm配置信息。执行该命令可以查看当前系统和用户级别的所有npm配置信息,以及当前项目的配置信息(如果在项目目录下执行该命令)

在这里插入图片描述

2.3 npm配置镜像源

npm config set registry 镜像源配置镜像源

npm get registry查看已配置的镜像源

在这里插入图片描述

扩展安装满神自己写的包xmzs,可以实现快捷切换各种镜像

在这里插入图片描述

在这里插入图片描述

如果公司有自定义的镜像 也可以使用这个包添加镜像

在这里插入图片描述

三、npm install 的原理

参考博客:满神——Npm install 原理

package.json和package-lock.json文件内的包版本一致或不一致时,包的安装版本依据是怎么样的?

不一致时:

会根据package.json的版本号去下载对应版本,并更新lock文件

一致时:

根据package-lock.json中的版本号去下载

其实包在下载前都会检查缓存中是否有对应包,如果有就直接解压到node_modules,如果没有就下载包资源,检查包的完整性后添加到缓存中再更新package-lock.json

node_modules中的很多包都会依赖其他的包,因此这样的包里面也会有node_modules文件夹,因此,在遍历依赖树的时候,会使用广度优先遍历算法,逐层处理每个依赖包的依赖,直到所有依赖包都被处理完毕。

安装包(依赖)的时候会采用扁平化的方式安装,简单理解就是:比如要安装两个包,分别是vue和react,它们都会依赖一个名为child子包,也可以称为二级依赖,如果这二级依赖版本是一致的,那么这个二级依赖会被提到一级依赖中,让vue和react共用这个依赖,这就是扁平化处理,如果不是一致的,那就在分别安装在vue和react的node_modules中作为二级依赖。

npm install 原理总结:执行该命令时会安装package.json/package-lock.json记录的依赖,在安装对应依赖前它会判断package.jsonpackage-lock.json内记录的包版本是否一致,从而决定根据package.json还是从-lock.json记录的版本下载,如果不一致会根据package.json下载,并更新-lock.json文件,如果一致则根据-lock.json下载【其实就是根据package.json下载】,下载前会使用广度优先遍历算法逐层遍历依赖树,判断是否要做扁平化处理,再检查缓存中是否有对应包,如果有就直接解压到node_modules,如果没就下载资源包并检查包完整性后添加到缓存并更新package-lock.json

四、package-lock.json的作用

  1. 锁定版本,记录依赖树详细信息
  2. 实现依赖缓存,它会通过name + version + integrity信息生成一个唯一的key,这个key能找到对应的index-v5下的缓存记录,如果有缓存记录就找到对应二进制文件解压到node_modules中。

包详细信息:

在这里插入图片描述

五、npm run 的原理

在这里插入图片描述

如上图,执行npm run dev,它会运行对应的可执行命令vite --mode dev,这些可执行命令是无法直接运行的,在package.json中配置完成后,在node环境下通过npm run scriptName 运行。那么这个可执行命令是如何运行的呢?这里以上面的vite举例:

它会从node_modules中找到.bin文件夹下的vite命令,可执行命令都在.bin文件夹下,如下图

在这里插入图片描述

这里的vite可执行命令还有cmd和powershell的版本,因此可以在cmd和powershell命令行内运行npm run dev命令,常规的vite可执行命令由于node是跨平台的,因此也可以给unix、Linux以及MacOs去使用,window比较特殊因此会有cmd和ps版的命令,

当然这个可执行命令也不是凭空产生的,它是在用户安装vite时,根据vite依赖的package.json文件下的bin配置生成的。

在这里插入图片描述

以上讲述了运行npm run命令会在当前项目的node_modules/.bin中运行可执行命令,如果没有.bin目录他还会从其他目录中找可执行命令,如下查找优先级

  1. 当前项目先去找有没有node_modules/.bin
  2. 全局的node_modules下面去找。使用npm config list查看配置,找到全局依赖的路径【prefix】,去这个路径找
  3. 去环境变量找
  4. 报错

在这里插入图片描述

npm run 的生命周期prevpost

npm run也是有生命周期的,以dev举例:如下图,这里运行npm run dev命令

在这里插入图片描述

如下,切换脚本代码顺序,依旧是先执行predev,接着dev,最后再执行postdev

在这里插入图片描述

应用场景:比如说运行npm run build命令,可以写个前置脚本实现清除dist文件夹,也可以写个后置脚本实现CI操作提交代码。

比如说熟悉的vue脚手架vue-cli就在使用pre前置命令,如下图:

在这里插入图片描述

所以说npm run生命周期的应用场景是非常多的。

六、npx

6.1 npx是什么

npx是一个命令行工具,它是npm5.2.0版本中新增的功能。它允许用户在不安装全局包的情况下,运行已安装在本地项目中的包或者远程仓库中的包。

npx的作用是在命令行中运行node包中的可执行文件,而不需要全局安装这些包。这可以使开发人员更轻松地管理包的依赖关系,并且可以避免全局污染的问题。它还可以帮助开发人员在项目中使用不同版本的包,而不会出现版本冲突的问题。

6.2 npx的优势

  • 避免全局安装:npx运行你执行npx package,而不需要你先全局安装package
  • 总是使用最新版本:如果你没有在本地安装相应的npm packagenpx会从npm的包仓库中下载并使用最新版,并且使用完会自动删除。
  • 执行任意的npm包:npx不仅可以执行在package.jsonscripts部分定义的命令,还可以执行任何npm package
  • 执行GitHub gist:npx甚至可以执行GitHub gist或者其他公开的JavaScript文件。

6.3 npm和npx区别

npx侧重于执行命令,执行某个模块命令。虽然会自动安装模块,但是重在执行某个命令。

npm侧重于安装或者卸载某个模块。重在安装,并不具备执行某个模块的功能。

这里卸载vite,并写了一个简易的html文件,执行npx vite可以看到成功使用vite运行index.html文件,并且package.json文件中并没有看到新增vite依赖。

在这里插入图片描述

在这里插入图片描述

七、发布npm包

发布npm包的好处是什么?

  • 方便团队或者跨团队共享代码,使用npm包就可以方便的管理,并进行版本控制
  • 做开源造轮子必备技术,否则你做完的轮子如何让别人使用,难道是u盘拷贝?
  • 面试题会问,字节就问过
  • 增加个人IP,让更多的人知道你的技术能力和贡献

发布npm包前需要注册npm账号,可以去npm官网注册,也可以命令行输入npm adduser

输入npm adduser会自动跳转npm账号注册网站,需要注意的是,注册时一定要将镜像源切换成npm官方镜像源https://npmjs.com/registry/,如下:

在这里插入图片描述

如未使用npm官方镜像源注册是会提示如下错误:

在这里插入图片描述

注册完成后使用npm login命令登录:

在这里插入图片描述

登录成功后使用npm publish命令发布包,如果发布时报403错误,表示包重名了需要重命名或者是版本重合,需要提升版本序号,如下:

在这里插入图片描述

下面我们更改包的名称,重新发布,如下:

在这里插入图片描述

接着,我们在npm官网搜索刚发的包,可以看到自己刚发布的包如下:是不是非常神奇?!

在这里插入图片描述

八、搭建npm私服

npm私服:通过npm install命令下载前端项目依赖时,每次都需要从淘宝等第三方npm服务器下载,速度慢,耗时长;第三方npm服务器一般不支持包的上传,公司内部开发的公共包只能通过拷贝的方式添加到各个程序员开发的前端项目内,效率低,不方便;因此,搭建npm私有服务器(简称npm私服)显得尤为重要。

npm私服工作原理:用户通过 npm install 命令安装某个模块时,npm会先检查 node_modules目录中是否已经存在该模块,如果存在,则结束该模块安装,否则向npm私服发起请求,npm私服先查询该模块是否是我们自己的私有模块或已经缓存过的公共模块,如果是则直接将其返回给用户,如果不是,则继续向上游npm服务器(如淘宝、yarnpkg和npmjs等npm服务器)查找,如果找到,则将该模块返回给用户并将其缓存至npm私服,否则响应用户“npm ERR! 404 Not Found”错误。

npm私服的优势

  • 可以离线使用,你可以将npm私服部署到内网集群,这样离线也可以访问私有的包
  • 提高包的安全性,使用私有的npm仓库可以更好的管理你的包,避免在使用公共的npm包的时候出现漏洞
  • 提高搞的下载速度,使用私有的npm仓库,你可以将经常使用的npm包缓存到本地,从而显著提高包的下载速度,减少依赖包的下载时间。这对于团队内部开发和持续集成、部署等场景非常有用

如何搭建npm私服

Verdaccio是一个通过Node.js创建的企业级npm私有仓库程序,可以安装运行在Windows系统和Linux系统,为了更好地让大家理解npm私有仓库用法,这里将其安装运行在Linux系统中。

官网:https://verdaccio.org/zh-CN/

安装指令:npm install verdaccio -g

使用方式非常简单:直接运行verdaccio即可。

在这里插入图片描述

运行verdaccio生成的默认端口是4873,打开此端口如下:可以点击设置更改翻译为中文

在这里插入图片描述

使用verdaccio --listen 自定义端口号可以指定开启端口,如下

在这里插入图片描述

下面我们可以根据启动的端口中所给指示创建用户并发布包:

在这里插入图片描述

在这里插入图片描述

刷新端口页面,可以成功看到新发布的包,再去查看npm官网中我们先前发布的包,可以看到版本还是1.0.0,说明npm私服并不会影响到npm官网中上传的包。

在这里插入图片描述

在这里插入图片描述

每次发包都要需要加上--registry http://localhost:2270/显然非常麻烦,因此我们可以使用mmp将端口存储端口镜像,如下:

在这里插入图片描述

刷新端口页面验证结果如下:

在这里插入图片描述

这样,以后我们想将包发布私服或者发布到npm官网,只需要切换镜像源即可。

九、模块化

Nodejs的模块化规范遵循两套规范,分别是CommonJS规范和ESM规范。

9.1 CommonJS规范

使用此规范package.json文件中设置"type": "commonjs"

引入模块require

它只支持这四种格式的引入:

  1. 内置模块,例如http os fs child_process等nodejs内置模块
  2. 第三方模块express md5 koa
  3. 自己编写的模块./index.js
  4. 支持引入addon C++扩展模块 .node文件
const fs = require('node:fs');  // 导入核心模块
const express = require('express');  // 导入 node_modules 目录下的模块
const myModule = require('./myModule.js');  // 导入相对路径下的模块
const nodeModule = require('./myModule.node');  // 导入扩展模块

导出模块exportsmodule.exports

module.exports = {hello: function() {console.log('Hello world!')}
}

如果不想导出对象,直接导出值

module.exports = 123

9.2 ESM规范

使用此规范package.json文件中设置"type": "module"

引入模块importimport必须写在头部

import fs from 'node:fs'

如果要引入json文件,需要做特殊处理,增加断言并且指定类型为json,node低版本是不支持的。

import data from './data.json' assert { type: "json" }
console.log(data)

在这里插入图片描述

导入模块的整体对象

import * as all from 'demo.js'

动态导入模块:import静态加载(也就是写在头部的那种导入方式)不支持掺杂在逻辑中,因此想要动态加载请使用import('')这里函数模式。

if(true) {import('./demo.js').then()
}

模块导出

导出默认对象

export default {  // 导出一个默认对象 只能有一个,不能重复export defaultname: 'test'
}

导出变量

export const a = 1  // 可以有多个

9.3 CommonJS和ESM的区别

  • CommonJS是基于运行时的同步加载,ESM是基于编译时的异步加载
  • CommonJS是可以修改值的,ESM值只读不可修改
  • CommonJS支持树摇tree Shaking,ESM不支持树摇
  • CommonJS中顶层的this指向这个模块本身,而ES6中顶层this指向undefined

十、全局变量和API

如何在nodejs定义全局变量?

在nodejs中使用global定义全局变量,定义的变量,在引入的文件中也可以访问,例如:

demo.js

global.value = '2270'
require('index.js')  // 引入使用全局变量的测试文件
console.log(global);  // 输出global对象

index.js

console.log(value)

在这里插入图片描述

需要注意的是,引入文件的代码要使用全局变量就必须要放在定义全局变量的后面

在浏览器中我们定义的全局变量都在window对象下,而nodejs是定义在global下,不同的环境还需要判断是浏览器还是nodejs,于是在ECMAScript 2020 出现了一个globalThis全局变量,在nodejs环境会自动切换成global对象,浏览器环境自动切换window对象,非常的方便。

在这里插入图片描述

在这里插入图片描述

关于其他全局API

由于nodejs中没有DOM和BOM,因此nodejs没有windowdocument相关的api,除了这些api,其他的ECMAScript Api基本都能使用,例如:

setTimeout setInterval Promise Math console Date等。

nodejs内置全局API

__dirname

它表示当前模块的所在目录的绝对路径。

__filename

它表示当前模块文件的绝对路径,包括文件名和文件扩展名,也就是说比__dirname多了一个文件名和文件扩展名。

process

process 模块是 nodejs 提供给开发者用来和当前进程交互的工具,它的提供了很多实用的 API,如获取命令行参数、获取当前工作目录、获取环境变量等…

  • process.argv:这是一个包含命令行参数【命令行参数指的是,控制台输入命令行后面追加的参数】的数组。第一个元素是Node.js的执行路径,第二个元素是当前执行的JavaScript文件的路径,之后的元素是传递给脚本的命令行参数。
  • process.env:这是一个包含当前环境变量的对象。您可以通过process.env访问并操作环境变量。
  • process.cwd():这个方法返回当前工作目录的路径。
  • process.on(event, listener):用于注册事件监听器。您可以使用process.on监听诸如exituncaughtException等事件,并在事件发生时执行相应的回调函数。
  • process.exit([code]):用于退出当前的Node.js进程。您可以提供一个可选的退出码作为参数。
  • process.pid:这个属性返回当前进程的PID(进程ID)。

这些只是process对象的一些常用属性和方法,还有其他许多属性和方法可用于监控进程、设置信号处理、发送IPC消息等。

需要注意的是,process对象是一个全局对象,可以在任何模块中直接访问,无需导入或定义。

Buffer

Buffer主要用于处理数据。之后会详细讲

十一、CSR SSR SEO

这三篇博客讲解的非常细致

  1. https://xiaoman.blog.csdn.net/article/details/132273569?spm=1001.2014.3001.5502
  2. https://juejin.cn/post/6844903961091112968?searchId=2023092420374812D6B5A036826B3B1E95
  3. https://juejin.cn/post/6844903824428105735?searchId=2023092420374812D6B5A036826B3B1E95

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/90111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows上安装 Go 环境

一、下载go环境 下载go环境:Go下载官网链接找到自己想下载的版本,点击下载,比如我这是windows64位的,我就直接点击最新的。 二、安装go环境 双击下载的.msi文件 next next 他默认的是c盘,你自己可以改,然…

解决Spring Boot 2.7.16 在服务器显示启动成功无法访问问题:从本地到服务器的部署坑

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

二、C++项目:仿muduo库实现并发服务器之时间轮的设计

文章目录 一、为什么要设计时间轮?(一)简单的秒级定时任务实现:(二)Linux提供给我们的定时器:1.原型2.例子 二、时间轮(一)思想(一)代码 一、为什…

web:[极客大挑战 2019]Havefun

题目 点进页面,页面显示是一只猫,没有其他的提示信息 查看网页源代码,划到最后 这段php代码包含了通过get方式的提交信息 构造payload: http://aaf4c4b5-7bf2-404f-8bf5-f6e97d830b72.node4.buuoj.cn:81/?catdog 即得到flag f…

2023软工作业(一)——计算器

班级班级社区作业要求软件工程实践第一次作业-CSDN社区作业目标完成一个具有可视化界面的科学计算器参考文献Fyne 目录 作业要求 项目源码地址 作业目标 0. 界面及功能展示 1. PSP表格 2. 解题思路描述 3. 核心代码 4. 设计与实现过程 5. 程序性能改进 6. 单元测试展…

Fiddler 抓包八个实用技巧

大家对Fiddler应该不会陌生,但里面有些技巧不见得都会,这里就有八个实用技巧,通过对Fiddler的定制,能提高大家的测试效率。 fiddler抓包教程:一节课教你fiddler抓包在测试领域的四大实战,你一定要学_哔哩哔…

vue event bus 事件总线

vue event bus 事件总线 创建 工程: H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day04\准备代码\08-事件总线-扩展 vue --version vue crea…

微信多账号聊天、多账号管理,轻松拿捏

你是否微信账号太多,很难管理; 是否很难触达精准客户; 是否人力成本不断上升, 公司迫切需要提高工作效率,降低成本。 ...... 针对多个痛点问题, 微信管理系统进行了有针对性的开发和定位。 多账号聚合…

【计算机网络黑皮书】入门必学的基本网络知识

【事先声明】 这是对于中科大的计算机网络的网课的学习笔记,感谢郑烇老师的无偿分享 书籍是《计算机网络(自顶向下方法 第7版)》 需要的可以私信我,无偿分享,课程简介下也有 B站链接 目录 网络核心电路交换端到端之间的…

LeetCode【2251. 花期内花的数目】

给你一个下标从 0 开始的二维整数数组 flowers ,其中 flowers[i] [starti, endi] 表示第 i 朵花的 花期 从 starti 到 endi (都 包含)。同时给你一个下标从 0 开始大小为 n 的整数数组 people ,people[i] 是第 i 个人来看花的时间…

基于SpringBoot的医院管理系统

目录 前言 一、技术栈 二、系统功能介绍 病床信息管理 药房信息管理 个人中心管理 药房信息 病床类别 科室信息管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展,医院也在创建着属于自己的管理系统。本文介…

uniapp 事件委托失败 获取不到dataset

问题&#xff1a; v-for 多个span ,绑定点击事件 代码:view里包着一个span, <view class"status-list" tap"search"><span class"status-item" v-for"(key,index) in statusList" :key"index" :data-key"k…

【N年测试总结】区块链行业测试特点

一、区块链业务系统简介 转入转出业务&#xff1a;这类业务一般会涉及币的转入和转出&#xff0c;转入的流程一般是用户从第三方钱包往用户在公司的地址转入&#xff0c;系统收到用户的转入操作消息通知后&#xff0c;定时在链上监控该地址相关的交易&#xff0c;通过校验各项…

windows:批处理bat入门

文章目录 什么是BAT常用命令与语法help与/?titlecolormodeechopausecallremset/a/p gotostartifif errorlevel for普通用法for /l 用法for /d用法for /r用法for /f用法in (file)delims和tokensskipeolusebackq 变量扩展变量延迟 setlocalshiftdirrd&#xff08;删除文件夹&…

服务器搭建(TCP套接字)-libevent版(服务端)

Libevent 是一个开源的事件驱动库&#xff0c;用于开发高性能、并发的网络应用程序。它提供了跨平台的事件处理和网络编程功能&#xff0c;具有高性能、可扩展性和可移植性。下面详细讲解 Libevent 的主要组成部分和使用方法。 一、事件基础结构&#xff08;event_base&#x…

【网络协议】Http-下

HTTP常见Header Content-Type: 数据类型(text/html等) Content-Length: Body的长度 Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上; User-Agent: 声明用户的操作系统和浏览器版本信息; referer: 当前页面是从哪个页面跳转过来的; location: 搭配3xx状态…

无需公网IP,实现公网SSH远程登录MacOS【内网穿透】

目录 前言 1. macOS打开远程登录 2. 局域网内测试ssh远程 3. 公网ssh远程连接macOS 3.1 macOS安装配置cpolar 3.2 获取ssh隧道公网地址 3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址 4.1 保留一个固定TCP端口地址 4.2 配置固定TCP端口地址 5. 使用固定TCP端…

定义豪车新理念 远航汽车亮相2023中国(天津)国际汽车展览会

近年来&#xff0c;随着汽车行业竞争持续加剧&#xff0c;老品牌面临积极转型&#xff0c;新势力则经验不足、实力欠佳&#xff0c;到底是难抵市场的风云变幻。在此背景下&#xff0c;有着“老品牌 新势力”双重基因的远航汽车可谓底气十足。作为大运集团携手博世、华为、阿里斑…

JumpServer开源堡垒机与爱可生云树数据库完成兼容性认证

近日&#xff0c;中国领先的开源软件提供商FIT2CLOUD飞致云宣布&#xff0c;JumpServer开源堡垒机已经完成与爱可生云树数据库软件的兼容性认证。经过双方联合测试&#xff0c;云树数据库软件&#xff08;简称&#xff1a;ActionDB&#xff09;V1.0与杭州飞致云信息科技有限公司…

什么是Vue的Vetur插件?它有哪些功能

引言 在现代前端开发中&#xff0c;Vue.js已经成为了一个备受欢迎的JavaScript框架。随着Vue.js的流行&#xff0c;开发人员需要强大的工具来提高他们的生产力和Vue.js项目的质量。Vetur插件是一个为Vue.js开发者提供的强大工具&#xff0c;它不仅提供了丰富的功能&#xff0c…