一直以來,前端所作的事情比較重複和枯燥,確切的來講並無什麼太大的技術含量(僅從我這個初級前端角度來講)。特別是如今前端工程化帶來的各類工具的使用,前端開發愈來愈像搭積木。找到合適的模塊,按照UI圖進行拼裝,而後在這基礎上修修補補。具體表現之一就是UI組件庫的使用,餓了麼的UI庫很強大,常常被拿來「開箱即用」。這樣的確是提升了開發效率,可是居安思危來看,前端工程師存在的意義也大大下降了。css
知其然,更要知其因此然。 這句話是老話了,可是大多數人都作不到,包括我在內。正好公司此次項目大迭代,須要抽出一些公用的業務組件。趁此機會,個人思路是搭建一個公用的業務組件庫,並將其發佈到 NPM 上面。這樣子。不一樣的項目能夠直接引入 npm 包,作到組件的通用性。html
按照這個思路,網上找了很多文章,發現有着和我一樣想法的人真很多。基本都寫出了一個demo,可是缺點也有。那就是大部分都是我的實踐,並非工做須要,因此一些細節方面並不嚴謹。這也是能夠理解的,畢竟不是工做上的任務,因此會隨意點。綜合這些前輩的實踐,我開始嘗試寫出一個業務組件庫。前端
在此以前,我對於npm的理解就是一個node包管理工具,每次運行新項目都要首先npm install
安裝好相關依賴,而後npm run dev
運行。至於還有yarn
也只知道皮毛,相似於npm的包管理工具。聽說它比npm好用,下載速度快。除此以外,還有淘寶鏡像的修改。託管npm包的服務器在國外,若是不fq的話,安裝依賴會很慢很慢。出於這個痛點,淘寶在國內服務器上作了一個npm包的備份,每隔5分鐘(沒記錯的話)更新一下資源。這樣子,國外可使用cnpm代替npm,進行項目依賴的安裝,顯著提高了速度。vue
如今瞭解到了更多關於NPM的東西。首先NPM除了是包管理工具以外,它仍是有着本身的網站,負責包的服務器託管和對外宣傳。node
在官網的搜索框裏,能夠搜索npm現存的全部package,若是你發佈了本身的 npm 包,也能夠直接搜索出來。當你想要發佈本身的 npm 包時,你首先須要作的是註冊一個帳號,能夠拿經常使用的郵箱進行註冊,這裏要注意的是註冊帳號的 驗證郵件可能被郵箱當作垃圾郵件。 由於公司前端項目是基於 Vue 的,因此搭建的組件庫也是基於 Vue,因此要使用 vue-cli 來初始化項目。這裏首先就出了一個問題,那就是安裝 vue-cli。由於個人電腦以前沒有安裝 vue-cli,因此運行npm i -g @vue/cli
,安裝了最新的4.0.X版本。這裏要注意,4.0.x版本生成的項目結構和3.X.X版本有很大差異。webpack
// 安裝vue-cli
npm i -g @vue/cli
// 初始化項目
vue create xhx-ui
而後看本身喜歡選擇配置,幾下回車以後一個清爽的初始項目就行了
複製代碼
咱們在開發組件庫,是須要實時進行預覽的,不能等到發到npm上面再預覽。因此本地項目中須要提供開發樣例,測試組件的效果。將src
改成example
用來寫開發樣例,測試組件效果,而後在根目錄下新建一個packages
文件夾,用來放置編寫的業務組件。git
在修改了目錄結構以後,你會驚奇的發小項目運行不了了。不要緊,這很正常,畢竟 src
都不見了,路徑什麼的確定得報錯。因此咱們如今來解決這個問題。在根目錄下新建一個 vue.config.js
文件(新項目是沒有這個文件的),並寫入如下內容:github
const path = require('path')
module.exports = {
// 修改 pages 入口
pages: {
index: {
// 入口
entry: 'examples/main.js',
// 模板
template: 'public/index.html',
// 輸出文件
filename: 'index.html'
}
},
// 擴展 webpack 配置
chainWebpack: config => {
// @ 默認指向 src 目錄,這裏要改爲 examples
// 另外也可新增一個 ~ 指向 packages
config.resolve.alias
.set('@', path.resolve('examples'))
.set('~', path.resolve('packages'))
// 把 packages 和 examples 加入編譯,由於新增的文件默認是不被 webpack 處理的
config.module
.rule('js')
.include.add(/packages/).end()
.include.add(/examples/).end()
.use('babel')
.loader('babel-loader')
.tap(options => {
// 修改它的選項
return options
})
}
}
複製代碼
這個時候運行npm run serve
命令就能夠預覽效果了,會看到經典的 Welcome to Your Vue.js App。web
npm i node-sass sass-loader --save-dev
複製代碼
那麼如何在項目中使用呢?vue-cli
<style scoped lang='scss'>
</style>
複製代碼
本組件庫是用於移動端的,因此固然須要考慮到移動端的樣式適配。我看了目前主流的適配方案,最終選擇了 px轉vw 方案。選擇這個方案的理由是,能夠直接對照設計圖寫px,而不須要換算到 rem。另外,在移動端,vw的使用更適合保持不一樣尺寸屏幕的樣式統一。可是 vw 方案會有一個bug,當你使用圖片時,可能會出現部分手機瀏覽器中圖片消失的問題。解決問題也很簡單,在全局加入下面的 css 代碼。
img {
content: normal !important;
}
複製代碼
下面進行相關插件的安裝:
安裝成功以後,在項目根目錄下的package.json
文件中,能夠看到新安裝的依賴包:
postcss.config.js
文件,對新安裝的 postcss 插件進行配置:
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
"postcss-aspect-ratio-mini": {},
// to edit target browsers: use "browserslist" field in package.json
"postcss-write-svg": {
uft8: false
},
"postcss-cssnext": {},
"postcss-px-to-viewport-opt": {
viewportWidth: 750, // 設計稿寬度
// viewportHeight: 1230, // 設計稿高度,能夠不指定
unitPrecision: 3, // px to vw沒法整除時,保留幾位小數
viewportUnit: 'vw', // 轉換成vw單位
selectorBlackList: ['.ignore', '.hairlines','.vux-number-selector-plus','.vux-number-selector-sub'], // 不轉換的類名
minPixelValue: 1, // 小於1px不轉換
mediaQuery: false, // 容許媒體查詢中轉換
exclude: /(\/|\\)(node_modules)(\/|\\)/,
keepComment: 'no'
},
"postcss-viewport-units": {},
"cssnano": {
preset: "advanced",
autoprefixer: false, // 和cssnext一樣具備autoprefixer,保留一個
"postcss-zindex": false,
reduceIdents: false , // 解決了 animation-name 被重寫的 bug https://github.com/cssnano/cssnano/issues/247
}
}
}
複製代碼
特別聲明:因爲cssnext
和cssnano
都具備autoprefixer
,事實上只須要一個,因此把默認的autoprefixer
刪除掉,而後把cssnano
中的autoprefixer
設置爲false
。 因爲配置文件修改了,因此從新跑一下npm run serve
。項目就能夠正常看到了。
通常來講,組件指的是基礎 UI 組件和業務組件。前者就是相似於餓了麼UI同樣,封裝好了一些相似 Button 等經常使用的基礎組件。此次我寫的組件就沒有這麼難了,就是業務組件:如優惠券組件、問答組件等等。
在新建的packages
文件夾中新建index.js
,這個會在後面的全局引入中用到,接着新建一個Test
文件夾用來存放test
組件,其中 Test
裏面的index.js
是爲後面按需加載準備的(暫時忽略)。文件目錄以下:
packages
下面的
index.js
文件代碼以下:
// 引入編寫的組件
import Test from './test'
// 全部組件列表
const components = [
Test
]
// 定義 install 方法,接收 Vue 做爲參數
const install = function(Vue) {
// 判斷是否安裝,安裝過就不繼續往下執行
if (install.installed) return;
install.installed = true;
// 遍歷註冊全部組件
components.map(component => Vue.component(component.name, component));
// 下面這個寫法也能夠
// components.map(component => Vue.use(component))
};
// 檢測到 Vue 才執行,畢竟咱們是基於 Vue 的
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export default {
install,
// 全部組件,必須具備 install,才能使用 Vue.use()
...components
};
複製代碼
這個文件的做用就是引入編寫的各個小組件,統一註冊對外暴露。
咱們在開發自定義的組件的時候,不免會遇到一些問題,因此一個完整的本地調試是頗有必要的。不然發佈到npm上再改來改去,形成了不少無效的版本的浪費。前面已經說了咱們將最開始的src
文件夾重命名爲example
,這個文件夾裏就是本地調試組件的代碼。
這裏的代碼就是咱們通常的Vue文件裏面的src源碼文件夾,只須要將咱們開發的組件當成是本地組件,引入使用便可。首先在main.js文件中引入組件,並註冊組件:
import Vue from 'vue'
import App from './App.vue'
import XhxUI from '../packages'
Vue.config.productionTip = false
// 註冊組件庫
Vue.use(XhxUI)
new Vue({
render: h => h(App),
}).$mount('#app')
複製代碼
而後就正常使用組件。
組件發佈到npm上以前,須要進行打包。在 vue-cli4 中咱們經過如下命令能夠將一個單獨的入口打包成一個庫:
// target: 默認爲構建應用,改成 lib 便可啓用構建庫模式
// name: 輸出文件名
// dest: 輸出目錄,默認爲 dist,這裏咱們改成 lib
// entry: 入口文件路徑
vue-cli-service build --target lib --name lib [entry]
複製代碼
要注意的是在庫模式中,打包出來的庫中是不包含 Vue 的。 而後咱們修改一下 package.json 文件,就像下面這樣:
接着執行 npm run lib 就能生成庫啦,看看左側的目錄是否是多了個 lib 文件夾,那個就是咱們要發佈的東西。 補充下,lib 目錄下面的 js 之因此有好幾種,是由於有兩種規範(common 和 umd)、是否壓縮(min)和映射(map)的區別,暫且知道有這麼回事就行,不用深究。萬事俱備,就差發布了。先修改一下 package.json 文件:
{
"name": "xr-ui",
"version": "0.3.0",
"description": "基於 vue-cli4 的 UI 組件庫",
"main": "lib/xr-ui.umd.min.js", // 這是 lib 目錄下的其中一個
"keywords": "xr-ui",
"private": false,
"license": "MIT"
}
複製代碼
在根目錄下新建一個 .npmignore 文件,內容和 .gitignore 差很少:
# 這是複製 .gitignore 裏面的
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
# 如下是新增的
# 要忽略目錄和指定文件
examples/
packages/
public/
vue.config.js
babel.config.js
*.map
*.html
複製代碼
最後執行 npm login 登入最開始註冊好的 npm 帳號,再執行 npm publish 發佈便可,就這麼簡單的兩步就能夠,過一會在 npm 上就能搜到了。固然前提是你有個 npm 帳號,沒有的話去註冊一個吧,很 easy 的,而後還要搜下你的 npm 包名是否有人用,有的話就換一個。
隨着組件的開發迭代,咱們會須要更新組件。更新組件流程很簡單:
npm run lib
登陸(未登陸需登陸驗證npm帳號) npm login
更新版本號(xx.xx.xx)
npm version patch
修改版本號最後一位,表示一些補丁和修復
npm version minor
修改版本號第二位,表示一個小版本的更新
npm version major
修改版本號第一位,表示一個大版本的更新
npm publish
到此爲止,一個簡易的npm包算是發佈完成了。反思本身,不懂的東西還不少,努力探究技術。追求真愛和自由!