使用npm打造自己的vue组件库

背景说明

最近公司要将项目用的组件整合成一个npm库,像使用mint-ui一样引用,于是借这个机会学习了一下,实现按需引用自己的vue组件库。
参考链接:https://segmentfault.com/a/1190000015884948#articleHeader1

目标

可以像mint-ui一样按需引用组件,方便团队统一管理组件。

难点

webpack的入口、出口配置,以及组件的按需加载

原理

利用 babel-plugin-component 插件,来实现按需加载。该插件需要的是 这样一个文件结构


image.png

实现过程

  • vue-cli 搭建基础项目。

vue init webpack adms-plugin

因为公司组件依赖mint-ui,因此还需要install mint-ui以及使用iconfont。

npm i mint-ui --save
image.png

项目是用vue-cli搭建的项目:
1、build中是webpack相关配置
2、example目录是开发时调试用
3、src目录中components中是各个功能模块,各功能模块的入口中同element一样,对组件进行扩展,增加install方法,将组件进行全局注册,index.js是入口,其中引入所有功能模块,同时导出模块和install方法,将所有模块进行注册。
4、lib中是最终打包的目标目录,记录将要打包的功能模块名称和路径
5、增加components.json文件

{
    "Datepopup":"./src/components/Datepopup",
    "index":"./src/index"
}

index文件为所有文件入口,可用于全局引用。

  • webpack相关配置更改

规划中,需要将各个模块打包至lib,一个功能模块为一个.js文件,并且在theme目录中存在一个同名的.css文件,这样使用时借助babel-plugin-component插件就可实现按需引入。还需要一个总的index.js包含所有的功能模块,和一个index.css包含所有的样式。
这里采用多入口(entry)配置,实现各个功能模块分别打包成一个.js文件,并使用extract-text-webpack-plugin将样式进行抽离后,按入口chunk进行打包为对应的.css文件。
npm run build进行将各个模块打包为各自的.js文件,样式文件也同时抽离处理为同名的.css
下面是webpeck相关具体修改:
E:\npm\adms-plugin\config\index.js


image.png

assetsRoot路径改为lib

  • 下面详细介绍webpack.prod.conf

E:\npm\adms-plugin\build\webpack.prod.conf.js

'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
// 整理入口
const components = require('../components.json')
const entrys = {}
Object.keys(components).forEach(item => {
  entrys[item] = components[item]
})
const webpackConfig = merge(baseWebpackConfig, {
  entry: entrys,
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  },
  devtool: config.build.productionSourceMap ? config.build.devtool : false,
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    library: 'VueDropUpload',
    libraryTarget: 'umd'
  },
  externals: {
    vue: {
      root: 'Vue',
      commonjs: 'vue',
      commonjs2: 'vue',
      amd: 'vue'
    }
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: false
        }
      },
      sourceMap: config.build.productionSourceMap,
      parallel: true
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: '/theme/[name].css'
    })
  ]
})

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

1、删除HtmlWebpackPlugin相关配置,这里只需打包为js文件和css文件,不涉及html
2、引入components.json,根据配置的模块及路径配置入口entrys,配置完后,将入口写入entry配置
3、ExtractTextPlugin插件是进行css抽离的,这里不用处理
4、ouput中,出口.js文件的名称不能写死
5、在plugins插件配置处,ExtractTextPlugin相关配置,filename不能写死,需要根据chunk名称自动生成对应名称。这里设置为'/theme/[name].css'指定目录lib/theme存放
到此,webpack配置就差不多完成了。
npm run build打包完成后的目录结构:


image.png
  • 配置package.json

E:\npm\adms-plugin\package.json


image.png

private设置项目为公开,main设置项目入口地址

打包发布

npm login //登录npm 
npm publish //发布包 

截止到目前为止,vue组件成功发布到npm。
此处需要将 将淘宝镜像 还原。否则 发布、安装 都出问题。

// 查询当前配置的镜像 npm get registry //https://registry.npmjs.org/ 
// 设置成淘宝镜像 npm config set registry http://registry.npm.taobao.org/
// 换成原来的 npm config set registry https://registry.npmjs.org/

另外,每次发布 需要 修改 package.json 里的 version。
还需要注意是否包名(package.json 里的 name)冲突,npm 平台已存在的话 不让上传。

引入使用

接下来大家就可以开心的使用自己的npm库了,

import {Datepopup} from 'adms-plugin'
Vue.use(Datepopup)

这里需要使用babel-plugin-component插件,并且配置

npm i babel-plugin-component -D

E:\npm\hello-world\demo.babelrc文件

"plugins": ["transform-vue-jsx", "transform-runtime",[
    "component",{
      "libraryName": "adms-plugin",
      "styleLibrary": {
        "name": "theme",
        "base":true
      }
    }
  ]],

其中libraryName为自己的库名,name为样式文件,base为是否使用引用base.css文件。

遇到的难点

  • 多个组件引用base.css文件
    使用babel-plugin-component会引用base.css,难点主要是 base.css 文件的生成,由于 webpack 无法单独生成css文件(要依赖js)。这里 我新建了一个 base.js 文件,也作为了一个 webpack 的入口文件
    因此我新建了一个base.js
import './assets/css/base.css'
import './assets/font/iconfont.css'

并且修改components.json文件:

{
    "Datepopup":"./src/components/Datepopup",
    "index":"./src/index",
    "base":"./src/base"
}

这样就可以生成base.css,同时依赖的iconfont也加载了进来

  • 打包时需要注意名称命名需要使用kebab-case (短横线分隔命名)格式,例如:button-model,在components.json配置中,需要使用短横线分隔命名。

总结

构建vue项目库难点主要创建webpack入口,以及base.css文件的引入,同时使用时候记得配合babel-plugin-component插件按需加载,希望这篇文章能帮助有需要的同学们。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容