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

Angular Schematics调用ng-new报Invalid Source (undefined)问题求助

解决Angular自定义Schematics调用ng-new后出现"Invalid source: undefined"的问题

问题根源

你碰到的这个错误,本质是后续调用的Angular官方Schematics(比如library)依赖projectName这个上下文变量,但它并没有自动从ng-new的执行流程中传递过来。Angular官方很多Schematics的schema里用了"$default": { "$source": "projectName" }来自动获取当前项目名,但在自定义Schematics的链式调用里,这个变量不会默认继承,所以就抛出了"Invalid source: undefined"的错误。

具体解决步骤

1. 从ng-new的执行结果中提取projectName

ng-new执行完之后,会生成angular.json文件,我们可以从这个文件里读取项目名称,这样比直接用传入的options.name更稳妥(毕竟用户可能在ng-new里改了名称参数):

import { chain, externalSchematic, Rule, Tree } from '@angular-devkit/schematics';

export function myFullSchematic(options: any): Rule {
  return chain([
    // 先执行ng-new,创建基础工作区
    externalSchematic('@schematics/angular', 'ng-new', {
      name: options.name,
      createApplication: false, // 如果只做库项目,建议关闭应用创建
      skipGit: false, // 根据你的需求调整
      // 其他ng-new需要的参数
    }),
    // 这里用一个中间Rule来获取projectName,再执行后续操作
    (tree: Tree) => {
      // 读取angular.json解析出项目名
      const workspaceContent = tree.read('angular.json')!.toString();
      const workspaceConfig = JSON.parse(workspaceContent);
      // 取第一个项目名,或者直接用options.name(如果确定不会变的话)
      const projectName = Object.keys(workspaceConfig.projects)[0];

      // 链式执行后续的Schematics,显式传递projectName
      return chain([
        externalSchematic('@schematics/angular', 'library', {
          name: `${options.name}-core`, // 你的库名称
          projectName: projectName, // 关键:显式传入projectName
          // 其他library参数,比如prefix、skipTests等
        }),
        // 你的自定义配置规则:替换Jest、添加CI配置等
        setupJestConfig(projectName),
        addCIConfiguration(),
      ]);
    },
  ]);
}

2. 给所有依赖projectName的官方Schematics显式传参

不管是调用library、component还是其他官方Schematics,只要它的schema里用到了$source: projectName,就必须在externalSchematic的参数里明确传入projectName,不能依赖自动获取。

3. 自定义Schematics里统一从angular.json取项目名

如果你自己写的自定义规则也需要用到项目名,建议直接从angular.json读取,而不是依赖上下文变量,这样更稳定,避免上下文传递的问题。

你的方案可行性分析

完全可行!而且这是非常聪明的做法:

  • 复用官方@schematics/angular的逻辑,既能享受Angular官方的更新(比如新的配置项、修复的bug),又不用自己从零实现所有创建逻辑,只需要在官方基础上做自定义扩展。
  • 后续用CI自动化测试也非常适配:你可以在CI流程里自动运行你的自定义Schematics生成项目,然后执行lint、测试、构建等步骤,确保每次依赖升级后功能都正常。

可选的替代思路

如果你觉得链式传递变量有点繁琐,也可以考虑两种替代方式,但都不如你当前的方案高效:

  • 预定义模板文件:直接创建一个配置好Jest、CI的工作区模板,然后用Schematics复制模板并替换变量。但缺点是官方Schematics更新时,你得手动同步模板,维护成本高。
  • 利用Schematics上下文传递变量:通过context对象把projectName传递给后续规则,但这种方式需要对Angular Devkit的上下文机制有更深的理解,出错概率更高。

总的来说,你现在的思路是最优的,只需要补充提取并传递projectName的逻辑,就能解决这个错误。

内容的提问来源于stack exchange,提问作者Matt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:49:48