You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vite/Rollup的transform或transformIndexHtml中获取输入键名?

如何在Vite/Rollup的transform钩子中获取当前编译的输入文件名

问题场景

我要开发一款文件路由Vite插件,翻了Awesome Vite和Rollup Awesome没找到合适的,也懒得挨个筛选。核心问题是Rollup的input选项可以给文件指定名称,用来关联输出和入口文件,但不知道怎么在Rollup的transform或者Vite的transformIndexHtml钩子中拿到当前的转换名称。

我的需求很明确:在transform的处理函数里拿到类似about/know-me的输入名称,把HTML里的%SCRIPT_SRC%替换成对应路径。整体构想是插件扫描所有以.page.tsx结尾的脚本文件,生成对应的.html页面,同时根据文件名存储临时配置,这样就能调用config[name].script。说白了就是想知道怎么在transform函数里同步或者异步获取当前编译的输入文件名。

解决方案

核心思路

在Vite插件里,最直接的方式是先在configResolved钩子中收集「文件路径→input名称」的映射表,之后在transform或transformIndexHtml钩子中,通过当前文件的路径反向匹配对应的input名称。如果是动态生成的HTML,也可以在生成时嵌入标识,直接在transform阶段提取。

具体实现步骤

  1. 提前收集入口映射
    在插件的configResolved钩子中,遍历Rollup的input配置,把每个入口的绝对路径和对应的input名称存进映射表:

    // 插件实例中初始化映射表
    this.inputMap = new Map();
    
    // 在configResolved钩子中填充映射
    configResolved(config) {
      const { root, build: { rollupOptions: { input } } } = config;
      for (const [inputName, filePath] of Object.entries(input)) {
        const absFilePath = path.resolve(root, filePath);
        this.inputMap.set(absFilePath, inputName);
      }
      // 同时存储自定义配置,比如从.page.tsx文件解析的配置
      this.pageConfigs = await this.scanPageConfigs(root);
    }
    
  2. 在transform钩子中匹配input名称
    拿到当前转换文件的绝对路径,去映射表里找对应的input名称,再替换模板变量:

    async transform(code, id) {
      // 只处理HTML文件
      if (!id.endsWith('.html')) return code;
    
      const inputName = this.inputMap.get(id);
      if (!inputName) return code;
    
      // 从自定义配置中拿到脚本路径
      const scriptSrc = this.pageConfigs[inputName]?.script || `/assets/${inputName}.js`;
      return code.replace('%SCRIPT_SRC%', scriptSrc);
    }
    
  3. 适配transformIndexHtml钩子
    这个钩子的上下文参数context包含bundle信息,可以通过chunk的name关联到input名称:

    transformIndexHtml(html, context) {
      if (!context.bundle) return html;
    
      // 找到当前HTML对应的chunk
      const targetChunk = Object.values(context.bundle).find(
        chunk => chunk.type === 'asset' && chunk.fileName === context.filename
      );
    
      if (!targetChunk?.name) return html;
    
      const scriptSrc = this.pageConfigs[targetChunk.name]?.script || `/assets/${targetChunk.name}.js`;
      return html.replace('%SCRIPT_SRC%', scriptSrc);
    }
    

备用方案:嵌入标识直接提取

如果是动态生成的HTML,建议生成时就把input名称以注释或自定义属性嵌入,避免路径匹配的问题:

<!-- input-name: about/know-me -->
<script src="%SCRIPT_SRC%"></script>

然后在transform中直接解析这个注释:

transform(code) {
  const matchResult = code.match(/<!-- input-name: (.*?) -->/);
  if (!matchResult) return code;

  const inputName = matchResult[1];
  const scriptSrc = this.pageConfigs[inputName]?.script || `/assets/${inputName}.js`;
  return code.replace('%SCRIPT_SRC%', scriptSrc);
}

内容的提问来源于stack exchange,提问作者Farhan M Sabran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 20:30:28