封装第三方组件并上传到npm

一、npm简介

npm是内置于nodejs的一个包管理工具,用于管理第三方模块。当你安装完nodejs,也就可以使用npm命令了。

npm的官方服务器上有大量第三方模块,如nodejs工具(webpack、rollup等)、nodejs模块(mysql、path等)、vue及react等的脚手架(vue-cli、create-react-app等),以及各大js框架对应的不计其数的组件、插件等。截止到目前(2020年2月15日),npm服务器上已经累计上传了超过120万个第三方模块。

总的来说,npm就是一个JavaScript模块的集中管理平台,与js相关的几乎所有第三方模块都可以从这里找到。而一旦将你自己的模块上传到npm,就等于将其开放给了所有的JavaScript开发者。

说到npm,就不得不提到cnpm。

在国内,很多人都会使用cnpm命令来安装npm服务器上的第三方包,因为cnpm的下载速度要比npm快。那么cnpm究竟是什么呢?

原来,npm服务器位于国外,我们在国内直接访问npm服务器的速度是相对较慢的,有时甚至会出现安装失败。为了解决这个问题,淘宝的工程师团队在国内也搭建了一个服务器,称为“淘宝npm镜像”(其实就是把npm服务器上的第三方包给同步过来,供开发者下载)。淘宝的npm镜像服务器地址是https://registry.npm.taobao.org,通过以下命令可以安装cnpm:

npm install -g cnpm -registry=https://registry.npm.taobao.org

现在你就已经安装了cnpm,你可以使用cnpm命令去淘宝的服务器上下载从npm服务器上同步过来的第三方模块。

注意:该服务器每10分钟与npm官方服务器同步一次。因此如果你刚刚向npm服务器上传了一个模块,使用cnpm命令不一定能立即下载。

补充说明:现在还有一个常用的包管理工具:yarn。由于在旧版本的npm中存在一些缺陷,比如npm install安装过慢、版本管理不统一等,Facebook、Google等互联网公司联合推出了新的包管理工具yarn。相比于npm,它速度更快,性能更好,备受互联网大厂欢迎。由于yarn与npm的原理是基本一致的,这里我们就不再详述,感兴趣的可以去了解一下。

二、向npm上传一个vue组件

这里我们以上传一个vue组件为例,来讲解向npm服务器上传第三方模块的全过程。

本文所要上传的是我编写的一个小的vue组件:vue-image-container。

它是一个可拖拽的悬浮窗,内置了若干个格子,你可以将页面上的某些图片拖拽进去临时存储起来,之后可以把图片拖拽出来放置到目标位置(目前只完成了一个概念版本,功能并不健全,后续会进一步完善)。如图:
在这里插入图片描述
当你需要把某张图片拖拽到当前可视区之外(比如你要从网页顶部将一张图片拖拽到底部,而网页却非常长),或者当你从一个页面路由到另一个页面时需要拖拽一张图片过去(单页应用的路由切换不会跨页面,因此理论上是可以跨路由拖拽图片的),你可能就需要这样一个组件了。

好了,简单介绍了要上传的组件之后,下面就是本文的重点:如何向npm服务器上传这个组件。这主要分两大部分,其一是完成组件的开发,向npm上传的模块必须遵循一定的格式,其二是向npm上传该模块。

先来看组件的开发:

1. 创建一个vue项目

我们先使用vue-cli创建一个vue项目(当然,在这之前你需要先安装nodejs和vue-cli,它们的安装不是本文的重点)。在当前文件夹下打开cmd命令行窗口,输入以下命令:

vue create vue-image-container

选择项目的默认配置,回车执行。执行完毕后,当前文件夹下就会出现一个刚刚初始化的空vue项目:vue-image-container。

由于新版的vue-cli删除了默认的配置文件,因此我们在项目下新建一个vue.config.js,此时项目结构如下:
在这里插入图片描述

2. 配置vue.config.js

接下来我们要配置一下项目的配置文件,代码如下:

module.exports = {
      pages: {
        index: {
          entry: 'src/main.js,
          template: 'public/index.html,
          filename: 'index.html
        }
      },
      css: {
        extract: false   //强制使用内联样式,这样打包出的插件样式会内置在js中,不需要单独引入
      }
    }

