npm 发包和管理包及镜像源管理

邱秋 • 2022年11月10日 • 阅读:227 • npm nrm nodejs

将撸好的轮子发到NPM(node package manager)上很简单,只需要几个步骤 ,

登录账号

如果连账号都没有的话,点此创建

使用 npm login 登录

根据命令行提示,输入用户名、密码、邮件地址:

$ npm login
Username: chuchur
Password: 
Email: (this IS public) chuchur@qq.com
Logged in as chuchur on https://registry.npmjs.org/.

发包

如果连包都没, 那赶紧撸一个。

搞个目录, 进到里头,npm init 初始化一下

# 搞个目录
mkdir test-pkg
# 进到里头
cd tets-pkg
# 初始化
npm init

最终生成一个 package.json文件, 这个文件包含发布项目所需的必要项。

package name: (test-pkg)
version: (1.0.0)
description: this is a test pgk.
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)

最后一步,用 npm publish发布该项目

npm publish

如果一个同名的包已经存在 NPM,你将发布失败!

可通过npm search 命令看是否被占用:

npm search test-pkg

非要用这个名字怎么办,发布包到scope下,可以二选一:

  • package.json中,手动的修改name@username/package-name
  • 替代 npm initnpm init --scope=username

username 就是你的 npm 账号名

如果你的仓库有一个scope,你需要调整发布命令:

npm publish --access public

一个粗糙的发包流程就搞完了。

版本管理

升级包

发的包有bug ,我要更新包,就得重新发一个高一点的版本。

先更新版本 ,再发布

major (大版本),minor(版本),patch(小修复)

# 从 0.0.1 更新到 1.0.0
npm version major
# 从 0.0.1 更新到 0.1.0
npm version minor
# 从 0.0.1 更新到 0.0.2
npm version patch

执行版本命令之后,再发布

npm publish

废弃包

这个包, 不想维护了, 有其它的替代方案, 那......就废了它。

npm deprecate test-pkg "包有毒,不建议安装"

注意, 这个时候不是说包没有, 包还在的,在npm网站上仍然能够查到已废弃的npm包 。

废弃状态,是不能进行更新的。

删除包

这包我不要了,屎山代码见不得人,爱谁谁。

npm unpublish test-pkg -fore
# or
npm unpublish test-pkg -f

那么这个包就不见了,npm上 也找不到,屎山代码终于不被人所见, 好开森。

版本撤回

我操, 刚更新了一个小版本, 发现又造成了另外一个新的bug ,这可咋办,难不成我又要再发一个"打死不改版本2.0"吗,那要是这样, 是不是后面还有 "打死不改版本最终版本1000.0"版本呢。

不可能, 绝对不可能。。把这个有bug 的版本撤回即可。

npm unpublish test-pkg@2.0.3

以上撤回有bug的2.0.3 版本。

发包前的准备和辅助工具NP

  • 首先得有个包
  • 包 remote了 git仓库
  • 至少已经push到 remote 至少一次
  • 工作目录是干净的(已经commit and push)
  • 更新版本号
  • 给代码(屎山)创建 git tag
  • 给代码(屎山)创建 release notes

以上这准备做好了, 才可以发一个正式的包。

发包的流程都已经熟悉了, 代码没问题, npm version然后npm publish, 这个包就发上去了。

有一个辅助工具可以帮我们做这个事情 :NP

全局安装 np

 npm install --g np

安装完成之后,准备发包前执行即可:

np

他能辅助你做的工作, - 更新版本号 - 检查test 错误 - 检查是否已经得交了代码 - 给包打tag - 发包 - 提示你写release notes

当然,你也可以不用它。自己能做的事情, 不麻烦别人。

镜像源管理(nrm)

有时候我们装一个包 , 死活安装不了, 网络问题和被墙的问题,那么一定知道cnpm

cnpm 是 npm 镜像源其中的一种。

npm 默认的镜像源 是 https://registry.npmjs.org/

安装 nrm

npm install -g nrm

执行 nrm ls 就可以看到:

*npm ---------- https://registry.npmjs.org/
yarn --------- https://registry.yarnpkg.com/
tencent ------ https://mirrors.cloud.tencent.com/npm/
cnpm --------- https://r.cnpmjs.org/
taobao ------- https://registry.npmmirror.com/
npmMirror ---- https://skimdb.npmjs.com/registry/

有 腾讯 淘宝镜像源 。

切换镜像源

nrm use taobao #切换成taobao的源

nrm 的一些命令:

