npm,看这篇就够了

前言

最近在研究 npm 组件发布,碰到一些相关问题,算是整理一下。vue

涉及内容

  • package.json 文件介绍
  • .npmrc 的做用及配置
  • 公网 npm 组件发布

package.json

概述

package.json 定义了当前项目中 npm包 之间的依赖关系和项目的一些配置信息(项目名称,版本,描述,开发人,许可证 等等)。node

当说到包管理器,就会遇到 yarnnpm 的选择性问题。我是喜欢用 yarn 的,看看 github 上的开源项目,好比 vue 项目下就有 yarn.lock 文件,由此我猜想 yarn 可能更受欢迎一些,平常使用中我也是 yarn 用的比较多。webpack

当咱们 npm installyarn install 会根据项目下的 package.json 解析依赖包之间的依赖关系而后从配置的 npm registry.npmrc 能够配置对应的 registry)地址中搜索并下载包。git

咱们能够在 yarn.lockpackage-lock.json 看到包从哪里下载和依赖关系。github

提交代码的时候排除 node_modules 目录,可是要提交 yarn.lockpackage-lock.json ,用于锁定项目依赖包的版本。而且升级包的时候不要手动改 package.json 中的版本号,要使用命令 yarn upgradenpm upgrade 升级。web

npm inityarn init 能够生成 package.json。vue-cli

{
    "name": "@mflyyou/npm-description",
    "version": "0.1.0",
    "private": true,
    "author": "张攀钦",
    "license": "MIT",
    "main":"index.js",
    "keywords": [
        "npm 搜索关键词"
    ],
    "publishConfig": {
        "registry": "https://registry.npmjs.com/"
    },
    "repository": {
        "type": "git",
        "url": "http://git.com/项目git地址"
    },
    "files": [
        "dist",
        "src"
    ],
    "bugs": {
        "url": "http://localhost:8080//issues",
        "email": "bug@example.com"
    },
    "contributors": [
        {
            "name": "zhangpanqin",
            "email": "zhangpanqin@email.com"
        }
    ],
    "scripts": {
        "dev": "sh ./build/build.sh",
        "npm-version": "npm -v",
        "serve": "vue-cli-service serve"
    },
    "dependencies": {
        "vue": "^2.5.21"
    },
    "devDependencies": {
        "@vue/cli-plugin-babel": "^3.3.0"
    },
    "peerDependencies":{}
}

复制代码

package.json 字段介绍

name

name 字段做为项目的名称。 好比 vue 中的一个组件 @vue/cli-plugin-babel ,前面这个 @vue 其实就当前包的 scope ,既命名空间。咱们能够根据 scope 配置一些私有包 registry,从而达到一些包来源于特定的地址。shell

registry=https://registry.npm.taobao.org/
@pay-plugin:registry=https://npm.udolphin.com
复制代码

version

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]

'npm [-v | --version]' to print npm version
'npm view <pkg> version' to view a package's published version 'npm ls' to inspect current package/dependency versions 复制代码

"version": "0.1.0”, 对应 major-minor-patchnpm

# 更新 major 的位置,其他位置为 0
npm version major 

# 更新 minor 的位置,major 不变,其他位置为 0
npm version minor 

# 更新 patch 的位置,其他位置不变
npm version patch 
复制代码
  • major 对应一次大的迭代,好比 vue 3.0 ts 从新,添加新的功能,更新 major 版本号
  • minor 对应小版本迭代,发生兼容旧版API的修改或功能添加时,更新 minor 版本号
  • patch 对应修订版本号,通常针对 bug 修复时,修改 patch 的版本号

当你的项目须要发布的时候,version 必定要和之前的不同,不然发布不成功。json

private

标识当前包是否私有,为 true 时包不能发布。

main

默认 index.js。指定 import 或 require 的时候加载的 js。

keywords

描述当前项目的关键字,用于检索当前插件。

publishConfig

"publishConfig": {
    "registry": "https://registry.npmjs.com/"
}
复制代码

有的时候呢咱们在 .npmrc 配置了别的 registry ,好比淘宝镜像。我安装依赖包的时候呢,想从淘宝镜像安装。发布插件的时候想发布到官网上。就能够在 publishConfig 中配置了。

files

指定发布的依赖包,包含的文件,默认会忽略一些文件。也能够根目录下建立 .npmignore 忽略一些文件。

scripts

配置一些执行脚本。好比说 npm run dev 就是运行 sh ./build/build.sh

