【手牽手】搭建前端組件庫(一)

本文梳理如何搭建和構建前端組件庫.javascript

028.png

瞭解幾個問題css

爲什麼須要組件化?html

大部分項目起源都是源於業務方的各類各樣的奇葩需求。隨着公司的業務發展,公司內部開始衍生出不少的B2C系統、後臺系統,前端部門也疲於應對愈來愈多同質化的項目,這些項目在不少基礎模塊層、源代碼存在不小的類似,甚至存在類似的業務模塊。前端

筆者曾經所在的一個電商團隊,前端成員基本每一個人多作過登陸註冊、購物車、支付、微信登陸...... 大量重複的業務代碼。因爲組內技術沒有強制規範vue

本質上相同的東西,重複的去code就顯得浪費.java

分析這些問題發現:
日漸增多的業務場景需求webpack

前端資源有限,沒法支持全部項目的快速迭代git

公司內部諸多產品業務混亂、體驗不統一web

因而開發底層的工具去服務不一樣業務就頗有必要:
設計一套公司內部的基礎組件庫支撐各個前端項目,提高項目和業務的可用性和一致性。vue-cli

一個前端團隊擁有大量的業務場景和業務代碼,類似的頁面和代碼層出不窮,如何管理和抽象這些類似的代碼和模塊,絕大多數團隊會遇到這樣的問題。 不斷的拷代碼? 修改代碼?仍是抽象成組件?顯而後者更高效。因此在多項目存在高度的可控、底層依賴的狀況下,前端實現組件庫是最好的選擇。

組件化,又或者組件抽離的目的是爲了功能共享方便維護,其可以帶來的好處是少寫代碼,統一管理、統一維護。一套基礎組件代碼千錘百煉精而又精,從而起到快速支撐業務迭代,提高開發效率的目的。

業務型組件庫

前端組件庫百花齊放,antd、element ui這些基礎組件庫已經很強大,使用於各類業務場景。可是這些基礎組件的粒度是基於單個交互,而在交互產品之間隔着各類各樣的模塊和業務場景,產品的匯聚源於各類基礎組件在業務邏輯的沾粘下集成爲一個個項目,一個團隊或多或少會有項目或模塊存在功能、交互流程的重複、本質上的同質化。

因此antd、element ui 這類組件庫是基於單個非連續性的交互組件,一個組件表明着一次人機無反作用的操做與響應,其不思考實體、用戶、終端的狀態,最小化的暴露和響應組件內部狀態。對於連續性的交互一般來講與特色的業務場景有關,存在諸多的外部依賴,目前都是在各個業務模塊由用戶(coder)自行編寫。

有沒有一種方法解決連續性交互流程的共用問題?

解決的辦法是組件封裝包含業務場景的連續性交互流程,利用組件化將內部依賴經過接口映射到外部。

前端架構部門爲業務部門提供業務型組件庫可以有效提升開發效率.

組件庫設計思路

組件是對一些具備相同業務場景和交互模式、交互流程代碼的抽象,組件庫首先應該保證各個組件的視覺風格和交互規範保持一致。組件庫的 props 定義須要具有足夠的可擴展性,對外提供組件內部的控制權,使組件內部徹底受控。支持經過 children 自定義內部結構,預約義組件交互狀態。保持組件具備統一的輸入和輸出,完整的API.

組件庫的開發咱們須要考慮:

  • 組件設計思路、須要解決的場景
  • 組件代碼規範
  • 組件測試
  • 組件維護,包括迭代、issue、文檔、發佈機制

一個完整強大的組件庫須要多方面努力,迴歸正題.

使用到的基礎技術

  1. vue cil 3
  2. npm
  3. webpack
  4. rollup(v1.2.2)

Demo

下面就手把手搭建一個前端偏業務性的組件庫。

組件庫包括:

  • message 組件: 一個封裝用於呈現後臺經過 websocket 推送到前臺頁面的實時消息模塊;
  • pay 組件: 一個封裝用於實現商品支付的模塊
  • share 組件: 一個封裝用於實現商品、文章、視頻在各社交平臺分享的模塊

只拋出一個栗子,組件內部實現略~

這裏注意組件抽取的粒度,組件的抽離以一個完整的連續性交互爲目地。

