前端npm组件库开发基本流程

2,043 阅读5分钟

日常开发中经常用到一些插件、组件,通常开发中大家都是放到components文件夹里,有新项目的时候会在copy一份出来。其实完全可以通过npm的方式进行安装引用,对于日常中我们常用的一些方法和组件,可以进行封装发布到npm,方便日常开发使用。

本文以vue为例,简单梳理一下开发一个组件,并发布到npm的整个流程,以及对遇到的一些问题的整理。

一、注册npm账号

发布npm包最基础的一步,没有账号的可以自行注册 (www.npmjs.com/) ,注册完成需要记住账号密码和邮箱,因为在后续发布时会用到。

二、组件开发及发布(vue为例)

1、创建vue项目

  ① 、npm create vite,输入项目名字

  ②、选择vue、ts

  ③、进入目录执行 npm i 安装依赖

2、修改项目

①、创建一个env.d.ts的文件,在里边输入下列内容并保存,并在tsconfig.jsoninclude里添加此配置,用来避免引入vue时报ts错误。

// env.d.ts
declare module "*.vue" {
  import { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

declare module Window {
  Vue: any
}

// tsconfig.json
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "./*.d.ts"],

②、新建文件夹package,用于存放开发的组件

③、将src文件夹修改为example,用于自测。此处如果修改,也需要将index.html文件里main.ts的引用路径同步修改为example

3、组件开发

上边创建的package文件夹用来存放组件;该文件夹下包含各个单独的各个组件文件夹和一个index.ts文件用于整体导出;同时,各个单独组件文件夹内包括src文件夹用于存放组件和一个index.ts文件用于单独注册各个组件。

此处以button为例,看下具体开发步骤:

a.button/index.vue文件,就是日常的组件开发:

 <template>
   <button class="default-btn" :class="className">{{ text }}</button>
 </template>

 <script setup>
 const props = defineProps({
   text: {
     type: String,
     default: '确认'
   },
   className: {
     type: String,
     default: ''
   },
 })
 </script>

 <style lang="scss" scoped>
 .default-btn {
   background-color: #1188ff;
   color: white;
   border: none;
   padding: 6px 12px;
 }
 </style>
 

b、button/index.ts文件,进行单独组件注册和导出:

  // 导出button组件
  import MyButton from './src/index.vue'

  // 定义name,局部install和全局install时才能准确匹配
  MyButton.name = 'my-button'

  // 添加组件的install属性,用于按需引入
  MyButton.install = function (Vue: any) {
    Vue.component(MyButton.name, MyButton)
  }

  export default MyButton

c、package/index.ts文件,进行所有组件的全局注册和导出:

 // 全局注册组件
 import MyButton from './button/index'
 import MyLineText from './lineText/index'

 // 数组存放所有组件,便于遍历
 const components = [
   MyButton,
   MyLineText
 ]

 // 用于单独按需引入
 export { 
   MyButton,
   MyLineText
 }

 const install = function (Vue: any) {
   if ((install as any).installed) return;
   components.map(component => Vue.component(component.name, component))
 }

 // 全局注册
 if(window.Vue && typeof window !== 'undefined'){
   install(window.Vue)
 }

 // 用于全局引入
 export default {
   install
 }

4、组件本地测试

组件开发完成,可以进行本地测试,分别测试下整体引入和按需引入。

  • 整体引入:在example/main.ts里引入整体的导出文件,在其他页面中,就可以直接使用组件。
  // main.ts
  import { createApp } from 'vue'
  import './style.css'
  import App from './App.vue'
  import myUi from '../package/index'

  const app = createApp(App)
  app.use(myUi)
  app.mount('#app')
   // app.vue
   <template>
     <div>
       <my-button :text="'这是一个按钮'" :className="'test-btn'"></my-button>
     </div>
   </template>