"scripts": {
    // 运行 shell 脚本
	"dev": "sh ./build/build.sh",
	"build": "npm -v",
    // build 成功以后会执行 publish 
	"pub": "npm run build && npm publish"
}
复制代码

dependencies

项目的开发依赖。key 为模块名称,value 为版本范围。项目打包时会将这里的依赖打包进去。

fly-npm 地址

fly-npm 和 fly-use-npm 已发布。

注意,这里也有个坑。好比我有两个插件 fly-npm,fly-use-npm,fly-use-npm 中 dependencies 中依赖 fly-npm。我在 my-vue 项目开发的时候引入 fly-use-npm。我是能够直接 import fly-use-npm 项目能够正常运行。可是当你 import fly-npm 项目解析依赖会报错。由于只有在当前项目中 dependencies 引入的依赖才能够被 import。

<template>
    <div>
        <button @click="clickTest">
            测试
        </button>
    </div>
</template>
<script>
// fly-npm 只有在当前 my-vue 项目 dependencies 引入才能够被 import
//import flyNpm from 'fly-npm';    
import flyUseNpm from 'fly-use-npm';

export default {
    name: 'TestPlugin',
    methods: {
        clickTest() {
            flyUseNpm();
        },
    },
};
</script>


复制代码

devDependencies

为开发依赖,打包的时候不会打包进去。好比咱们使用的 babel webpak 等相关的插件,打包的时候,并不会被打包进去。

peerDependencies

在将这个以前,咱们先来了解 npm 的树形依赖是什么意思。

我建立一个 vue 项目 my-vue 依赖 fly-use-npm(它依赖 fly-npm 1.0.0),fly-npm(2.0.0),在咱们项目中能够看到。

my-vue 没有引入 fly-npm 2.0.0 的时候,my-vue/node_modules/fly-npm 为 1.0.0。

当咱们引入 fly-npm 2.0.0 的时候,依赖关系图如上图,这就是树形依赖。

下面是测试引入 fly-npm 2.0.0 以后的变化。

<template>
    <div>
        <button @click="clickTest">
            测试
        </button>
    </div>
</template>
<script>
import flyUseNpm from 'fly-use-npm';
import flyNpm from 'fly-npm';

export default {
    name: 'TestPlugin',
    methods: {
        clickTest() {
            // 打印 2.0.0
            console.log('fly-npm', flyNpm);
            // 使用的是 1.0.0
            flyUseNpm();
        },
    },
};
</script>

复制代码

从上面咱们能够看到,一个项目存在了两份 fly-npm 的包。这样打包的体积相应也会增大。为了解决这个问题,引入了 peerDependencies

建立 vue 项目 my-vue,依赖 fly-use-npm(4.0.0,其 peerDependencies 是 fly-npm 1.0.0 )。

peerDependencies 添加的依赖包,不会(测试的 yarn 1.22.0,npm 6.13.7)自动安装的。

当我在 my-vue 项目 yarn install 的时候,因为没有引入 fly-npm 会报错。

当我在项目中引入 fly-npm 2.0.0 安装会在当前项目下,出现警告信息。

warning " > fly-use-npm@4.0.0" has incorrect peer dependency "fly-npm@1.0.0”。

当你开发一个组件,依赖特定包的版本就须要这样处理。

// fly-use-npm
import flyNpm from 'fly-npm';
const obj = () => {
    console.log('引用的 fly-npm 版本为:', flyNpm.version);
    if (flyNpm.version > 1) {
        throw new Error('版本大于 1');
    }
}
export default obj;
复制代码

算是场景模拟,fly-npm 最新包是 2.0.0,这算是一个重大版本升级,可能存在不兼容 1.0.0 的东西。因此我在 fly-use-npm 推荐使用(peerDependencies)1.0.0。当我在实际用的时候呢,引入 fly-npm 2.0.0 ,发现某个功能依赖 fly-npm 2.0.0 报错了,就须要想到是否是依赖包不兼容的问题了。

可是同时你还想用 fly-npm 2.0.0 的功能,那你只能去提交一个 pr 兼容 fly-npm 或者 fly-use-npm 。

这种状况不多会遇到,通常版本升级都会兼容之前的功能的,也不用太在乎这样的问题。

通常咱们不多会遇到这种问题。github 上流行的库也不多会用到 peerDependencies

.npmrc

package.json 中的依赖包从哪里安装呢?.npmrc 能够配置依赖包从哪里安装,也能够配置 npm 的一些别的配置。

