<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          記一次搭建業(yè)務(wù)平臺(tái)組件庫(kù)的過程

          共 6245字,需瀏覽 13分鐘

           ·

          2022-02-17 17:08

          以下內(nèi)容來自公眾號(hào)逆鋒起筆,關(guān)注每日干貨及時(shí)送達(dá)

          來源:樹竹

          https://juejin.cn/post/7020032793774129189

          前言

          因業(yè)務(wù)平臺(tái)擴(kuò)大,組件越來越豐富,想通過抽離組件(包含功能組件,業(yè)務(wù)組件,基礎(chǔ)組件)的方式分享給公司更多的小伙伴使用,所以有了這樣的一次分享。????

          接下來,我將對(duì)自己的這次所學(xué)所得做一次總結(jié)。

          耐心看完,你將收獲到:

          • 通過什么方式進(jìn)行項(xiàng)目管理

          • 如何搭建組件庫(kù)的demo環(huán)境

          • 如何搭建組件庫(kù)的開發(fā)環(huán)境

          • 如何搭建組件庫(kù)編譯打包生成資源的存放位置

          • 自動(dòng)化將組件注冊(cè)為全局組件

          • 如何實(shí)現(xiàn)按需引入

          • 約束規(guī)范

          • 如何將一個(gè)組件庫(kù)發(fā)布到npm上

          通過什么方式進(jìn)行項(xiàng)目管理

          背景

          本著調(diào)研的目的去思考如何在開發(fā)一個(gè)組件庫(kù)時(shí),是將這些package放在一個(gè)倉(cāng)庫(kù)里維護(hù)還是放在多個(gè)倉(cāng)庫(kù)里單獨(dú)維護(hù)?或者說一個(gè)倉(cāng)庫(kù)想基于多個(gè)不同框架開發(fā)的組件庫(kù),那么如何去管理呢?

          那是將每個(gè)組件當(dāng)成一個(gè)package進(jìn)行管理(即多項(xiàng)目多倉(cāng)庫(kù)的形式,也稱為Multirepo),還是用一個(gè)倉(cāng)庫(kù)去管理多個(gè)package(即Monorepo)

          可能上述的表達(dá)有點(diǎn)抽象,用實(shí)例來看看兩者的區(qū)別:

          image.png

          解決

          為了降低多package項(xiàng)目的維護(hù)成本,我使用lerna作為流程管理工具。
          • 初始化Lerna項(xiàng)目:
          //?進(jìn)入項(xiàng)目文件夾
          cd?DDMC-UI-?
          //?初始化?
          lerna?init
          復(fù)制代碼
          • 初始化之后 ,生成的項(xiàng)目結(jié)構(gòu)如下:
          DDMC-UI?/
          ??packages?/
          ??package.json
          ??lerna.json
          復(fù)制代碼
          lerna.json是為L(zhǎng)erna的管理配置文件,在搭建過程中我是采用的是lerna的固定模式。那什么是固定模式呢?

          固定模式的Lerna項(xiàng)目是在一條單一的版本線上操作的,這個(gè)版本是在項(xiàng)目根目錄的?lerna.json文件中的?version字段中控制的。當(dāng)執(zhí)行?lerna publish時(shí),如果一個(gè)模塊自上次發(fā)布以來有更新,它將會(huì)更新為你要發(fā)布的新的版本,這意味著你只需在需要時(shí)發(fā)布新版本的package。

          • 補(bǔ)全項(xiàng)目的目錄,最終生成項(xiàng)目倉(cāng)庫(kù)如下:
          DDMC-UI?/
          ??config?/??
          ??example?/?
          ??????app.js
          ??????index.html
          ??packages?/
          ??????demo1?/
          ??????????index.vue
          ??????????index.js
          ??????demo2?/
          ??????????index.vue
          ??????????index.js
          ??????index.js
          ??src?/
          ??????utils?/
          ??????common?/
          ??package.json
          ??lerna.json
          復(fù)制代碼

          webpack 構(gòu)建項(xiàng)目

          地基是打好了,但是作為打工人還要考慮項(xiàng)目如何構(gòu)建。在構(gòu)建項(xiàng)目這個(gè)過程中,我通過使用webpack實(shí)現(xiàn)項(xiàng)目的構(gòu)建。
          組件庫(kù)demo環(huán)境,組件庫(kù)開發(fā)環(huán)境以及組件庫(kù)編譯打包生成資源的存放位置,都是基于webpack的配置來實(shí)現(xiàn)。具體的配置目錄是通過config文件。
          項(xiàng)目中的example文件就是demo環(huán)境。它是給用戶查看組件具體用法的例子。
          創(chuàng)建dev.config.js- 新增開發(fā)環(huán)境的配置:
          image.png
          創(chuàng)建pro.config.js- 新增生產(chǎn)環(huán)境的配置:
          image.png
          這2個(gè)文件分別都是對(duì)應(yīng)開發(fā)環(huán)境和生產(chǎn)環(huán)境的配置,組件可以在package文件下開發(fā),example文件進(jìn)行使用。
          創(chuàng)建lib.config.js- 新增組件庫(kù)編譯打包生成資源的存放位置配置:
          image.png
          生成的lib文件主要是作為組件庫(kù)發(fā)布到npm的一個(gè)入口文件。所以針對(duì)的入口是packages下的組件。
          基于上面的配置之后,我們來實(shí)現(xiàn)package.json命令配置:
          image.png
          將文件區(qū)分開來,知道每個(gè)文件是用來干嘛的,分工明確是第一步其實(shí)是重要的。
          我還創(chuàng)建了一個(gè)base.config.js是公共的配置文件。這個(gè)文件實(shí)現(xiàn)了一些基礎(chǔ)配置:
          • js模塊將es6轉(zhuǎn)成es5
          • 將css文件和js文件分離打包
          • css的轉(zhuǎn)換
          • 配置別名
          • 圖片處理之類
          • 微信搜索readdot,關(guān)注后回復(fù)視頻教程獲取23種精品資料

          自動(dòng)化將組件注冊(cè)為全局組件

          為了避免使用組件的時(shí)候頻繁的import...導(dǎo)入操作,我們可以將其注冊(cè)為全局組件。需要用到Vue.component()Vue.use()兩個(gè)方法。
          先來看看一個(gè)demo組件的目錄結(jié)構(gòu):
          demo
          ├——?index.vue??#?組件實(shí)現(xiàn)
          │?
          └──?index.js?#?每個(gè)組件install方法,供全局引入
          index.js?提供install方法,供Vue.use()使用?

          復(fù)制代碼
          將組件注冊(cè)為全局組件,具體的代碼實(shí)現(xiàn)如下:
          const?fs=require('fs');
          const?path=require('path');
          var?endOfLine?=?require('os').EOL;
          const?render?=?require('json-templater/string');

          const?IMPORT_TEMPLATE='import?{{name}}?from?\'./index.vue\';';
          const?USE_TEMPLATE='Vue.component({{name}},?{{component}});';
          const?MAIN_TEMPLATE=`
          {{include}}
          {{component}}.install?=?function?(Vue)?{
          ????{{list}}
          };
          export?default?{{component}};
          `


          const?files=fs.readdirSync('./packages');

          const?folder?=files.slice(0,-1)

          console.log(folder)


          const?includeComponentTemplate?=?[];
          const?listComponentTemplate?=[];

          const?writeFile=function(file,include,list){
          ????const?p=path.resolve(__dirname,`../packages/${file}/index.js`);
          ????fs.writeFileSync(p,render(MAIN_TEMPLATE,{
          ????????include:include,
          ????????list:?list,
          ????????component:file
          ????}));
          }

          folder.forEach((item)=>{
          ????const?include=render(IMPORT_TEMPLATE,{
          ????????name:item,
          ????????component:item,
          ????});
          ????const?list=render(USE_TEMPLATE,{
          ????????name:item,
          ????????component:item,
          ????});
          ????writeFile(item,include,list);
          });

          復(fù)制代碼
          主要思路是組件提供install方法,并使用Vue.component()注冊(cè)成全局組件。腳本中通過模塊json-templater可以在js和json對(duì)象上進(jìn)行胡子樣式模板替換。執(zhí)行命令:npm run build:cp,生成的demo文件下的index.js代碼:
          image.png
          將組件注冊(cè)為全局組件之后,需要在index.js引入。也是通過腳本自動(dòng)化引入,具體的實(shí)現(xiàn)可參考如上代碼。通過執(zhí)行命令:npm run build:pck,生成的代碼:
          image.png

          如何實(shí)現(xiàn)按需引入

          開發(fā)完組件庫(kù)之后,在其他所需該組件的項(xiàng)目中,我們班可以通過import XXX from 'ddmc-ui'。這樣的方式叫做全局引入,將組件庫(kù)都引入到所需的項(xiàng)目中。
          那如何實(shí)現(xiàn)按需引入呢?例如import {XXX} from 'ddmc-ui/lib/demo'
          注意:這里的按需引入是指你所開發(fā)的項(xiàng)目中需要按需引入這個(gè)組件庫(kù)
          要想實(shí)現(xiàn)如上的方式引入組件,我們需要把組件一個(gè)一個(gè)單獨(dú)打包的,所以要獲取每個(gè)組件的路徑。通過webpack配置,將輸出lib目錄要和packages目錄結(jié)構(gòu)一致。在lib.config.js配置需要更改。
          主要是獲取packages文件的目錄是關(guān)鍵點(diǎn),如下代碼可實(shí)現(xiàn)獲取入口對(duì)象:
          function?getEntries(path)?{
          ??let?files?=??fs.readdirSync(resolve(path));
          ??const?entries?=?files.reduce(?(ret,?item)?=>?{
          ????????const?itemPath?=`${path}/${item}`;
          ????????const?isDir?=??fs.statSync(resolve(itemPath)).isDirectory();
          ????????console.log(isDir,itemPath)
          ????????if?(isDir)?{
          ????????????ret[item]?=?resolve(join(itemPath,?'index.js'));
          ????????}?else?{
          ????????????const?[name]?=?item.split('.');
          ????????????ret[name]?=?resolve(itemPath);
          ????????}
          ????????return?ret;
          ??},?{})
          ??return?entries;
          }

          復(fù)制代碼
          好了,到這里組件庫(kù)的按需引入是完成了。但是有個(gè)缺點(diǎn),就是每次使用按需引入就要寫一大串import {XXX} from 'ddmc-ui/lib/demo'這樣的引入方式。
          這個(gè)時(shí)候就需要用到babel-plugin-import這個(gè)插件了。
          注意:babel-plugin-import是指你所開發(fā)的項(xiàng)目中用到并修改其配置
          具體的配置是:
          //?.babelrc
          {
          ????...
          ????"plugins":[
          ????????"import",?{
          ????????????"libraryName":?"ddmc-ui",
          ????????}
          ????]
          }

          復(fù)制代碼

          約束規(guī)范

          組件庫(kù)的管理和構(gòu)建功能都有了,但是在多人共建的一個(gè)項(xiàng)目中,必須得有一個(gè)規(guī)范去進(jìn)行約束,而規(guī)范除了書面上的闡述外,還需要一些自動(dòng)化的、強(qiáng)制性的約束。所以需要在代碼提交前對(duì)每個(gè)打工仔的代碼進(jìn)行一遍驗(yàn)證,防止亂提交。
          husky?給GIT提交添加鉤子執(zhí)行一些我們需要做的驗(yàn)證,并執(zhí)行一些腳本去驗(yàn)證代碼是否有問題是否規(guī)范。
          lint-staged?是一個(gè)在git暫存文件上運(yùn)行l(wèi)inters的工具。可以搭配husky進(jìn)行git commit前的代碼校驗(yàn)。
          commitlint?提交信息校驗(yàn),基于以上的兩個(gè)工具包,我們有能力在Git的鉤子里做一些事情。首先不得不提的是代碼的提交規(guī)范和規(guī)范的校驗(yàn),優(yōu)雅的提交方便團(tuán)隊(duì)協(xié)作和快速定位問題。微信搜索readdot,關(guān)注后回復(fù)視頻教程獲取23種精品資料
          一般GIT比較常見的提交格式規(guī)范是:: 。
          實(shí)現(xiàn)約束規(guī)范的過程:
          • 安裝
          npm?install?-D?husky?lint-staged

          復(fù)制代碼
          • 初始化
          npx?husky?install
          npx?husky?add?.husky/pre-commit?"npm?run?test"
          npx?husky?add?.husky/commit-msg?'npx?--no-install?commitlint?--edit?"$1"'
          復(fù)制代碼
          • package.json配置
          "lint-staged":?{?"src/*?*/*?.{js,json,vue,ts,tsx}":?[?"npm?run?lint"?]?}
          復(fù)制代碼
          • 新建commitlint.js
          module.exports?=?{?extends:?['@commitlint/config-conventional']?}
          復(fù)制代碼

          如何將一個(gè)組件庫(kù)發(fā)布到npm上

          package.json配置:
          • 配置組件庫(kù)名稱
          {
          ??"name":?"foxit-ui"
          }
          復(fù)制代碼
          注意:這個(gè)組件庫(kù)名稱要在 npm 上是獨(dú)一無(wú)二,不能重復(fù),否則發(fā)布時(shí)會(huì)提示你無(wú)權(quán)限修改此庫(kù)
          • 將組件庫(kù)設(shè)置為公開
          {
          ???"private":?true
          }
          復(fù)制代碼
          • 配置關(guān)鍵詞、描述、作者
          {
          ??"description":?"XXX?組件庫(kù)",
          ??"keywords":?[
          ????"element",
          ????"vue",
          ????"ddmc-ui"
          ??],
          ??"author":?"hhl"
          }

          復(fù)制代碼
          • 配置主入口文件地址
          {
          ??"main":?"lib/index/index.js"
          }
          復(fù)制代碼
          • 設(shè)置忽略文件,減少依賴包大小
          一個(gè)組件庫(kù)只有編譯后的?lib?文件夾、package.json?文件、README.md?文件才是需要被發(fā)布的。其他都不需要的,需要在根目錄下創(chuàng)建一個(gè)??.npmignore?文件中把沒必要發(fā)布的資源忽略掉,減少依賴包大小。

          思考

          在搭建的過程,主要是工具包之間本身的版本兼容問題,還有就是和node版本相關(guān)的問題。
          過程中使用vue-loader的高版本出現(xiàn)了Error: Cannot find module 'webpack/lib/RuleSet'。查閱vue-loader源碼最后解決方案是降低版本。
          雖然整體上的倉(cāng)庫(kù)以及組件庫(kù)已完成,但是隨著倉(cāng)庫(kù)的擴(kuò)大還是需要迭代優(yōu)化的。也可以從webpack配置進(jìn)行優(yōu)化。
          • 刪除無(wú)用的css樣式
          • 將打包后的圖片進(jìn)行壓縮
          • CDN加載文件
          • 過濾第三方包。比如vue,vuex之類的。使用webpack的externals選項(xiàng)。externals來防止這些依賴包被打包
          • tree-shaking :沒有用的代碼剔除掉等。后續(xù)會(huì)慢慢迭代項(xiàng)目?jī)?yōu)化這塊
          • happypack 多線程打包,可以將不同的邏輯交給不同的線程來處理
          • DllReferencePlugin 和 DllPlugin提前打包,大幅度提升構(gòu)建速度
          • 動(dòng)態(tài)加載 通過import引入文件:添加webpackChunkName字段,webpack配置output選項(xiàng)
          因時(shí)間的關(guān)系比較趕,后續(xù)將會(huì)慢慢迭代上去。

          總結(jié)

          以上是我從零開發(fā)一款組件庫(kù)遇到的問題踩過的坑總結(jié)下來并實(shí)際使用的工具和方法,希望能給大家?guī)韼椭?/span>

          除了上面提到的這些比較常用的工具和方法外,對(duì)于前端工程化/自動(dòng)化還有很多探索和學(xué)習(xí)。

          覺得不錯(cuò)給文章點(diǎn)個(gè)贊,是對(duì)我最大的支持和鼓勵(lì)????

          六千字講透 Vue3 響應(yīng)式是如何實(shí)現(xiàn)的

          如何將業(yè)務(wù)代碼寫得更優(yōu)雅

          真實(shí)業(yè)務(wù)訂單 拆單 架構(gòu)與實(shí)戰(zhàn)

          如何搭建一臺(tái)永久運(yùn)行的個(gè)人服務(wù)器?

          一鍵部署!搭建一個(gè)文檔網(wǎng)站 超簡(jiǎn)單!

          點(diǎn)個(gè)『在看』支持下?
          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91成人做爰黄A片 | 久久一道本色 | www.色日本 | 操逼逼啊啊啊 | 天天干天天射天天舔麻豆 |