这里是标准的vue.config.js配置。

pages参数指定了项目的入口js文件和要使用的HTML模板。

css参数的extract属性指定在打包时是否要生成单独的样式文件。如果将extract置为true,则项目打包后会生成单独的css文件,在引入的时候就必须同时引入这个css文件才可以,如:
在这里插入图片描述
当你的组件有多个主题时,这样做会比较灵活。但如果你的组件只有一套样式,就可以将该参数置为false,此时所有的样式都会被打包成内联样式,开发者在使用的时候就不需要单独引入样式文件了。这里我们暂且只提供一个主题,因此将extract置为false。

3. 新建packages文件夹

一般来说,我们会在src目录下编写本地组件,然后在其他组件中进行调用。但是我们现在要编写的需要上传到npm的第三方组件,我们不希望它和项目的其他代码混在一起(这样不利于打包),因此我们将新建一个packages文件夹来存放这个组件。

此时项目结构如下:
在这里插入图片描述

4. 编写插件

我们先按照常规开发组件的方式开发好组件,这与直接在src下编写插件没有什么差别:
在这里插入图片描述

<template>
  ...  // 模板
</template>

<script>
  ...  // 脚本代码
</script>

<style>
  ...  // 样式
</style>

注意:我们不止可以向npm上传单个组件,也可以上传一个组件库,这时packages下面可能包含多个vue组件。

开发完插件后,在packages目录下新建index.js,作为组件的入口文件。
在这里插入图片描述

(1). 开发单个组件

如果只需要上传单个组件(如本项目),index.js代码如下:

// 导入组件
import imgContainer from './img-container/img-container'; 

let plugin = {};
plugin.install = function( Vue ){
    Vue.component(imgContainer.name, imgContainer); // 注册组件
}

// 当使用Vue.use(plugin)安装插件时,
// 实际上就是在调用这里暴露出的对象的
// install方法,因此务必确保这里带有install方法
export default plugin;    

组件的索引文件暴露出了一个plugin对象,该对象有一个install方法,当调用Vue.use()安装组件时,实际上就是在调用这个方法。因此你可以像下面这样使用imgContainer

本地项目:

// 引入组件暴露出的plugin对象
import imgContainer from 'img-container';

// 执行plugin的install方法
Vue.use(imgContainer);  

请注意,即使组件不是从npm下载的,你也可以调用Vue.use(),只要传入的对象有install方法。

(2). 开发组件库

如果你要上传一个组件库,可以像下面一样编写index.js

import ... from ''
import ... from '';
...   // 将所有的组件引入进来

const components = [...]; // 将上述组件保存到一个数组

// 定义install方法,它将作为export暴露的对象的方法被Vue.use调用
const install = function(Vue){
	// 判断当前组件是否已被安装过,如果已安装过则不再安装
    if(install.installed) return;  
    install.installed = true;
    
    // 遍历components数组,依次注册每个组件
    components.map(component => {
        Vue.component(component.name, component);
    }) 
}

if(typeof window !== 'undefined' && window.Vue){
    install(window.Vue);
}
export default{
    install,
    ...components    //将插件暴露出去,这样可以按需引入
} 
// 如果只需要部分组件,请使用import {button} from '';
// Vue.component(Button)的语法手动注册组件
// 这样便可以实现按需引入

项目中引入组件库的方式与引入单个组件是一致的。

5. 测试组件

编写完组件后,需要先进行测试,排除组件的bug后才能上传到npm服务器。我们仍然按照常规的方式,在src文件夹下编写项目代码,引入packages下面的组件进行测试(我们有时也会把src文件夹改为test,表示这是测试组件用的)。
在这里插入图片描述
App.vue:
在这里插入图片描述
与常规引入组件的方式是一致的,只是路径是packages文件夹。

6. 配置package.json

