ApkList 源问题修复

问题描述

很久没动的 Angular 项目忽然修改东西,自动化发布失败了。

问题原因

淘宝源从 https://registry.npm.taobao.org/ 更换为 https://registry.npmmirror.com 导致获取依赖失败

修复方案

方案一 更改源后生成新的 yarn.lock 文件(失败)

  1. 移除 yarn.lock 文件
  2. 使用 npm config set registry https://registry.npmmirror.com 设置源
  3. 然后执行 yarn install

最后运行 node_modules/@angular/cli/bin/ng build

为什么之前还能构建的项目,现在就不行呢?
这个问题实际上次构建使用的依赖是保存在 yarn.lock 文件上的,移除整个yarn.lock文件后,同时因为package.json 声明小版本可以升级的问题,导致最后生成的 yarn.lock 文件实际上用到的依赖和以前的依赖是不一样的

从文件对比中可以发现,版本是有小升级的,为什么会这样? ,因为我们写的 package.json 文件的依赖关系是有问题的。

上图中可以看到每个依赖的版本号前面都有符号,这些符号是代表不同的意思,完整意思如下

在使用 yarn add 命令添加依赖项时,可以通过指定版本号以及使用不同的符号来控制安装的依赖版本范围。这些符号包括 ^, ~, <=, >=, =, 和无符号版本号。下面是一些常用的例子和它们的含义:

使用 ^ 符号

  • 命令
    yarn add @angular/forms@^8.2.14
    
  • 含义:安装 @angular/forms 版本 8.2.14 及其所有向后兼容的次版本更新,即 >= 8.2.14 < 9.0.0

使用 ~ 符号

  • 命令
    yarn add @angular/forms@~8.2.14
    
  • 含义:安装 @angular/forms 版本 8.2.14 及其所有向后兼容的修订版本更新,即 >= 8.2.14 < 8.3.0

使用 <= 符号

  • 命令
    yarn add @angular/forms@<=8.2.14
    
  • 含义:安装 @angular/forms 版本 8.2.14 或更低版本。

使用 >= 符号

  • 命令
    yarn add @angular/forms@>=8.2.14
    
  • 含义:安装 @angular/forms 版本 8.2.14 或更高版本。

使用 = 符号

  • 命令
    yarn add @angular/forms@=8.2.14
    
  • 含义:安装 @angular/forms 的确切版本 8.2.14。

不使用符号(默认行为)

  • 命令
    yarn add @angular/forms
    
  • 含义:安装 @angular/forms 的最新版本(通常是最新的稳定版本)。

使用多个版本范围

你也可以结合多个版本范围来指定更复杂的依赖规则。

  • 命令
    yarn add @angular/forms@">=8.2.14 <9.0.0"
    
  • 含义:安装 @angular/forms 版本在 8.2.14 及其以上但低于 9.0.0 的版本。

示例

假设你想安装 @angular/forms 版本在 8.2.x 系列中最新的修订版本,但不想升级到 8.3.x 或更高版本,可以使用以下命令:

yarn add @angular/forms@~8.2.14

这样会确保安装版本范围在 >= 8.2.14 < 8.3.0 之间。

总结

使用这些版本控制符号,你可以更精确地管理项目中的依赖版本,确保在获得最新更新的同时,不会因为版本不兼容而引发问题。以下是一些常见的符号及其含义的总结:

  • ^: 允许升级到不改变主版本号的最新版本。
  • ~: 允许升级到不改变次版本号的最新版本。
  • <=: 允许安装指定版本或更低版本。
  • >=: 允许安装指定版本或更高版本。
  • =: 安装确切版本。

根据项目需求选择合适的符号,可以更好地控制依赖版本的安装。

方案二 直接替换 yarn.lock 文件域名(完美可行)

就像这样直接全局替换为 https://registry.npmmirror.com/ 即可

方案三 最终解决方案

真正的问题是因为 package.json 编写的 version 并不是固定的,而是动态的,这个在依赖管理中其实是大忌,毕竟你永远不知道第三方包的一个小升级是否会导致你代码出现问题。
所以,根本的解决方案是把,yarn.lock 中依赖的版本提取出来,然后放到 package.json 文件中。我用 kotlin 编写了以下代码来进行校准版本

package com.hangox.test

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject

import java.io.File

/**
 * package 文件位置,用来对比更新
 */
val PACKAGE_JSON_PATH = "/path/package.json"

/**
 * lock 文件位置,用来提取实际上依赖的包
 */
val YARN_LOCK_FILE = File("/patch/yarn.lock")
fun main() {
    val yarnLockFile = YARN_LOCK_FILE
    val lockFilerVersionMap = mutableMapOf<String, String>()


    yarnLockFile.bufferedReader().use { reader ->
        var currentPackage: String? = null
        reader.forEachLine { line ->
            val trimmedLine = line.trim()
            when {
                !line.startsWith(" ") && trimmedLine.endsWith(":") -> {
                    val lineName = trimmedLine.replace("\"", "").replace(":", "")
                    val packageName = if (lineName.startsWith("@")) {
                        // 提取第二个 @ 位置的内容
                        "@" + lineName.substringAfter("@").substringBefore("@")
                    } else {
                        trimmedLine.substringBefore("@")
                    }
                    currentPackage = packageName
                }

                trimmedLine.startsWith("version") -> {
                    // Extract version
                    val version = trimmedLine.substringAfter("version").trim().removeSurrounding("\"")
                    if (currentPackage != null) {
                        lockFilerVersionMap[currentPackage!!] = version
                    }
                }
            }
        }
    }

    // Print all versions
    lockFilerVersionMap.forEach { (packageName, version) ->
        println("Package: $packageName, Version: $version")
    }
    

    File(PACKAGE_JSON_PATH).readText().let {
        val data = Gson().fromJson(it, JsonObject::class.java)
        listOf("dependencies", "devDependencies").forEach { depKey ->
            val depJson = data.get(depKey).asJsonObject
            depJson.entrySet().forEach { (packageName, packageVersion) ->
                val key = packageName
                val lockVersion = lockFilerVersionMap[key]
                if (lockVersion == null) {
                    println("不存在的版本: $packageName, lockVersion: $lockVersion packageVersion : $packageVersion")
                    return@forEach
                }
                if (packageVersion.asString != lockVersion) {
                    println("replace: $packageName, lockVersion: $lockVersion packageVersion : $packageVersion")
                }
                depJson.addProperty(key, lockVersion)
            }
            println(GsonBuilder().setPrettyPrinting().create().toJson(depJson))
        }

    }

}

脚本会输出完整的依赖文本(如下),只要替换掉原本的依赖文本即可

posted @ 2024-06-25 21:03  hangox  阅读(6)  评论(0编辑  收藏  举报