惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
LangChain Blog
云风的 BLOG
云风的 BLOG
M
MIT News - Artificial intelligence
A
About on SuperTechFans
J
Java Code Geeks
量子位
博客园 - 三生石上(FineUI控件)
博客园 - Franky
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
IT之家
IT之家
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
Martin Fowler
Martin Fowler
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

博客园 - hangox

Claude Code 自定义状态栏配置指南 如何给 Claude 中的网页做截图 AGP 8.0+ Publish idea 插件兼容 K2 模式 IDEA 不提示 gitlab-ci 字段问题 不要随便使用 npm 源加速站点 Xcode Format Swift 代码 idea Convert File To Kotlin File 多 Commit 问题 BCM94360CS2 黑苹果 macOS Sonoma Wifi 不能开启修复 NginxProxyManager 数据库迁移记录 android ConcurrentModificationException 错误 Android Studio 插件分享——Gradle Utilities Android Studio 插件分享——Jadx Class Decompiler templete Android Studio 3.0 新特性 Android SpringAnimator初探 关于Android菜单上的记录 升级到 classpath 'com.android.tools.build:gradle:1.0.0-rc1 OnScrollListenerPro
ApkList 源问题修复
hangox · 2024-06-25 · via 博客园 - hangox

问题描述

很久没动的 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))
        }

    }

}

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