使用npm打造自己的vue組件庫

背景說明

最近公司要將項(xiàng)目用的組件整合成一個npm庫藤违,像使用mint-ui一樣引用,于是借這個機(jī)會學(xué)習(xí)了一下议街,實(shí)現(xiàn)按需引用自己的vue組件庫璧榄。
參考鏈接:https://segmentfault.com/a/1190000015884948#articleHeader1

目標(biāo)

可以像mint-ui一樣按需引用組件骨杂,方便團(tuán)隊(duì)統(tǒng)一管理組件。

難點(diǎn)

webpack的入口蛤售、出口配置,以及組件的按需加載

原理

利用 babel-plugin-component 插件鳄炉,來實(shí)現(xiàn)按需加載搜骡。該插件需要的是 這樣一個文件結(jié)構(gòu)


image.png

實(shí)現(xiàn)過程

  • vue-cli 搭建基礎(chǔ)項(xiàng)目记靡。

vue init webpack adms-plugin

因?yàn)楣窘M件依賴mint-ui,因此還需要install mint-ui以及使用iconfont空凸。

npm i mint-ui --save
image.png

項(xiàng)目是用vue-cli搭建的項(xiàng)目:
1呀洲、build中是webpack相關(guān)配置
2啼止、example目錄是開發(fā)時調(diào)試用
3献烦、src目錄中components中是各個功能模塊,各功能模塊的入口中同element一樣吏夯,對組件進(jìn)行擴(kuò)展即横,增加install方法,將組件進(jìn)行全局注冊杠园,index.js是入口舔庶,其中引入所有功能模塊惕橙,同時導(dǎo)出模塊和install方法,將所有模塊進(jìn)行注冊肚逸。
4、lib中是最終打包的目標(biāo)目錄膝晾,記錄將要打包的功能模塊名稱和路徑
5务冕、增加components.json文件

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

index文件為所有文件入口禀忆,可用于全局引用。

  • webpack相關(guān)配置更改

規(guī)劃中离熏,需要將各個模塊打包至lib戴涝,一個功能模塊為一個.js文件啥刻,并且在theme目錄中存在一個同名的.css文件,這樣使用時借助babel-plugin-component插件就可實(shí)現(xiàn)按需引入。還需要一個總的index.js包含所有的功能模塊蒲肋,和一個index.css包含所有的樣式兜粘。
這里采用多入口(entry)配置,實(shí)現(xiàn)各個功能模塊分別打包成一個.js文件剃法,并使用extract-text-webpack-plugin將樣式進(jìn)行抽離后路鹰,按入口chunk進(jìn)行打包為對應(yīng)的.css文件晋柱。
npm run build進(jìn)行將各個模塊打包為各自的.js文件,樣式文件也同時抽離處理為同名的.css
下面是webpeck相關(guān)具體修改:
E:\npm\adms-plugin\config\index.js


image.png

assetsRoot路徑改為lib

  • 下面詳細(xì)介紹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相關(guān)配置侥锦,這里只需打包為js文件和css文件德挣,不涉及html
2、引入components.json署照,根據(jù)配置的模塊及路徑配置入口entrys吗浩,配置完后懂扼,將入口寫入entry配置
3、ExtractTextPlugin插件是進(jìn)行css抽離的赶熟,這里不用處理
4陷嘴、ouput中,出口.js文件的名稱不能寫死
5邑退、在plugins插件配置處地技,ExtractTextPlugin相關(guān)配置秒拔,filename不能寫死,需要根據(jù)chunk名稱自動生成對應(yīng)名稱作谚。這里設(shè)置為'/theme/[name].css'指定目錄lib/theme存放
到此梯轻,webpack配置就差不多完成了喳挑。
npm run build打包完成后的目錄結(jié)構(gòu):


image.png
  • 配置package.json

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


image.png

private設(shè)置項(xiàng)目為公開,main設(shè)置項(xiàng)目入口地址

打包發(fā)布

npm login //登錄npm 
npm publish //發(fā)布包 

截止到目前為止回官,vue組件成功發(fā)布到npm搂橙。
此處需要將 將淘寶鏡像 還原区转。否則 發(fā)布、安裝 都出問題侄泽。

// 查詢當(dāng)前配置的鏡像 npm get registry //https://registry.npmjs.org/ 
// 設(shè)置成淘寶鏡像 npm config set registry http://registry.npm.taobao.org/
// 換成原來的 npm config set registry https://registry.npmjs.org/

另外蜻韭,每次發(fā)布 需要 修改 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
      }
    }
  ]],

其中l(wèi)ibraryName為自己的庫名吨岭,name為樣式文件辣辫,base為是否使用引用base.css文件。

遇到的難點(diǎn)

  • 多個組件引用base.css文件
    使用babel-plugin-component會引用base.css,難點(diǎn)主要是 base.css 文件的生成姐浮,由于 webpack 無法單獨(dú)生成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也加載了進(jìn)來

  • 打包時需要注意名稱命名需要使用kebab-case (短橫線分隔命名)格式集晚,例如:button-model,在components.json配置中区匣,需要使用短橫線分隔命名亏钩。

總結(jié)

構(gòu)建vue項(xiàng)目庫難點(diǎn)主要創(chuàng)建webpack入口,以及base.css文件的引入蛤签,同時使用時候記得配合babel-plugin-component插件按需加載彻坛,希望這篇文章能幫助有需要的同學(xué)們。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市间驮,隨后出現(xiàn)的幾起案子竞帽,更是在濱河造成了極大的恐慌,老刑警劉巖疙渣,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妄荔,死亡現(xiàn)場離奇詭異谍肤,居然都是意外死亡荒揣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門恳蹲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阱缓,“玉大人,你說我怎么就攤上這事敞嗡『奖常” “怎么了玖媚?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長勺像。 經(jīng)常有香客問我错森,道長吟宦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任涩维,我火速辦了婚禮殃姓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瓦阐。我一直安慰自己蜗侈,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布睡蟋。 她就那樣靜靜地躺著踏幻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪戳杀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天豺瘤,我揣著相機(jī)與錄音,去河邊找鬼听诸。 笑死坐求,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晌梨。 我是一名探鬼主播桥嗤,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼须妻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泛领?” 一聲冷哼從身側(cè)響起荒吏,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎渊鞋,沒想到半個月后绰更,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锡宋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年儡湾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片执俩。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡徐钠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出役首,到底是詐尸還是另有隱情尝丐,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布衡奥,位于F島的核電站爹袁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏杰赛。R本人自食惡果不足惜呢簸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乏屯。 院中可真熱鬧根时,春花似錦、人聲如沸辰晕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽含友。三九已至替裆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窘问,已是汗流浹背辆童。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惠赫,地道東北人把鉴。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庭砍。 傳聞我的和親對象是個殘疾皇子场晶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容