Skip to content

Conversation

@thecrypticace
Copy link
Contributor

@thecrypticace thecrypticace commented Dec 2, 2025

There are two performance improvements here that both come down to caching:

  • We call indexToPosition a lot. Every time this is called it takes the string passed in and re-computes the indices every time. There's no need for this so we have a small, module-level LRU cache to store the data.

This should eventually be replaced with parsing and storing data up front when files are edited instead of just doing this whenever we receive a request. That would negate the need for a module-level cache.

  • We call compile() and candidatesToCss a lot as well. This is expected but 90% of the time the classes passed in have already been seen. We take the generated CSS and convert to a PostCSS node because a lot of the implementation uses that internally. There's no need to go through the whole parse -> serialize -> re-parse routine like we are.

I've opted to store the compiled PostCSS roots on the designSystem.storage object (which will be created when it doesn't exist on old versions) and we'll return clones of those objects every time (since they may get mutated).

With this there's only one large-ish block in a left-heavy profile: findClassListsInHtmlRange. That is mostly related to the class attribute lexer. Fixing it will require us to scan document and store info about them when they change. We shouldn't need to run the class attribute lexer if the document hasn't changed. Fixing this will require some more work though.

Fixes #1503

This shows up *heavily* in profiles. What really needs to happen is necessary info is precomputed and parsed once after we recieve edits for files and then reused everywhere *until the next edit*. That’s a larger refactor so this is a stop gap measure until then.
This will help perf in two cases:
1. Repeated compilation of the same classes across requests
2. Compilation *of the same* class mulitple times in a single call

We store this data on the design system itself so that it gets invalidated and garbage collected when the design system is recreated on CSS file changes
@thecrypticace thecrypticace changed the title Improve perf in large files Improve performance in large files Dec 2, 2025
@thecrypticace thecrypticace marked this pull request as ready for review December 2, 2025 16:27
@thecrypticace thecrypticace merged commit 29eab26 into main Dec 3, 2025
12 checks passed
@thecrypticace thecrypticace deleted the fix/issue-1503 branch December 3, 2025 19:28
timsexperiments pushed a commit to timsexperiments/tailwindcss-intellisense that referenced this pull request Dec 4, 2025
* Bump bundled Tailwind CSS version

* Improve performance in large files (tailwindlabs#1507)

There are two performance improvements here that both come down to
caching:

- We call `indexToPosition` *a lot*. Every time this is called it takes
the string passed in and re-computes the indices every time. There's no
need for this so we have a small, module-level LRU cache to store the
data.

This should eventually be replaced with parsing and storing data up
front when files are edited instead of just doing this whenever we
receive a request. That would negate the need for a module-level cache.

- We call `compile()` and `candidatesToCss` *a lot* as well. This is
expected but 90% of the time the classes passed in have already been
seen. We take the generated CSS and convert to a PostCSS node because a
lot of the implementation uses that internally. There's no need to go
through the whole parse -> serialize -> re-parse routine like we are.

I've opted to store the compiled PostCSS roots on the
`designSystem.storage` object (which will be created when it doesn't
exist on old versions) and we'll return clones of those objects every
time (since they may get mutated).

With this there's only one large-ish block in a left-heavy profile:
`findClassListsInHtmlRange`. That is mostly related to the class
attribute lexer. Fixing it will require us to scan document and store
info about them when they change. We shouldn't need to run the class
attribute lexer if the document hasn't changed. Fixing this will require
some more work though.

Fixes tailwindlabs#1503

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: GitHub Action <action@github.com>
timsexperiments pushed a commit to timsexperiments/tailwindcss-intellisense that referenced this pull request Dec 5, 2025
* Bump bundled Tailwind CSS version

* Improve performance in large files (tailwindlabs#1507)

There are two performance improvements here that both come down to
caching:

- We call `indexToPosition` *a lot*. Every time this is called it takes
the string passed in and re-computes the indices every time. There's no
need for this so we have a small, module-level LRU cache to store the
data.

This should eventually be replaced with parsing and storing data up
front when files are edited instead of just doing this whenever we
receive a request. That would negate the need for a module-level cache.

- We call `compile()` and `candidatesToCss` *a lot* as well. This is
expected but 90% of the time the classes passed in have already been
seen. We take the generated CSS and convert to a PostCSS node because a
lot of the implementation uses that internally. There's no need to go
through the whole parse -> serialize -> re-parse routine like we are.

I've opted to store the compiled PostCSS roots on the
`designSystem.storage` object (which will be created when it doesn't
exist on old versions) and we'll return clones of those objects every
time (since they may get mutated).

With this there's only one large-ish block in a left-heavy profile:
`findClassListsInHtmlRange`. That is mostly related to the class
attribute lexer. Fixing it will require us to scan document and store
info about them when they change. We shouldn't need to run the class
attribute lexer if the document hasn't changed. Fixing this will require
some more work though.

Fixes tailwindlabs#1503

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: GitHub Action <action@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IntelliSense becomes very slow in large HTML projects

2 participants