.npmrc 配置文件优先级

  • 项目配置文件: /project/.npmrc
  • 用户配置文件:~/.npmrc
  • 全局配置文件:/usr/local/etc/npmrc
  • npm 内置配置文件 /path/to/npm/npmrc
# 获取 .npmrc 用户配置文件路径
npm config get userconfig
复制代码

项目下 .npmrc 文件的优先级最高,能够每一个项目配置不一样的镜像,项目之间的配置互不影响。咱们也能够指定特殊的命名空间(scope)的来源。

@thingjs-plugin 开头的包从 registry=https://npm.udolphin.com 这里下载,其他全去淘宝镜像下载。

registry=https://registry.npm.taobao.org/
@thingjs-plugin:registry=https://npm.udolphin.com
复制代码
npm config set <key> <value> [-g|--global]  //给配置参数key设置值为value;
npm config get <key>                        //获取配置参数key的值;
npm config delete <key>  [-g|--global]      //删除置参数key及其值;
npm config list [-l]                		//显示npm的全部配置参数的信息;
npm config edit                     		//编辑用户配置文件
npm get <key>                           	//获取配置参数 key 生效的值;
npm set <key> <value> [-g|--global]         //给配置参数key设置值为value;
复制代码

没有加 -g 配置的是用户配置文件

-g 会配置到全局配置文件

npm 组件发布流程

  • 去 npm 官网申请帐号
  • 添加帐号到你电脑
  • 开发你的组件,使用 webpack,babel 处理
  • npm 发布你的包

申请帐号

官网申请一个帐号,用于登陆和发布组件。

在项目的根路径下建立 .npmrc 配置文件,添加以下内容。

# 安装包的时候,配置阿里镜像
registry = https://registry.npm.taobao.org
复制代码

package.json 中配置发布源。

"publishConfig": {
    "registry": "https://registry.npmjs.com/"
}
复制代码

这样下载依赖包会从淘宝镜像下载,发布依赖包会发布到 npm 官网去。

添加帐号到你电脑

添加帐号命令官网说明 npm adduser

# npm adduser [--registry=url] [--scope=@orgname] [--always-auth] [--auth-type=legacy]

npm adduser  --registry=https://registry.npmjs.com/
复制代码

运行上述命令,.npmrc 用户配置文件生成一下内容

registry=https://registry.npmjs.com/
//registry.npmjs.com/:_authToken=xxx
复制代码

开发你的组件,使用 webpack,babel 处理

因为 webpack,babel 配置比较麻烦,这里使用 vue-cli 脚手架进行开发

package.json

{
    "name": "@thingjs-ad/thingjs-app",
    "version": "0.1.1",
    "private": false,
    "scripts": {
        "serve": "vue-cli-service serve",
        "build": "vue-cli-service build --target lib --name thingjs-app ./src/index.js",
        "lint": "vue-cli-service lint",
        "pub": "npm run build && npm publish --access=public"
    },
    "main": "dist/thingjs-app.umd.min.js",
    "files": [
        "src",
        "dist"
    ],
    "devDependencies": {
        "@vue/cli-plugin-babel": "^4.2.0",
        "@vue/cli-plugin-eslint": "^4.2.0",
        "@vue/cli-service": "^4.2.0",
        "babel-eslint": "^10.0.3",
        "eslint": "^6.7.2",
        "eslint-plugin-vue": "^6.1.2",
        "vue-template-compiler": "^2.6.11"
    },
    "eslintConfig": {
        "root": true,
        "env": {
            "node": true
        },
        "extends": [
            "plugin:vue/essential",
            "eslint:recommended"
        ],
        "parserOptions": {
            "parser": "babel-eslint"
        },
        "rules": {}
    },
    "browserslist": [
        "> 1%",
        "last 2 versions"
    ]
}
复制代码

组件内容

  • AA.vue
<template>
     <div>
         AA 组件
     </div>
</template>
<script>
export default {
    name:'AA'
};
</script>
复制代码
  • index.js
import AA from './components/AA.vue';

const components = [AA];


// 当调用 Vue.use,实际会调用这个 install 方法。Vue.component 注册全局组件。

const install = function (Vue) {
    components.forEach(component => {
        Vue.component(component.name, component);
    });
};

if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue);
}

export default {
    version: '1.0.0',
    install,
    AA
}
复制代码

发布组件

npm publish --access=public
复制代码

本文由 张攀钦的博客 创做。 可自由转载、引用,但需署名做者且注明文章出处。

如转载至微信公众号,请在文末添加做者公众号二维码。微信公众号名称:Mflyyou

img
相关文章
相关标签/搜索