如何编辑和替换NPM软件包依赖关系
#javascript #npm #git

上周,我的first actual contribution into a public open source项目已合并。实际上,它只是对Nitros server engine使用的Unstorage库的一个小变化,而Nitros server engine又被流行的NuxtJs框架使用。当时,我被困在一个使用NUXT的附带项目中,因为Unstorage缺乏我需要的一些功能。但是,由于依赖树中的透明是2层的,因此我在那里更改代码并不是很微不足道的。

我想这实际上是使用NPM时的常见任务。人们有很多理由更改库的库,这是依赖树深处的几层。也许他们遇到了需要修复的错误,或者存在一些安全问题,因此他们希望将依赖性更改为另一个库。但是,当时我可以找到任何完成此任务的完整教程。我只找到了一些部分步骤或不完整的文档,需要将它们拼凑在一起。因此,经过一些摆弄,一些试验和错误,我终于找到了如何做。在这里,我将分享这些方法,以便其他人不必经历与我相同的麻烦。

要向您展示它是如何完成的,我将通过做同样的事情来证明。那是通过创建一个新的NUXT项目,然后用我自己的更改来分配解开软件包。但是,在此示例中,我们只会添加一个简单的更改,不会影响整体功能,只是为了说明其完成方式。您可以忽略NUXTJS零件,因为在这里我们的主要主题实际上不是必需的。

设置场景

首先让我们创建一个新的NUXTJS项目。

npx nuxi@latest init my-app
cd my-app

然后,让我们设置一个简单的页面以使用Unsostorage功能。让我们使用它创建一个简单的计数页,该页面将存储在默认的解开存储存储中(这是内存商店)。首先,我们将编辑app.vue文件:

// app.vue
<template>
  <div>
    Counter: {{ counter }}
    <button @click="updateCounter()">
      add
    </button>

    <br />
    Server Counter: {{ server_counter }}
  </div>
</template>

<script setup lang="ts">
const counter = useState('counter', () => 0)
const server_counter = useState('server_counter', () => 0)

async function updateCounter() {
  counter.value++

  const res = await $fetch('/api/add_counter', {
    method: 'post', 
    body: { counter: counter.value },
  })

  server_counter.value = res.value
}
</script>

然后我们将添加server/api/add_counter.post.ts。同样,这是nuxtjs的东西。它不必了解如何替换NPM依赖性。

// server/api/add_counter.post.ts
export default defineEventHandler(async (event) => {
  const { counter } = await readBody(event)

  await useStorage().setItem('data:counter', counter)
  const res = await useStorage().getItem('data:counter')

  return { value: res }
})

现在,我们有一个简单的虚拟示例来进行演示:

Screenshot of our new dummy web app

让unstorage软件包克隆到我们的本地env中,然后将其更改为我们的需求。

git clone https://github.com/unjs/unstorage.git
cd unstorage
npm install

为了说明我们的更改,只要我们存储新值
,我们只需在src/drivers/memory.ts中添加一个简单的console.log

    ...
    setItem(key, value) {
      console.log(`setting key ${key} with value ${value}`)
      data.set(key, value);
    },
    ... 

现在运行npm run build,以确保我们的本地更改已准备就绪

在我们的主要软件包中覆盖依赖性,并进行本地更改

我们完成本地更改后,现在我们准备覆盖我们的依赖。打开我们的nuxt项目的package.json,然后在devDependencies部分中,我们将带有储藏包的本地路径,通往我们的分叉解锁软件包。当然,这取决于您的需求,无论是更改devDependencies还是dependencies部分。

  // package.json
  // other settings...
  "devDependencies": {
    "unstorage" : "file:/full/path/to/your/forked-unstorage",
    // other dependencies...

请注意,我们在依赖关系位置使用file:<path>格式。现在,我们将新的overrides部分添加到我们的软件包JSON。在这里,我们需要根据依赖树木进行调整。在我们的情况下,解开是Nitros Server Engine的依赖性,而Nuxtjs的依赖性。因此,我们的overrides部分看起来像这样:

  // package.json
  // other settings...  
  "overrides": {
    "nuxt": {
      "nitropack": {
        "unstorage": "$unstorage"
      }
    }
  }
}

现在运行npm update我们的nuxt文件夹以更新我们的依赖项,然后重新启动本地NUXT服务器。我们可以通过在我们的NUXT文件夹上运行ls -al node_modules/unstorage确认,并看到我们的UnStorage文件夹已更改为指向我们的叉子拆卸文件夹的链接:

Content of our latest unstorage local folder

现在,当我们尝试NUXT应用程序时,它将打印出我们的最新更改:

Result of our latest changes

暂时发布我们的更改

我们在本地成功地覆盖了我们的依赖性。现在在我们的舞台或生产环境中使用它吗?实际上,我们需要公开提供更改。最好的方法当然是将其合并到上游官方的包装中。您可以在此处向上游回购创建一个新的拉请请求,并且存储库维护者将其合并到代码库中,您可以在项目中使用它。当然,这很少会很快发生,所以我们的选择是将其发布在Github中。 NPM实际上支持using github repo & branch as NPM package,因此我们将在此处使用此方法。

首先,让我们在本地文件夹中创建一个新的分支,而不是将构建文件夹提交新的分支。然后将其推入您自己的github仓库。

# in our forked unstorage folder
git checkout -b my-build-branch
git add -f dist
git commit 'example npm build'
git push -o origin my-build-branch

您可以看到my branch in my github account供参考。在那里,您可以看到它包含当时包含我本地构建的dist文件夹。就我而言,dist文件夹实际上包含在unstorage repo的.gitignore中,因此我需要运行git add -f dist才能将文件夹强制添加到我的提交中。

现在,我们准备再次更新package.json。使用我们的公共GitHub repo&Branch更新我们的devDepencies / dependecies部分。例如,在我的情况下是:

  // package.json
  // other settings...
  "devDependencies": {
    "unstorage": "azophy/unstorage#my-build-branch",

然后再次运行npm update。现在您准备在项目上使用新叉子。

结论

我希望本文可以为您提供有关如何自己替换NPM依赖性的清晰概述。如果您发现缺乏任何东西,请随时发表评论。