这一步是为测试和打包做准备,我们在原package.json的顶部添加如下代码:
package.json:

  "name": "vue-image-container",  // 组件名
  "version": "0.1.4",  // 版本号
  "description": "img-container",  // 组件描述
  "main": "lib/vue-img-container.umd.min",  // 打包结果文件
  "private": false,   // 是否为私有项目
  "author": "carter_liu",
  "license": "MIT",
  "style": "lib/vue-img-container.css",  // 打包后的样式文件
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "lib": "vue-cli-service build --target lib --name vue-img-container --dest lib packages/index.js"  // 打包命令
  },
  // 下面的配置都是自动生成的,不用动
  "dependencies": {
    ... 
  },
  "devDependencies": {
	... 
  },
  ...

这里需要特别注意的是,要将组件上传到npm上,private参数必须置为false

另外,如果之前配置vue.config.js时选择生成单独的css文件,则这里的style参数是必须的(否则会找不到样式文件),如果没有单独的css文件,这个参数可以省略。

这里最重要的是scripts内的lib命令,调用它可以将模块打包,只有打完包,才能上传到npm服务器。我们来分析一下各个参数的含义:

vue-cli-service build  // 调用vue-cli提供的build命令
--target lib // 打包目标是package.json同级目录下的lib文件夹(打包时会自动创建)
--name vue-img-container // 包名
--dest lib packages/index.js // 打包入口是packages文件夹下的index.js

7. 打包

在命令行输入:

npm run lib

然后回车即可进行组件打包。稍等片刻,lib文件夹下就会生成打包结果。这个lib就是我们真正要给开发者使用的包(理论上你可以只向npm上传这个文件夹,不过大多数情况下我们会把整个项目上传,便于其他开发者学习和研究)。

8. 配置.npmignore文件

在项目根目录下新建.npmignore文件:
在这里插入图片描述
这个文件里约定了哪些文件夹是不需要上传到npm服务器上的。一般来说,node_modules文件夹,以及项目的工程文件(如.idea,.vscode)等是不上传的,而lib文件夹是必须要上传的,其他的可以根据需要。

下面是我的配置文件:

    node_modules/
    vue.config.js
    babel.config.js
    *.map
    *.html

    .idea
    .vscode

上述文件或文件夹将不会被上传到npm。

至此,我们的组件已经开发和打包完毕,可以准备上传到npm了。要上传到npm,首先需要有一个npm账号。

9. 注册npm账号

登录网址:https://www.npmjs.com,可以免费注册一个开发者账号。注册完毕后需要验证邮箱,没有验证邮箱是不能上传模块的。

提示:我用手机端验证了邮箱,发现上传时仍显示未验证邮箱,后来在电脑端验证邮箱才可以正常使用,不知道是不是操作失误。

10. 登录npm账号

回到项目文件夹,打开命令行窗口,输入:

npm login

随后需要依次输入用户名、密码(密码是隐藏的,输完直接回车即可)和邮箱。

输入完成,回车即可登录npm账号。

11. 发布组件

现在我们可以将组件发布到npm服务器上了。执行命令:

npm publish

回车,稍等一会,组件就会被上传到npm服务器上了。

如果你在执行该命令时遇到以下报错:

403 Forbidden - PUT https://registry.npm.taobao.org/vue-image-container - [no_perms] Private mode enable, only ad
      npm ERR! 403 In most cases, you or one of your dependencies are requesting
      npm ERR! 403 a package version that is forbidden by your security policy.

这是因为使用了淘宝的镜像服务器(淘宝镜像服务器在上传模块时可能存在一定的权限问题),你可以输入以下命令:

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

将上传的服务器地址重置为官方的服务器地址,然后重新执行npm loginnpm publish,即可成功上传。

关于组件的更新:如果你需要升级该组件,需要先去package.json文件中修改项目的版本号,然后再次执行npm publish。切记,如果没有修改版本号,npm服务器上包是不会更新的。

此外,npm unpublish ...命令用于撤销已上传的模块。

三、总结

本文以一个简单的vue组件为例,讲解了如何开发和上传一个第三方组件到npm服务器。鉴于封装组件(俗称“造轮子”)已经称为一个前端开发者最重要的技能之一,没有尝试过的同学还是尽快尝试一下。

发布了44 篇原创文章 · 获赞 98 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_41694291/article/details/104328725