• 第二十五节:npm介绍、package.json详解、npm install原理、常用指令、npx工具、发布自己的包


    一. 包管理工具npm

    (关于npm的安装、配置下载路径、一些指令,可以参考之前的文章:https://www.cnblogs.com/yaopengfei/p/14478126.html)

    1. npm简介

    (1). 包管理工具npm

        npm全称,Node Package Manager,也就是Node包管理器;

        但是目前已经不仅仅是Node包管理器了,在前端项目中我们也在使用它来管理依赖的包;比如vue、vue-router、vuex、express、koa、react、react-dom、axios、babel、webpack等等;

    (2).如何下载npm工具呢?

      npm属于node的一个管理工具,所以我们需要先安装Node,安装完node以后,npm也就安装了。

      node管理工具:https://nodejs.org/en/

    (3). npm管理的包可以在哪里查看、搜索呢?

      npm包的官网:https://www.npmjs.com/

    (4). npm管理的包存放在哪里呢?

      我们发布自己的包其实是发布到registry上面的;当我们安装一个包时其实是从registry上面下载的包;

      A. 通过【npm install xxx -g】全局安装的包,在你设置的全局文件夹下:D:\Develop\npm\node_modules

      B. 通过【npm install xxx】和【npm install -D】安装项目依赖的包,在对应项目的node_modules里。

    注意:对于项目依赖的包,她是有缓存的,即如果本地电脑已经下载过这个版本的包,就直接去本地拿到压缩包,解压到项目中的node_modules即可,不需要去npm官网的registry上下载,那么这个压缩包在 D:\Develop\npm-cache 下。

    【后面将结合package_lock.json详细讲解】
     

    2. npm配置文件(package.json)

    (1). npm如何管理这么多包?

       我们每一个项目都会有一个对应的配置文件,无论是前端项目(Vue、React)还是后端项目(Node);这个配置文件会记录着你项目的名称、版本号、项目描述等;也会记录着你项目所依赖的其他库的信息和依赖库的版本号

       这个配置文件就是package.json

    (2). 如何生成这个配置文件

      A.  手动从零创建项目,【npm init –y】 或者【npm init】一步一步生成

      B.  通过脚手架创建项目,脚手架会帮助我们生成package.json,并且里面有相关的配置

    npm init -y 创建的配置文件

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

    Vue3的配置文件

    {
        "name": "vue3Admin",
        "version": "0.1.0",
        "description": "vue3 vite next admin template js setup",
        "author": "ypf",
        "license": "MIT",
        "scripts": {
            "serve": "vite --force",
            "build": "vite build",
            "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
        },
        "dependencies": {
            "@element-plus/icons-vue": "^0.2.4",
            "axios": "^0.24.0",
            "echarts": "^5.2.2",
            "element-plus": "^1.2.0-beta.6",
            "mitt": "^3.0.0",
            "nprogress": "^0.2.0",
            "qrcodejs2-fixes": "^0.0.2",
            "screenfull": "^6.0.0",
            "sortablejs": "^1.14.0",
            "vue": "3.2.20",
            "vue-clipboard3": "^1.0.1",
            "vue-router": "^4.0.12",
            "vuex": "^4.0.2"
        },
        "devDependencies": {
            "@vitejs/plugin-vue": "^2.0.1",
            "@vue/compiler-sfc": "^3.2.26",
            "dotenv": "^10.0.0",
            "eslint": "^8.5.0",
            "eslint-plugin-vue": "^8.2.0",
            "prettier": "^2.5.1",
            "sass": "^1.45.1",
            "sass-loader": "^12.4.0",
            "unplugin-auto-import": "^0.5.4",
            "vite": "^2.7.4",
            "vite-plugin-vue-setup-extend": "^0.1.0",
            "vue-eslint-parser": "^8.0.1"
        },
        "browserslist": [
            "> 1%",
            "last 2 versions",
            "not dead"
        ],
        "bugs": {
            "url": "https://www.cnblogs.com/yaopengfei"
        },
        "engines": {
            "node": ">=12.0.0",
            "npm": ">= 6.0.0"
        },
        "keywords": [
            "vue",
            "vue3",
            "vuejs/vue-next",
            "vuejs/vue-next-template",
            "vuejs/vue-next-template-js",
            "element-ui",
            "element-plus",
            "vue-next-admin",
            "next-admin"
        ],
        "repository": {
            "type": "git",
            "url": "https://www.cnblogs.com/yaopengfei"
        }
    }
    View Code

    3. package.json属性详解

    (1). 基本属性

       name是项目的名称;【必填】

       version是当前项目的版本号;【必填】

       description是描述信息,很多时候是作为项目的基本描述;

       author是作者相关信息(发布时用到);

       license是开源协议(发布时用到);

    (2). private属性

       private属性记录当前的项目是否是私有的;

       当值为true时npm是不能发布它的,这是防止私有项目或模块发布出去的方式;

    (3). main属性

       设置程序的入口。webpack实际上是找到对应的main属性查找文件的

    (4). scripts属性

        scripts属性用于配置一些脚本命令,以键值对的形式存在;配置后我们可以通过 npm run 命令的key来执行这个命令;

        比如配置了 "serve": "vite --force",  我们就可以执行 【npm run server】 实际上等价于 【npx vite --force

    特殊情况:对于常用的key,是可以省略run的。【npm start】和【npm run start】是等价的。对于常用的 start、 test、stop、restart可以省略掉run直接通过 npm start等方式运行;

    (5). dependencies属性

        dependencies属性是指定无论开发环境还是生产环境都需要依赖的包通常是我们项目实际开发用到的一些库模块vue、vuex、vue-router、react、react-dom、axios等等;

    (6). devDependencies属性

        一些包在生产环境是不需要的,仅开发过程中需要,比如webpack、babel等; 这个时候我们会通过 【npm install webpack --save-dev】,将它安装到devDependencies属性中;

    (7). peerDependencies属性

        还有一种项目依赖关系是对等依赖,也就是你依赖的一个包,它必须是以另外一个宿主包为前提的; 比如element-plus是依赖于vue3的,ant design是依赖于react、react-dom;

    (8). 依赖版本管理【重】

     npm的包通常需要遵从semver版本规范:semver:https://semver.org/lang/zh-CN/   npm semver:https://docs.npmjs.com/misc/semver

     semver版本规范是X.Y.Z: 

       X主版本号(major):当你做了不兼容的 API 修改(可能不兼容之前的版本);

       Y次版本号(minor):当你做了向下兼容的功能性新增(新功能增加,但是兼容之前的版本);

       Z修订号(patch):当你做了向下兼容的问题修正(没有新功能,修复了之前版本的bug);

      比如:   "vue": "3.2.20"、“^3.2.20”、“~3.2.20”、

     我们这里解释一下 ^和~的区别:

      ^x.y.z:表示x是保持不变的,y和z永远安装最新的版本;【这里指npm install的时候】

      ~x.y.z:表示x和y保持不变的,z永远安装最新的版本;    【这里指npm install的时候】

        x.y.z :  就如字面一样的版本

    (9). engines属性

      engines属性用于指定Node和NPM的版本号;

      在安装的过程中,会先检查对应的引擎版本,如果不符合就会报错;

      事实上也可以指定所在的操作系统 "os" : [ "darwin", "linux" ],只是很少用到;

    (10). browserslist属性

       用于配置打包后的JavaScript浏览器的兼容情况,参考;否则我们需要手动的添加polyfills来让支持某些语法;也就是说它是为webpack等打包工具服务的一个属性

    二. npm install原理

    1. package-lock.json剖析

     下面代码是执行了【npm install axios】后的文件

    {
      "name": "01_npm",
      "version": "1.0.0",
      "lockfileVersion": 2,
      "requires": true,
      "packages": {
        "": {
          "name": "01_npm",
          "version": "1.0.0",
          "license": "ISC",
          "dependencies": {
            "axios": "^0.26.1"
          }
        },
        "node_modules/axios": {
          "version": "0.26.1",
          "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
          "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
          "dependencies": {
            "follow-redirects": "^1.14.8"
          }
        },
        "node_modules/follow-redirects": {
          "version": "1.14.9",
          "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz",
          "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
          "engines": {
            "node": ">=4.0"
          },
          "peerDependenciesMeta": {
            "debug": {
              "optional": true
            }
          }
        }
      },
      "dependencies": {
        "axios": {
          "version": "0.26.1",
          "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
          "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
          "requires": {
            "follow-redirects": "^1.14.8"
          }
        },
        "follow-redirects": {
          "version": "1.14.9",
          "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.14.9.tgz",
          "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
        }
      }
    }
    View Code

    name:项目的名称;

    version:项目的版本;

    lockfileVersion:lock文件的版本;

    requires:使用requires来跟踪模块的依赖关系;

    dependencies:项目的依赖,当前项目依赖axios,但是axios依赖follow-redireacts;

    axios中的属性如下:

      version表示实际安装的axios的版本

      resolved用来记录下载的地址,registry仓库中的位置;

      requires记录当前模块的依赖;

      integrity用来从缓存中获取索引,再通过索引去获取压缩包文件

    2. 【npm install】指令原理

    npm install首先会检测是有package-lock.json文件:

    (1). 没有lock文件

      A. 分析依赖关系,这是因为我们可能包会依赖其他的包,并且多个包之间会产生相同依赖的情况;

      B. 从registry仓库中下载压缩包(如果我们设置了镜像,那么会从镜像服务器下载压缩包,比如设置了从taobao下载);

      C. 获取到压缩包后会对压缩包进行缓存(从npm5开始有的);

      D. 将压缩包解压到项目的node_modules文件夹中(require的查找顺序会在该包下面查找)

    (2). 有lock文件

     A. 检测lock中包的版本是否和package.json中一致(会按照semver版本规范检测,详见上面08);

     B. 不一致,那么会重新构建依赖关系,直接会走顶层的流程;

     C. 一致的情况下,会去优先查找缓存

     D. 没有找到,会从registry仓库下载,直接走顶层流程;

     E. 查找到,会获取缓存中的压缩文件,并且将压缩文件解压到node_modules文件夹中;

    (3). 缓存的作用

      将通过npm下载过的包存放到本地(D:\Develop\npm-cache\_cacache) ,【npm get cache 查找路径】,下次npm的时候,会先查看package_lock中的版本是否符合package中的版本要求,如果符合,则优先查找缓存。

      如何查找去缓存中查找呢?

      package_lock中的integrity属性存放的是索引,然后根据索引去对应的文件夹Content-v2中找到压缩包,然后解压到项目中去。

     

    D:\Develop\npm-cache\_cacache\index-v5   存放索引
    D:\Develop\npm-cache\_cacache\content-v2  存放内容

    (4). package_lock.json的作用

     A. 锁定实际版本,用于【npm install】恢复的时候,下载该版本的包。

     B. 记录包本地缓存的索引,便于查找本地磁盘中的查找压缩包,来解压到项目中。

    4.  实战测试

    场景1:只有package.json  ,  初始化运行【npm install】

    如下,为package.json中的包对应的版本号,此时npm服务器上最新的版本分别为  0.26.1、4.17.21

    "dependencies": {
        "axios": "^0.26.0",
        "lodash": "^4.17.20"
      }

    运行指令【npm install】,按照规范 y和z处的版本号都要保持最新,所以实际安装的使 0.26.1 和 4.17.21这一版本 ,如下图生成的package_lock.json文件中的版本号

     

    场景2:存在lock文件,初始化运行【npm install】

    如下,为package.json中的包对应的版本号,此时npm服务器上最新的版本分别为  0.26.1、4.17.21

    "dependencies": {
        "axios": "^0.26.0",
        "lodash": "^4.17.20"
      }

    package_lock.json文件中的的版本号为 0.26.0 、4.17.20

      "dependencies": {
        "axios": {
          "version": "0.26.0",
          "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.0.tgz",
          "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
          "requires": {
            "follow-redirects": "^1.14.8"
          }
        },
        "lodash": {
          "version": "4.17.20",
          "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.20.tgz",
          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
        }
      }

    运行【npm install】,安装的是lock中锁定的版本 0.26.0、4.17.20  (通过查node_modules中下载的源码可知)

    总结:如果copy代码给别人,只包含package.json文件,则会根据package.json文件的版本号规范,去下载符合规范的最新版本。

              如果包含package.json和package_lock.json文件,且lock的中版本号符合package的规范,则安装的使lock文件中锁定的版本号,lock中版本是多少,下载的就是多少。

    场景3:存在lock文件,但是安装指定版本【npm install xxx@1.2.1】

       无论lock中锁定的版本是多少,都会被修改为1.2.1。

    场景4:存在lock文件,安装默认版本 【npm install xxx】

     如下,package.json文件中axios的版本为 "axios": "^0.26.0",  package_lock.json中的版本号为:0.26.0,服务器上最新的版本号为:0.26.1

     此时运行指令【npm install axios】,结果如下:

     package.json中变为: axios: ^0.26.1,lock文件中的版本号变为:0.26.1

    三. npm 常用指令

    详见官方文档:https://docs.npmjs.com/cli-documentation/cli

    详见之前的文档:https://www.cnblogs.com/yaopengfei/p/14478126.html

    四. npx工具

    1. 说明

        npx是npm5.2之后自带的一个命令。npx的作用非常多,但是比较常见的是使用它来调用项目中的某个模块的指令(node_modules文件夹中的某个包下的指令)。

    2. 实操

       比如:以webpack为例,全局安装的是webpack5.1.3,项目安装的是webpack3.6.0。

       那么我在项目中的命令行运行指令 【 webpack --version】,显示的是5.1.3, 调用的是全局的webpack,那么如何调用项目依赖的webpack呢?

    方案1:

       直接到node_modules下的webpack文件夹下执行这个指令,如:【./node_modules/.bin/webpack --version】

    方案2:

       配置package.json中的script下配置,如下,运行指令【npm run ypf】即可

    "scripts": {
        "ypf": "webpack --version"
      },

    方案3:

       使用npx直接调用即可,指令为:【npx webpack --version】

    五. npm发布包

    1. 准备

        首先需要去npm官网注册npm账号:https://www.npmjs.com/

    2. 发布

       (1). 编写ESModule代码

       (2). 项目中运行指令 【npm login】,输入账号密码进行登录

       (3). 运行指令【npm publish】进行发布

    如果要更新的话,需要修改版本号,需要符合semver规范,重新运行【npm publish】进行发布。

    其它指令:

        删除发布的包:【npm unpublish】

        让发布的包过期:【npm deprecate】

    3. 使用

        通过【npm install xxx】下载即可

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    Asp.Net MVC ajax调用 .net 类库问题
    sql关键查询
    js数组
    win2003 sp2+iis 6.0上部署.net 2.0和.net 4.0网站的方法
    Linux开启服务器问题(李蕾问题)
    SWFUpload 中文乱码问题
    设置html滚动条(陶庭飞问题)
    反射(前台到后台,后台到前台)
    MySql数据类型
    将页面居中
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/16144782.html
Copyright © 2020-2023  润新知