nrm -V #查看当前nvm版本; (即:是 ‘nrm -Version’ 简写);
nrm -h #显示所有命令; (即:是 ‘nrm -help’ 简写);
nrm current #显示当前源名称;
nrm add <registry> <url> [home] #添加一个源; (比如:公司自己的私有源);
nrm set-auth <registry> <value> [always]:#设置自定义源的授权信息;
nrm set-email <registry> <value> #给自定义源设置路径;
nrm set-hosted-repo <registry> <value> #设置发布到自定义源的 ‘npm’ 托管仓储
nrm home <registry> [browser] #浏览器中打开源首页;
nrm publish [options] [<tarball>|<folder>] #发布包到自定义源,如果没有使用自定义源,则直接发布到npm;
nrm ls #查看所有的支持源(有*号的表示当前所使用的源,以下[name]表示源的名称)
nrm use [name] #将npm下载源切换成指定的源
nrm use taobao #切换成taobao的源
nrm help #查看nrm帮助
nrm home [name] #跳转到指定源的官网
nrm add name http://registry.npm.frp.trmap.cn/ #增加特定源
nrm del name #删除源
nrm test npm #测试速度
nrm test #测试所有源的速度

如果你用了cnpm 或者 其它 的源, 这个时候你发包是发不了的, 你得把源切回到npm 才可以

当然不用这个逼 ,你也可以手动设置呀,

npm config set registry http://registry.npmjs.org

那是不是切换之后,就没法改变,当然不用它,你还可以零时指定源呀

npm i kui-vue --registry http://registry.npmjs.org

这个东西是备用的,就以防不时之需。 正常时候不推荐使用。 更新不及时,会造成很多问题。

npm 常用命令

npm   -v                             #查看版本号
npm   --help                         #查看npm所有命令
npm   adduser                        #添加npm账号,也可以去npm官网注册
npm   owner ls <package_name>        #查看模块拥有者
npm   owner add <user> <package_name> #添加一个发布者
npm   owner rm <user> <package_name> #删除一个发布者
npm   init                           #构建项目说明,生成package.json文件,如果有刚安装依赖
npm   view           gulp versions   #查看历史版本信息(最多只能显示100条)
npm   view           gulp versions  --json   #查看所有版本信息
npm   view           gulp version    #查看最新版本信息
npm   info           gulp            #查看所有版本及gulp的信息
npm   ls             gulp            #查看本地安裝的gulp版本
npm   ls             gulp -g         #查看全局安裝的gulp版本
npm   i              gulp@3.2.3      #安裝指定版本 
npm   i              gulp            #安装推荐的版本
npm   i              gulp@latest     #安裝指定、最新版本 
npm   i              A B C           #同时安裝ABC三个包
npm   install        gulp -D         #安裝到开发依赖(devDependencies字段中)
npm   install        gulp --save-dev #同上缩写
npm   install        gulp -S         #安裝到生产依赖(dependencies字段中)
npm   install        gulp --save     #同上缩写
npm   install        gulp@3.0.0 --save    
npm   update         gulp            #更新包
npm   update         gulp -g         #全局更新包
npm   uninstall      gulp@3.0.0 --save       #卸载依赖
npm   un             gulp@3.0.0 --save       #同上缩写
npm   install        cnpm -g --registry=https://registry.npm.taobao.org    #安装淘宝镜像
npm   config         list            #查看npm的配置
npm   config         set registry https://registry.npm.taobao.org          #设置淘宝镜像源
npm   config         set registry https://registry.npmjs.org               #设置npm源
npm   set            disturl https://npm.taobao.org/dist                   #设置资源库从淘宝库获取 
npm   cache          clean --force   #清空npm本地缓存  ,用于对付使用相同版本号发布新版本代码的人 
npm   run            dev/test/build  #执行script命令
npm   login                          #发布包时登录npm账号用的
npm   publish                        #发布包到npm官方库
npm   unpublish      test            #撤销已发布的包 
npm   unpublish      test --force    #强制撤销
npm   unpublish      test@1.0.2      #可以撤销发布自己发布过的某个版本代码 
npm   list           -g --depth 0    #查看全局安装过的包 
npm   dist-tag ls                    #查看当前的tag和对应的version
npm   dist-tag add   <package_name>@<version> latest  #把版本打名为 latest的tag

模块化/规范/打包

前端模块化演进

前端的模块化是一个演进的过程,经历了 4 个阶段:

  • 全局 function模式 : 将不同的功能封装成不同的全局函数
  • namespace模式 : 简单对象封装
  • IIFE模式:匿名函数自调用(闭包)
  • IIFE模式增强: 引入依赖

基本原理是将模块挂载在 window 属性下。到 IIFE 增强阶段,现在的模块化规范基本已经成型,有了明显的引入导出。如下代码的引入 jQuery 和暴露 myModule:

// module.js文件
(function(window, $) {
  let data = 'www.baidu.com';
  // 操作数据的函数
  function foo() {
    // 用于暴露有函数
    console.log(`foo() ${data}`);
    $('body').css('background', 'red');
    otherFun(); // 内部调用
  }
  function otherFun() {
    // 内部私有的函数
    console.log('otherFun()');
  }
  // 暴露行为
  window.myModule = { foo };
})(window, jQuery) // jQuery 作为参数引入

在此基础上,逐渐演化出了 AMD、CommonJS、CMD、UMD 等规范。

AMD(Asynchromous Module Definition - 异步模块定义)

AMD 更多用于浏览器端,需要异步加载各模块,然后再去执行内部代码。是 RequireJS 在推广过程中对模块定义的规范化产出,推崇依赖前置。

// 定义没有依赖的模块
define(function(){ return 模块 });

// 定义有依赖的模块
define(['module1', 'module2'], function(m1, m2){ return 模块 });

// 引入使用模块
require(['module1', 'module2'], function(m1, m2){ 使用m1/m2 });

CommonJS 规范

CommonJS 是服务端模块的规范,由于Node.js被广泛认知。根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的module.exports对象。

//module1.js
moudle.exports = { value: 1 };

//module2.js
var module1 = require('./module1');
var value2 = module1.value + 2;
module.exports ={ value: value2 };

CommonJS 加载模块是同步的,所以只有加载完成才能执行后面的操作。

CMD(Common Module Definition - 公共模块定义)

CMD 是 SeaJS 在推广过程中对模块定义的规范化产出,同时 CMD 也是延自 CommonJS Modules/2.0 规范。对于模块的依赖,CMD 是延迟执行,推崇依赖就近。

define((require, exports, module) => {
  module.exports = {
    fun1: () => {
       var $ = require('jquery'); // 执行 fun1 时,再加载
       return $('#test');
    } 
  };
});

如上代码,只有当真正执行到fun1方法时,才回去执行jquery。

UMD 规范

同时同时兼容 AMD 和 CommonJS,既可以适用浏览器端,有可以适用于服务器端.

UMD 规范甚至都不能称作一个规范,它是 AMD 和 CommonJS 的一个糅合。是一段固定的代码写法。如下的工厂模式:

((root, factory) => {
  if (typeof define === 'function' && define.amd) {
    //AMD
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    //CommonJS
    var $ = requie('jquery');
    module.exports = factory($);
  } else {
    //都不是,浏览器全局定义
    root.testModule = factory(root.jQuery);
  }
})(this, ($) => {
  //do something...  这里是真正的函数体
});

ES module 规范

另一种支持服务端和浏览器端的规范就是 ES module 了,即我们现在最常用的import 和 export:

export default ...;
import xxx from '';

export ...;
import { xxx } from '';

但目前也仅是大于 13.2 的 Node.js 版本才支持 ES 模块化,还需要等待很长的时间全面使用。

所以,出于兼容性考虑,我们仍然选择 UMD 规范进行开发。(处于淘汰边缘的UMD、CMD、AMD这些规范,大家不需要理解,只需要知道有这么一回事即可)

Webpack 打包

新建 webpack 配置文件,webpack.config.js。用 webpack 给组件库打包输出符合 UMD 规范的代码,只需要在基本配置稍作修改即可:

// webpack.config.js
const path = require('path');

module.exports = {
    mode: 'production',
    entry: './index.js',
    externals: 'lodash', // library包中有引入lodash,打包时不将lodash打进去,用户在引入该library时,需自己再引入lodash,避免用户重复引入lodash,导致文件过大。
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'library.js',
        library: 'library', // 全局挂载包的引用名
        libraryTarget: 'umd',  //通用模式:支持用户通过es、common.js、AMD的方式引入npm包
        globalObject: 'this' // node 等环境运行时需要设置为 this
    }
}

要修改的地方如下:

  • filename:打包产物library的名称;
  • externals: ‘lodash’, library 包中有引入 lodash,打包时不将 lodash 打进去,用户在引入该 library 时,需自己再引入 lodash,避免用户重复引入 lodash,导致文件过大;
  • libraryTarget: ‘umd’ 使用 UMD规范 支持用户通过 es、common.js、AMD 的方式引入 npm 包;
  • library: ‘library’ 会在全局变量中增加一个liabray的变量,用于挂载该包,主要用于通过脚本形式全局引入时的配置;
  • globalObject: 'this',为 webpack 4 新增属性,需要指定 global 的值为 this,否则会为默认值 self,无法在 nodejs 环境中使用。

我,秦始皇,打钱!

相关文章

禅境花园小程序

关注前沿技术开发.