Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Metadata-only config loads run `resolveConfig`, which reads `node_modules/.modules.yaml`; cached tasks that run `vp`, `oxlint` or `oxfmt` miss after every reinstall

未关闭
#2,845 0 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 1 天内回复

@wan9chi 已经在做这个了。

开始于 2026年9月28日。

评估

这个 Issue 还没有评估数据。

描述

pending triage
Describe the bug

Every metadata read of vite.config.* goes through Vite's full resolveConfig(…, 'build'): vp run's task lookup, vp check/lint/fmt/staged/pack/create (packages/cli/src/resolve-vite-config.ts:86-101), and the loadViteConfigField that oxlint and oxfmt call in Vite+ mode. resolveConfig runs resolveServerOptions, which reads node_modules/.modules.yaml to derive the dev server's server.fs.allow from pnpm's virtualStoreDir. Nothing about reading a run, lint or fmt block needs that, and lazyPlugins cannot help: the read is Vite's own, not a plugin's.

Under Vite Task this is a cache bug. pnpm rewrites .modules.yaml on every install (prunedAt) and it carries the machine's storeDir, so with { auto: true } tracking any cached task whose process tree runs vp, oxlint or oxfmt records it as an input. The task misses after every reinstall and can never replay on another machine.

Stack, from an fs hook loaded through NODE_OPTIONS=--require:

readFileSync(node_modules/.modules.yaml)
    at resolveServerOptions        (@voidzero-dev/vite-plus-core/dist/vite/node/chunks/node.js:30392)
    at async resolveConfig         (…/chunks/node.js:42610)
    at async withConfigMetadataResolution (vite-plus/dist/define-config-DhEJaYRc.js:575)
    at async resolveUniversalViteConfig   (vite-plus/dist/resolve-vite-config-BJYYtfY3.js:75)

vp fmt --check src produces the same read from oxfmt/dist/cli.js:141 (loadViteConfigField → resolveConfig); oxlint's dist/js_config.js makes the identical call.

The only line that differs between two installs of the same lockfile:

-  "prunedAt": "Mon, 28 Sep 2026 12:55:07 GMT",
+  "prunedAt": "Mon, 28 Sep 2026 12:58:26 GMT",
Reproduction

Three files.

// package.json
{ "name": "probe", "private": true, "type": "module", "packageManager": "[email protected]", "devDependencies": { "vite-plus": "1.0.0" } }
// vite.config.ts
import { defineConfig } from 'vite-plus';

export default defineConfig({
  fmt: {},
  run: {
    tasks: {
      // A cached task whose process tree runs a `vp` built-in.
      fmt: {
        command: "sh -c 'vp fmt --check src'",
        cache: { input: [{ auto: true }], output: [] },
      },
    },
  },
});
// src/a.ts
export const a = 1;
Steps to reproduce
vp install
export VITE_CACHE_PATH="$PWD/.task-cache"   # keep the task cache outside node_modules
vp run fmt                                  # executes
vp run fmt                                  # ◉ cache hit, replaying
rm -rf node_modules && vp install           # same lockfile, same versions
vp run fmt                                  # ○ cache miss: 'node_modules/.modules.yaml' modified

Replacing the two resolveConfig calls (vite-plus's resolveViteConfig and oxfmt's loadViteConfigField) with loadConfigFromFile(configEnv, configFile, cwd) and repeating the steps: the run after the reinstall is a cache hit, and the hook records zero reads of .modules.yaml.

Suggested fix

Load metadata with Vite's public loadConfigFromFile instead of resolveConfig. It evaluates the config file (including function configs, with a ConfigEnv) and returns the user config object, which is all the metadata paths read.

// packages/cli/src/resolve-vite-config.ts
export async function resolveViteConfig(cwd: string, options?: ResolveViteConfigOptions) {
  const { loadConfigFromFile } = await import('./index.js');
  return withConfigMetadataResolution(async () => {
    let configFile: string | undefined;
    if (options?.traverseUp && !hasViteConfig(cwd)) {
      const workspaceRoot = findWorkspaceRoot(cwd);
      if (workspaceRoot) configFile = findViteConfigUp(path.dirname(cwd), workspaceRoot);
    }
    const result = await loadConfigFromFile(
      { command: 'build', mode: 'production', isSsrBuild: false, isPreview: false },
      configFile,
      cwd,
    );
    return result ? { ...result.config, configFile: result.path } : { configFile: undefined };
  });
}

Two notes:

  • resolveConfig also set process.env.NODE_ENV as a side effect; with loadConfigFromFile the caller decides. We default it explicitly in our patch.
  • oxlint's and oxfmt's loadViteConfigField need the same swap, or a vite-plus export they can call.

We have run exactly this as pnpm patches of vite-plus, oxlint and oxfmt in production CI since 2026-09-08, across 1.0.0-rc.0, rc.1 and 1.0.0.

Related: #2698 (the same loads happen up to 8× per vp staged), #1756 and #1580 (plugin side effects on the same path, addressed by lazyPlugins), #2307.

System Info
vite-plus 1.0.0 (project), vp 1.0.0-rc.1 (global launcher)
vite 8.3.1, rolldown 1.2.11, oxfmt 0.70.0, oxlint 1.85.0
Node.js v24.21.0 (project runtime), pnpm 12.4.1
macOS 27.0, arm64; the same miss was first observed on Linux CI runners (Ubuntu 24.04)
Used Package Manager

pnpm

Logs
$ sh -c 'vp fmt --check src' ○ cache miss: 'node_modules/.modules.yaml' modified, executing
Checking formatting...
All matched files use the correct format.
Finished in 69ms on 1 files using 10 threads.

Statistics:   1 tasks • 0 cache hits • 1 cache misses
Task Details:
  [1] probe#fmt: $ sh -c 'vp fmt --check src' ✓
      → Cache miss: 'node_modules/.modules.yaml' modified
Validations
主要语言
Rust
星标
5.8k
派生
267
平均合并
21 小时 2 分钟
30 天内合并 PR
149

环境准备

在 Codespaces 中打开

在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

voidzero-dev/vite-plus 的其他 Issue

查看 voidzero-dev/vite-plus 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。