   <script setup lang="ts">
   </script>
   <style lang="scss">
   .test-btn{
     background-color: red;
     color: white;
   }
   </style>
  • 按需引入:在单个页面中只单独引入某个组件调用
  <template>
    <div>
      < my-lineText  :msg = "'这是一个文本'" ></ my-lineText >
    </div>
  </template>

  <script setup lang="ts">
  import MyLineText from '../package/lineText/index'
  </script>
  <style lang="scss">
  </style>

5、组件发布

5.1、package.json配置

   发布前需要配置package.json文件中的几个必要的字段:

  • name:包的名字,必须是唯一的,可以先去npm查一下名字是否存在;
  • version:包的版本,修改时不能和历史版本号一致;
  • files:需要发布的文件;
  • main:入口文件,默认为index.js,可以根据自己情况修改,此处设置为 dist/my-component.umd.js
  • module:模块入口,此处设置为dist/my-component.es.js

   package.json 配置完成后如下:

{
  "name": "my-component-single",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "files": [
    "dist/*"
  ],
  "main": "dist/my-component.umd.js",
  "module": "dist/my-component.es.js",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.4.21"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.4",
    "sass": "^1.75.0",
    "typescript": "^5.2.2",
    "vite": "^5.2.0",
    "vue-tsc": "^2.0.6"
  }
}

5.2、vite.config.ts配置,主要是配置rollup打包、输出相关命令

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  build: {
    // 配置rollup打包信息
    rollipOptions: {
      // 指定某些模块不被打包,由应用时的环境提供
      external: ['vue'],
      output: {
        globals: {
          // 为环境提供的模块指定一个全局变量
          vue: 'Vue'
        }
      }
    },
    lib: {
      entry: 'package/index.ts',
      // 暴露的全局名字
      name: 'my-component',
      // 输出的各种包文件
      fileName: (format) => `my-component.${format}.js`
    }
  }
})

5.3、执行npm run build,可以看到打包出dist文件

5.4、发布前确认源是否是npm

通过 npm config get registry 查看;如果不是npm源,可以通过 npm config set registry xxx 去修改。

然后通过npm login 进行登录,就是第一步注册的npm账号,需要输入账号、密码、邮箱,以及邮箱收到的的二次验证码。

最后通过 npm publish 上传。

5.5、安装包并验证

组件上传完成后,可以自行安装测试,通过npm instatll xxx安装包,然后在main.js里引入,并在组件内使用,可以看到可以成功安装并使用。

// main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import MyComponentSingle from 'my-component-single'
import 'my-component-single/dist/style.css'

const app = createApp(App)
app.use(MyComponentSingle)
app.mount('#app')

// component.vue
<template>
  <my-lineText :msg="'这是一个文本'"></my-lineText>
  <my-button :text="'这是一个按钮'" :className="'test-btn'"></my-button>
</template>

<script setup>
</script>

<style>
.test-btn{
  background-color: red;
  color: white;
}
</style>

6、组件发布问题及注意点

6.1、发布提示:This package has been marked as private

提示这个错误是因为在package.json文件里,有一个private属性默认为true,会阻止私有包发布到npm,需要将其属性修改为false即可。

6.2、发布报错:In most cases, you or one of your dependencies are requesting npm ERR! 403 a package version that is forbidden by your security policy, or npm ERR! 403 on a server you do not have access to.

这个错误就是因为发布的组件名字已经存在了,在配置package.jsonname属性时最好先去npm查一下名字是否已经存在了,此时只要修改名字再发布即可。

6.3、发布报错:You cannot publish over the previously published versions: xxx.

这个错误是因为之前已经发布了,现在又重新推送同样版本号的包,所以如果有修改更新的话,一定要修改版本包后再进行发布。

6.4、npm包删除

npm包上传完成之后,只有在72小时之内可以删除,超过之后便无法删除.

以上就是一个特别基础的npm组件库的开发流程,涉及到后续的操作,比如关联git。组件文档、样式分离等内容,感兴趣的小伙伴可以研究下,本文只是抛砖引玉提供一个整体思路和流程,希望能帮到有需要的小伙伴~