开发过程中,我们经常自己二次封装UI组件,或者自己封装一些方便开发的插件,为了方便团队成员也可以使用我们封装的插件,可以将插件单独打包成npm包,并在项目的package.json中配置好插件的信息,这样,在项目npm install安装依赖的时候,就可以将插件顺便安装下来,并引用。
以下是我在开发过程中,二次封装element-plus,并单独打包成npm包引用的示例。
1、将element plus的源码从git上拉取下来,git地址:GitHub - element-plus/element-plus: A Vue.js 3 UI Library made by Element team
2、根据自己项目需求修改或者二次封装UI组件(此处不做详细介绍);
3、将修改好的element plus项目进行打包,npm run build(element plus是基于pnpm打包的,如果本地未安装 pnpm,需安装pnpm,地址:安装 | pnpm中文文档 | pnpm中文网);
4、打包完成后,会在根目录下生成dist文件,结构如下图:
5、完成打包后,我们就要进行下一步操作,cd进入打包好的dist文件夹下的element-plus*,将其打成npm压缩包,在此之前我们需要进行一些配置。
要npm init生成一个package.json。并更新必要字段,下面是详细代码(需注意配置顺序):
{
"name": "element-plus-example", //这里需要写和element-plus不一样的名字,防止冲突
"version": "2.3.9", //版本号
"description": "A Component Library for Vue 3", //介绍
"keywords": [
"element-plus",
"element",
"component library",
"ui framework",
"ui",
"vue"
],
"homepage": "https://element-plus.org/",
"bugs": {
"url": "https://github.com/element-plus/element-plus/issues"
},
"license": "MIT",
"main": "lib/index.js", //入口文件
"module": "es/index.mjs",
"types": "es/index.d.ts",
"exports": {
".": {
"types": "./es/index.d.ts",
"import": "./es/index.mjs",
"require": "./lib/index.js"
},
"./es": {
"types": "./es/index.d.ts",
"import": "./es/index.mjs"
},
"./lib": {
"types": "./lib/index.d.ts",
"require": "./lib/index.js"
},
"./es/*.mjs": {
"types": "./es/*.d.ts",
"import": "./es/*.mjs"
},
"./es/*": {
"types": [
"./es/*.d.ts",
"./es/*/index.d.ts"
],
"import": "./es/*.mjs"
},
"./lib/*.js": {
"types": "./lib/*.d.ts",
"require": "./lib/*.js"
},
"./lib/*": {
"types": [
"./lib/*.d.ts",
"./lib/*/index.d.ts"
],
"require": "./lib/*.js"
},
"./*": "./*"
},
"unpkg": "dist/index.full.js",
"jsdelivr": "dist/index.full.js",
"repository": {
"type": "git",
"url": "git+https://github.com/element-plus/element-plus.git"
},
"publishConfig": {
"access": "public"
},
"style": "dist/index.css",
"sideEffects": [
"dist/*",
"theme-chalk/**/*.css",
"theme-chalk/src/**/*.scss",
"es/components/*/style/*",
"lib/components/*/style/*"
],
"peerDependencies": {
"vue": "^3.2.0"
},
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.0.6",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182",
"@types/lodash-es": "^4.17.6",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.3",
"escape-html": "^1.0.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.2",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
},
"devDependencies": {
"@types/node": "*",
"csstype": "^2.6.20",
"vue": "^3.2.37",
"vue-router": "^4.0.16"
},
"vetur": {
"tags": "tags.json",
"attributes": "attributes.json"
},
"web-types": "web-types.json",
"browserslist": [
"> 1%",
"not ie 11",
"not op_mini all"
],
"gitHead": "8b083b454e966f4812852992b9c618e0ba68c8f5"
}
配置global.d.ts文件,它用于定义全局变量、全局类型和全局模块,以便在整个项目中使用。 下面是详细代码:
// GlobalComponents for Volar
declare module '@vue/runtime-core' {
export interface GlobalComponents {
ElAffix: typeof import('element-plus')['ElAffix']
ElAlert: typeof import('element-plus')['ElAlert']
ElAside: typeof import('element-plus')['ElAside']
ElAutocomplete: typeof import('element-plus')['ElAutocomplete']
ElAvatar: typeof import('element-plus')['ElAvatar']
ElBacktop: typeof import('element-plus')['ElBacktop']
ElBadge: typeof import('element-plus')['ElBadge']
ElBreadcrumb: typeof import('element-plus')['ElBreadcrumb']
ElBreadcrumbItem: typeof import('element-plus')['ElBreadcrumbItem']
ElButton: typeof import('element-plus')['ElButton']
ElButtonGroup: typeof import('element-plus')['ElButtonGroup']
ElCalendar: typeof import('element-plus')['ElCalendar']
ElCard: typeof import('element-plus')['ElCard']
ElCarousel: typeof import('element-plus')['ElCarousel']
ElCarouselItem: typeof import('element-plus')['ElCarouselItem']
ElCascader: typeof import('element-plus')['ElCascader']
ElCascaderPanel: typeof import('element-plus')['ElCascaderPanel']
ElCheckbox: typeof import('element-plus')['ElCheckbox']
ElCheckboxButton: typeof import('element-plus')['ElCheckboxButton']
ElCheckboxGroup: typeof import('element-plus')['ElCheckboxGroup']
ElCol: typeof import('element-plus')['ElCol']
ElCollapse: typeof import('element-plus')['ElCollapse']
ElCollapseItem: typeof import('element-plus')['ElCollapseItem']
ElCollapseTransition: typeof import('element-plus')['ElCollapseTransition']
ElColorPicker: typeof import('element-plus')['ElColorPicker']
ElContainer: typeof import('element-plus')['ElContainer']
ElConfigProvider: typeof import('element-plus')['ElConfigProvider']
ElDatePicker: typeof import('element-plus')['ElDatePicker']
ElDialog: typeof import('element-plus')['ElDialog']
ElDivider: typeof import('element-plus')['ElDivider']
ElDrawer: typeof import('element-plus')['ElDrawer']
ElDropdown: typeof import('element-plus')['ElDropdown']
ElDropdownItem: typeof import('element-plus')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus')['ElDropdownMenu']
ElEmpty: typeof import('element-plus')['ElEmpty']
ElFooter: typeof import('element-plus')['ElFooter']
ElForm: typeof import('element-plus')['ElForm']
ElFormItem: typeof import('element-plus')['ElFormItem']
ElHeader: typeof import('element-plus')['ElHeader']
ElIcon: typeof import('element-plus')['ElIcon']
ElImage: typeof import('element-plus')['ElImage']
ElImageViewer: typeof import('element-plus')['ElImageViewer']
ElInput: typeof import('element-plus')['ElInput']
ElInputNumber: typeof import('element-plus')['ElInputNumber']
ElLink: typeof import('element-plus')['ElLink']
ElMain: typeof import('element-plus')['ElMain']
ElMenu: typeof import('element-plus')['ElMenu']
ElMenuItem: typeof import('element-plus')['ElMenuItem']
ElMenuItemGroup: typeof import('element-plus')['ElMenuItemGroup']
ElOption: typeof import('element-plus')['ElOption']
ElOptionGroup: typeof import('element-plus')['ElOptionGroup']
ElPageHeader: typeof import('element-plus')['ElPageHeader']
ElPagination: typeof import('element-plus')['ElPagination']
ElPopconfirm: typeof import('element-plus')['ElPopconfirm']
ElPopper: typeof import('element-plus')['ElPopper']
ElPopover: typeof import('element-plus')['ElPopover']
ElProgress: typeof import('element-plus')['ElProgress']
ElRadio: typeof import('element-plus')['ElRadio']
ElRadioButton: typeof import('element-plus')['ElRadioButton']
ElRadioGroup: typeof import('element-plus')['ElRadioGroup']
ElRate: typeof import('element-plus')['ElRate']
ElRow: typeof import('element-plus')['ElRow']
ElScrollbar: typeof import('element-plus')['ElScrollbar']
ElSelect: typeof import('element-plus')['ElSelect']
ElSlider: typeof import('element-plus')['ElSlider']
ElStep: typeof import('element-plus')['ElStep']
ElSteps: typeof import('element-plus')['ElSteps']
ElSubMenu: typeof import('element-plus')['ElSubMenu']
ElSwitch: typeof import('element-plus')['ElSwitch']
ElTabPane: typeof import('element-plus')['ElTabPane']
ElTable: typeof import('element-plus')['ElTable']
ElTableColumn: typeof import('element-plus')['ElTableColumn']
ElTabs: typeof import('element-plus')['ElTabs']
ElTag: typeof import('element-plus')['ElTag']
ElText: typeof import('element-plus')['ElText']
ElTimePicker: typeof import('element-plus')['ElTimePicker']
ElTimeSelect: typeof import('element-plus')['ElTimeSelect']
ElTimeline: typeof import('element-plus')['ElTimeline']
ElTimelineItem: typeof import('element-plus')['ElTimelineItem']
ElTooltip: typeof import('element-plus')['ElTooltip']
ElTransfer: typeof import('element-plus')['ElTransfer']
ElTree: typeof import('element-plus')['ElTree']
ElTreeV2: typeof import('element-plus')['ElTreeV2']
ElTreeSelect: typeof import('element-plus')['ElTreeSelect']
ElUpload: typeof import('element-plus')['ElUpload']
ElSpace: typeof import('element-plus')['ElSpace']
ElSkeleton: typeof import('element-plus')['ElSkeleton']
ElSkeletonItem: typeof import('element-plus')['ElSkeletonItem']
ElStatistic: typeof import('element-plus')['ElStatistic']
ElCheckTag: typeof import('element-plus')['ElCheckTag']
ElDescriptions: typeof import('element-plus')['ElDescriptions']
ElDescriptionsItem: typeof import('element-plus')['ElDescriptionsItem']
ElResult: typeof import('element-plus')['ElResult']
ElSelectV2: typeof import('element-plus')['ElSelectV2']
}
interface ComponentCustomProperties {
$message: typeof import('element-plus')['ElMessage']
$notify: typeof import('element-plus')['ElNotification']
$msgbox: typeof import('element-plus')['ElMessageBox']
$messageBox: typeof import('element-plus')['ElMessageBox']
$alert: typeof import('element-plus')['ElMessageBox']['alert']
$confirm: typeof import('element-plus')['ElMessageBox']['confirm']
$prompt: typeof import('element-plus')['ElMessageBox']['prompt']
$loading: typeof import('element-plus')['ElLoadingService']
}
}
export {}
6、加上上面两个文件之后,用命令:npm pack进行压缩,会生成一个名称为 package.json中名称+版本号的压缩包,dist目录变为下图:
7、这时我们可以直接将生成的npm包(压缩包)上传到npm(这个需要注册npm账号,并开通业务),或者上传到私有cnpm服务器(详细操作:cnpm 登录注册 发布 查看 更新等操作记录 - 简书),或者简单粗暴直接复制到项目的根目录,并在所用项目的package.json中配置依赖位置(详细操作:如何在项目中引用本地的npm包_海豹先生_的博客-CSDN博客)
这样就可以在项目下载依赖的时候,将插件的依赖包下载到项目中并使用。