如何解決 npm 包須要強制安裝其依賴包的最低版本?

如何解決 npm 包須要強制安裝其依賴包的最低版本?javascript

問題簡述

最近公司在自研一套小程序跨端的框架,遇到一個小問題 —— npm 包須要強制安裝其依賴包的最低版本。簡單來講,是這樣的:vue

  • 工程的 node_module 裝了一個包,專門負責編譯過程,名爲 compile
  • 工程的 node_module 還裝了一個包,是放組件庫的,名爲 components

如今 compile npm 的包版本升級到 0.2.0, 須要 components 的npm 包版本配合升級到 1.3.0。 緣由多是compile npm 的包修改了某個編譯規則,組件庫裏的某種寫法須要改變,不然會報錯。java

問題是,公司有多條業務線,存在多個工程,不可能每次 compile 包升級後,我都人肉去升級每一個工程的 components 包,不然要被業務同窗懟死。node

其實這個問題挺常見……

這個問題,vue 也遇到過。在 vue 官網有那麼這句話,以下:git

每一個 vue 包的新版本發佈時,一個相應版本的 vue-template-compiler 也會隨之發佈。編譯器的版本必須和基本的 vue 包保持同步,這樣 vue-loader 就會生成兼容運行時的代碼。這意味着你每次升級項目中的 vue 包時,也應該匹配升級 vue-template-compilernpm

因此,問題的本質是,如何保證 依賴包之間的強制最低版本要求json

解決方案

方案1: 遠程分發config 配置

在咱們工程中,每次開發者啓動項目,會有一個小彩蛋,咱們會友好熱情的舒適提示開發者,今天的天氣如何如何。其實本質上,就是啓動的時候,去服務端拉取一個動態腳本去執行。小程序

咱們想到了,能夠在這個環節,作一點事情。好比說,檢查一下用戶安裝的版本是否ok。框架

在服務端,咱們維護一份配置文件,這份配置文件描述了依賴包之間的強制最低版本要求。ui

服務端能夠本身搭建的一個node服務,甚至,最簡單的作法,也能夠放在一個git倉庫裏面。

每次開發者執行 npm run dev 的時候,也就是在 pre 這個鉤子時候,就去服務端拉取這份配置文件,而後,檢查一下用戶本地安裝的版本是否知足配置文件中的描述。

可是,這種方案存在一個問題,就是不太好維護。

首先,每次我發佈一個新的 compile 包,版本都更新一次,那麼這份配置文件也須要更新一次。

其次,配置文件長這個樣子:

{
  "compile編譯包": {
    "0.0.1版本": {
      "A依賴包": "0.1.2",
      "B依賴包": "0.1.3",
      "c依賴包": "0.1.3",  
    },
    "0.0.2版本": {
      "A依賴包": "0.1.2",
      "B依賴包": "0.1.4",
      "c依賴包": "0.1.5",  
    }
  }
}
複製代碼

由於這份配置文件是公用的。每次 compile編譯包 升級,都要 新加上一段代碼,日積月累,這個配置就會變得很大很大。

因此,最終咱們選擇了第二種方案。

方案2: 硬編碼

事實上,vue 等框架也是這樣作的。

直接把強制依賴的版本校驗的邏輯,寫死在代碼裏面。

在初始化以前,就去校驗自身版本,和依賴版本,是否符合配置文件的描述。配置文件是放在包內,隨版本走的。

具體實現

下面是代碼的具體實現:

下面定義了 compare 方法,用於比較 "0.2.3", 和 "0.3.4" 兩個字符串,表示的版本號大小

let _isVersion = (v) => {
    let result = /^\d+(\.\d+)*$/.test(v);
    return result;
};

let compare = (v1, v2) => {
    if (_isVersion(v1) && _isVersion(v2)) {
        v1 = v1.toString().split('.');
        v2 = v2.toString().split('.');
        for (let i = 0, l1 = v1.length, l2 = v2.length; i < l1 || i < l2; i++) {
            let n1 = parseInt(v1[i], 10);
            let n2 = parseInt(v2[i], 10);
            if (n1 < n2) {
                return -1;
            } else if (n1 > n2) {
                return 1;
            }
        }
        return 0;
    }
    return console.error('version value is invalid');
};
複製代碼

下面定義了 配置文件config.js

// compiler 依賴包最低版本的配置
module.exports = {
    'A依賴包': {
        'max': '',
        'min': '0.1.2',
        'require': true
    }
}

複製代碼

下面定義了 _checkDependencyVersion 方法:

// 檢查依賴包的版本
const _checkDependencyVersion = () => {
    return new Promise((resolve, reject) => {
        let depMinOption = require('./config.js');
        for (let key in depMinOption) {
            let dep = depMinOption[key];
            try {
                let depSource = require(`${key}/package.json`);
                let sourceVersion = depSource.version;
                if (dep.min && compare(sourceVersion, dep.min) === -1) {
                    console.log(` |***************************************************** | | ${chalk.red('ERROR!')} | ${chalk.red(`toolkit 依賴 ${key} 的最低版本是 ${dep.min}, 請升級 ${key}${dep.min} 及以上`)} | |***************************************************** `);
                    resolve(false);
                }
                if (dep.max && compare(sourceVersion, dep.max) === 1) {
                    console.log(` |***************************************************** | | ${chalk.red('ERROR!')} | ${chalk.red(`toolkit 依賴 ${key} 的最高版本是 ${dep.max}, 請調整 ${key} 版本`)} | |***************************************************** `);
                    resolve(false);
                }
        
                resolve(true)
            } catch (e) {
                console.log(e)
                if (dep.require) {
                    console.log(` |***************************************************** | | ${chalk.red('ERROR!')} | ${chalk.red(`toolkit 依賴 ${key} ${dep.min ? '最低版本:' + dep.min: ''} ${dep.max ? '最高版本:' + dep.max: ''}`)} | |***************************************************** `);
                }
            }
        }
    })
}
複製代碼

上面的 _checkDependencyVersion 方法會在 npm run dev 以後立刻執行,若是發現,開發者本地裝的版本不ok, 則會提醒開發者升級對應包的版本。

若是有更好的解決方案,歡迎在下方評論區留言。

相關文章
相關標籤/搜索