日常开发中经常用到一些插件、组件,通常开发中大家都是放到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.json的include里添加此配置,用来避免引入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.json的name属性时最好先去npm查一下名字是否已经存在了,此时只要修改名字再发布即可。
6.3、发布报错:You cannot publish over the previously published versions: xxx.
这个错误是因为之前已经发布了,现在又重新推送同样版本号的包,所以如果有修改更新的话,一定要修改版本包后再进行发布。
6.4、npm包删除
npm包上传完成之后,只有在72小时之内可以删除,超过之后便无法删除.
以上就是一个特别基础的npm组件库的开发流程,涉及到后续的操作,比如关联git。组件文档、样式分离等内容,感兴趣的小伙伴可以研究下,本文只是抛砖引玉提供一个整体思路和流程,希望能帮到有需要的小伙伴~