組件依賴數據、交互事件、控制權的暴露須要考慮全面,不一樣的上層業務部門都有本身對組件可配置的不一樣渴望。須要權衡,不能把配置化給搗鼓的永無止境到很難堪的局面。筆者曾經就參與一個項目的組件化,組件抽離的面目全非,各類依賴、環境、狀態的配置,致使最後只有組件編寫人員在看文檔加回憶的狀況下才能搞清楚其前因後果.

從簡單的開始~

一、初始化組件庫目錄

建立一個空項目

// 新建一個項目
vue create qw-ui

通過vue cil3初始化後的qw-ui目錄:

├─docs
│          
├─public
│
├─src
│  .gitignore
│  babel.config.js
│  package-lock.json
│  package.json
│  README.md
│  vue.config.js
│

此時爲了方便組件庫的代碼管理,將目錄結構修改成:

├─src        // 用做示例 Demo
│          
├─packages   // 新增 packages 用於編寫存放組件
│
├─lib        // 新增 lib 用於存放編譯後的輸出文件
│  .gitignore
│  babel.config.js
│  package-lock.json
│  package.json
│  README.md
│  vue.config.js
│

目錄結構能夠更具須要調整.

二、修改 vue.config.js 配置

vue cli3 提供一個可選的 vue.config.js 配置文件。這個文件存在則他會被自動加載,全部的對項目和webpack的配置,都在這個文件中。

修改 vue.config.js 配置的目的主要是:

  1. 使 Demo 可訪問,實現對 src目錄的編譯處理;
  2. 提供對 package的編譯、構建處理

作如下兩處修改:

  • 修改項目的入口

entry 字段爲項目入口

入口修改使用 Vue CLI 3 的 page屬性來配置:

module.exports = { pages: { index: { // page 的入口 entry: 'src/main.js', // 模板來源 template: 'public/index.html', // 在 dist/index.html 的輸出 filename: 'index.html' } } }
  • 添加對 packages 目錄的編譯處理

packages 是咱們後來新增的一個目錄,默認是不被 webpack 處理的,因此須要經過添加配置對該目錄的編譯支持。

新增編譯處理目錄,須要經過webpack的鏈式操做chainWebpack函數實現:

module.exports = { pages: { index: { // page 的入口 entry: 'examples/main.js', // 模板來源 template: 'public/index.html', // 在 dist/index.html 的輸出 filename: 'index.html' } }, chainWebpack: config => { // packages和examples目錄須要加入編譯 config.module .rule('js') .include.add(/packages/) .end() .include.add(/src/) .end() .use('babel') .loader('babel-loader') .tap(options => { // 修改它的選項... return options; }); } }

執行 npm run vue-cli-service serve , 實現對Demo的訪問.

三、編寫 packages 組件庫

建立一個 message組件

  • 建立組件

    • 在 packages 目錄下,全部的單個組件都以文件夾的形式存儲,這裏建立一個目錄 message 文件夾;
    • 在 message/ 目錄下建立 src/ 目錄存儲組件源碼,全部 message 依賴的除第三方資源都存放與該目錄下;
    • 在 /message目錄下建立 index.js` 文件對外提供對組件的引用

示例代碼:

message/index.js 對外提供應用

// message/index.js import message from './src/message ' message .install = function (Vue) { Vue.component(message .name, message ) } export default message 
// message/src/message .js <template> <div class="message"> <el-row class="message-test"> <el-col :span="12" class="message-row"><p class="text">hello {{ message }}</p></el-col> <el-col :span="6"> <img src="./st.png"/> </el-col> </el-row> </div> </template> <script> import './index.scss' export default { name: 'v-message', // 申明組件的 name屬性 props: { message: String } } </script> 

須要注意的是,組件 mesage 必須聲明 name 屬性,這個 name 就是組件的標籤,如:

<v-message><v-message/>

packages/message目錄結構以下:

packages/message
            ├─index.js
            │          
            ├─src
                │      message.vue
                │      st.png         // 組件依賴的圖片
                │      index.scss    // 組件依賴的樣式文件

導出 packages 組件庫

修改 /packages/index.js 文件,整合全部組件,並對整個組件庫進行導出:

// 導入組件 import hello from './hello' // 存儲組件列表 const components = [ hello ] // 定義 install 方法,接收 Vue 做爲參數。若是使用 use 註冊插件,則全部的組件都將被註冊 const install = function (Vue) { // 判斷是否安裝 if (install.installed) return // 遍歷註冊全局組件 components.map(component => Vue.component(component.name, component)) } // 判斷是不是直接引入文件 if (typeof window !== 'undefined' && window.Vue) { install(window.Vue) } export default { // 導出的對象必須具備 install,才能被 Vue.use() 方法安裝 install, // 如下是具體的組件列表 hello } 

到此,構建組件庫的環境準好好了

### 四、發佈組件庫到 npm

  1. packages 目錄的編譯打包

    在 package.json的 scripts 字段中新增一下命令:

    "lib": "vue-cli-service build --target lib --name kui --dest lib packages/index.js"
    vue cil3 提供了 [庫模式](https://cli.vuejs.org/zh/guide/build-targets.html#%E5%BA%93) 來打包第三方庫的開發,packages 的編譯打包須要使用庫模式 

    --target: 構建目標,默認爲應用模式。這裏修改成 lib 啓用庫模式。

    --dest : 輸出目錄,默認 dist。這裏咱們改爲 lib

    [entry]: 最後一個參數爲入口文件,默認爲 src/App.vue。這裏咱們指定編譯 packages/ 組件庫目錄。

    在 vue cil3 庫模式中,Vue 是 外置的。這意味着包中不會有 Vue,即使你在代碼中導入了 Vue。若是這個庫會經過一個打包器使用,它將嘗試經過打包器以依賴的方式加載 Vue;不然就會回退到一個全局的  Vue 變量。

    配置好了後,執行編譯命令:

    npm run lib

    稍後控制檯輸出,即編譯完成:

    DONE  Compiled successfully in 5988ms16:05:35 File Size Gzipped lib\kui.umd.min.js 8.08 KiB 4.55 KiB lib\kui.umd.js 17.78 KiB 7.31 KiB lib\kui.common.js 17.41 KiB 7.19 KiB lib\kui.css 0.10 KiB 0.10 KiB Images and other types of assets omitted.
Total task duration: 8.71s ``` 
  1. package.json 配置

    • name: 包名,該名字是惟一的。可在 npm 官網搜索名字。
    • version: 版本號,每次發佈至 npm 須要修改版本號,不能和歷史版本號相同。
    • description: 描述。
    • main: 入口文件,該字段需指向咱們最終編譯後的包文件。
    • keyword:關鍵字,以空格分離但願用戶最終搜索的詞。
    • author:做者
    • private:是否私有,須要修改成 false 才能發佈到 npm
    • license: 開源協議

      參考配置:

      {
        "name": "qw-ui", "version": "0.1.0", "private": false, "main": "lib/kui.umd.min.js", "description": "qw-ui", "keyword": "qw-ui", "author":"luojh", "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "lib": "vue-cli-service build --target lib --name kui --dest lib packages/index.js" } }
  2. 添加 .npmignore 文件

    發佈時,只有編譯後的 lib 目錄、package.json、README.md才須要被髮布。因此經過配置.npmignore文件忽略不須要提交的目錄和文件。

    # 忽略目錄 examples/ packages/ public/ # 忽略指定文件 vue.config.js babel.config.js *.map # 本地文件 .env.local .env.*.local # 日誌文件 npm-debug.log* yarn-debug.log* yarn-error.log* # 編輯器緩存文件 .idea .vscode *.suo *.ntvs* *.njsproj *.sln *.sw*
  3. 發佈到 npm

    首先須要在 npm 官網上註冊一個帳號,經過 npm adduser 命令建立一個帳戶,或者在 npm 官網註冊

    註冊完成後在本地命令行中登陸:

    npm login

    執行發佈命令,發佈到 npm

    npm publish
    1. npm 淘寶鏡像不支持 publish 命令,若是設置了淘寶鏡像,publish 前需將鏡像設置會 npm :

    npm config set registry http://registry.npmjs.org

    1. npm publish時,本地cmd終端需經過管理員運行

### 5.使用組件庫

安裝發佈的組件庫:

npm i qw-ui

使用組件:

# 在 main.js 引入並註冊 import qwui from 'qw-ui' Vue.use(qwui) # 在組件中使用 <template> <v-message message=" hello 333 :: 使用kui組件庫"></v-message> </template> <script> export default { data () { return { } } } </script>

完!

 

感謝:https://segmentfault.com/a/1190000018310478?utm_source=tag-newest

相關文章
相關標籤/搜索