Skip to content

Expose template source locations in dev mode to jump from the DOM to the template #70927

Description

@aminesbdev

Which @angular/* package(s) are relevant/related to the feature request?

compiler, compiler-cli, core

Description

When I want to change something I see on the page, the slowest part isn't the edit itself (template/style HMR is great), it's finding where that element lives. I open the browser inspector, look at markup full of _ngcontent-* attributes, guess which component it belongs to, and then search for the file and the line in my editor.

Other ecosystems solve this with a "click an element, open it in your editor" tool (Svelte's inspector, Vue DevTools' open-in-editor, click-to-component for React). Angular doesn't have one, but most of the pieces are already in the framework:

  • Add internal-only debugging attributes #58982 added ɵɵattachSourceLocations, which puts a data-ng-source-location="src/app/foo.html@o:…,l:…,c:…" attribute on every template element. The PR description says it's aimed at internal tools but that "we may consider exposing this in dev mode in the future".
  • refactor(compiler-cli): add compiler option for enabling source locations #70303 added the enableTemplateSourceLocations compiler option (under the internal Bazel/g3 options).
  • ng serve runs on Vite, which already exposes /__open-in-editor (the launch-editor middleware used by Vite, Vue and Nuxt). It detects the running editor (VS Code, Cursor, WebStorm, Zed…) or uses the LAUNCH_EDITOR env variable, so Angular doesn't need to know anything about editors.

I wanted to see how far these get us, so I built a small prototype on a fresh ng new app (v22.2.0). I enabled the option in a tsconfig.dev.json used only by the development configuration. Then I added a ~120 line dev-only script: hold Alt and hover to see the component and file:line:col, Alt+click calls /__open-in-editor?file=<path>:<line>:<col> and the editor opens on that line.

Prototype: https://github.com/aminesbdev/angular-source-inspector (see src/dev/source-inspector.ts and tsconfig.dev.json).

It worked better than I expected. I checked the locations in headless Chrome, and each one lands on the exact tag: external templates (product-card.html:6:3 → <button class="buy">), inline templates (price-tag.ts:7:7 → the <strong> inside the template string), and projected content. The compiler's project-relative paths work as-is with /__open-in-editor, since it resolves them from the directory where ng serve runs. With a real click, my editor opened on the right line. I did have to set LAUNCH_EDITOR because launch-editor doesn't detect my editor yet, but that's a one-line fix on their side.

A few things I noticed along the way:

  • Paths end up in production if you just turn it on. Putting enableTemplateSourceLocations in tsconfig.app.json ships every template path in the production bundle (about 450 bytes on a three-component app). I only avoided it with a separate tsconfig for the development configuration, which isn't something most people would think to do.
  • A component's host element points to the template where it's used, not to its own template. That's probably right for this use case, but a tool would likely want both. The component's own class location is already available through its debug info, but only via ɵcmp.
  • I only tried a single-project workspace. In a multi-project workspace, the compiler's paths and the directory /__open-in-editor resolves from might not match.
  • /__open-in-editor comes from Vite and isn't something the Angular CLI documents, so tooling built on it would want the CLI to keep it around.

Proposed solution

Roughly in this order:

  1. Make source locations safe to enable in dev: either the emitted instruction is dev-mode only, or the option is documented as a dev-only one. Then make the option public.
  2. Have ng serve turn it on by default for development builds (that part would be an angular-cli issue, I can open it there).
  3. Build tooling on top: an "Open in editor" action in Angular DevTools and/or an Alt+click overlay like the prototype. This could also start as a community package once the attribute is available.

I'm happy to help with any of this if you think it's worth doing. I'm especially interested in steps 1 and 3.

Alternatives considered

  • Component debug info only (ClassDebugInfo, already emitted in dev mode). This gives the component class file and line, which is useful as a fallback, but not the template or the specific element. Reading it also requires ɵcmp.
  • Chrome DevTools workspaces. They let you save edits back to files, but they don't tell you which component template an element comes from.
  • Third-party tools could do this today by reading private fields, but that breaks easily. A dev-mode attribute emitted by the compiler is a much more stable base to build on.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: compilerIssues related to `ngc`, Angular's template compilergemini-triagedLabel noting that an issue has been triaged by gemini

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions