插件窝 干货文章 修复包依赖关系

修复包依赖关系

ember 我们 codemod class 532    来源:    2024-10-23

embroider 和 pnpm 都要求包正确声明其依赖项:如果使用则列出依赖项(当且仅)。

在使用yarn@v1的大型单一存储库(考虑具有许多ember插件和node包的ember应用程序)上工作时,这是很难做到的。开发人员可能会忘记更新 package.json,因为即使缺少依赖项,ember 应用程序也可以构建和运行,只要从另一个包中拉入即可。

因此,构建和运行都无法告诉我们某个包是否未正确声明其依赖项。我们还能如何修复 package.json 以便引入 embroidery 和 pnpm?

1.静态代码分析

给定一个文件,我们可以看到应该存在哪些依赖项,因为我们知道 javascript 和 ember 是如何工作的。

例如,要显示 javascript(或 typescript)文件,

import { setupintl } from 'ember-intl/test-support';
import { setuprenderingtest as upstreamsetuprenderingtest } from 'ember-qunit';

export function setuprenderingtest(hooks, options) {
  upstreamsetuprenderingtest(hooks, options);

  // additional setup for rendering tests can be done here.
  setupintl(hooks, 'de-de');
}

从 import 语句中我们可以看出该包依赖于 ember-intl 和 ember-qunit。

并且,如果要显示模板文件,

{{page-title "my app"}}

<welcomepage></welcomepage>

{{outlet}}

我们对 ember 及其插件生态系统的了解分别引导我们进入 ember-page-title、ember-welcome-page 和 ember-source。即使事情是隐式的(例如双花括号中的歧义、模块解析、服务注入),由于 ember 强大的约定,我们也可以高精度地猜测资产的来源。

2. 代码修改

不过,我们不应该手动检查每个包中的每个文件。这既耗时又容易出错。

相反,我们使用@codemod-utils 编写一个codemod(实际上是一个linter)。对于每个包,codemod 都会解析相关内容并创建应该存在的依赖项列表(“实际”)。然后,它将列表与 package.json 中的列表进行比较(“预期”)。

要分析隐式代码,需要有一个已知资产列表(一次性创建),它将我们想要考虑的每个包映射到其资产。我们可以使用 map 来记录这些信息。

const known_assets = new map([
  [
    'ember-intl',
    {
      helpers: [
        'format-date',
        'format-list',
        'format-message',
        'format-number',
        'format-relative',
        'format-time',
        't',
      ],
      services: ['intl'],
    },
  ],
  [
    'ember-page-title',
    {
      helpers: ['page-title'],
      services: ['page-title'],
    },
  ],
  [
    'ember-welcome-page',
    {
      components: ['welcome-page'],
    },
  ],
]);

现在,由于 ember 的工作原理,对 import 语句的简单分析可能会导致误报。举个例子:

import route from '@ember/routing/route';
import fetch from 'fetch';

当我们不提供正确的上下文时(即此代码适用于 ember),codemod 会将 @ember/routing 和 fetch 视为依赖项,而不是 ember-source 和(可能)ember-fetch。 codemod 应该以这样的方式呈现其分析,以便我们可以轻松检查误报。

// Results for my-package-37

{
  missingDependencies: [
    'ember-asset-loader',
    'ember-truth-helpers'
  ],
  unusedDependencies: [
    '@babel/core',
    'ember-auto-import',
    'ember-cli-babel'
  ],
  unknowns: [
    'Services - host-router (addon/routes/registration.ts)',
  ]
}

3. 结果

我(几天内)构建的 codemod 在 49 秒内分析了包含 129 个包的生产存储库。总共有 12,377 个文件,但 codemod 只知道分析其中的 6,013 个(不到一半)。平均每个文件 0.008 秒,每个包 0.38 秒!

要了解有关编写 codemod 的更多信息,请查看 @codemod-utils 的主要教程。