-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add new css parser - postcss #1458
Conversation
|
} | ||
getSelectors(ast.stylesheet); | ||
const mediaFeatures = css | ||
.findAll(newAst, (node) => node.type === 'MediaFeature') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly some further optimizations we could even make here by using the css.walk
method to only traverse the AST once (rather than twice like I assume findAll
is doing)
packages/rrweb-snapshot/package.json
Outdated
@@ -1,6 +1,6 @@ | |||
{ | |||
"name": "rrweb-snapshot", | |||
"version": "2.0.0-alpha.13", | |||
"version": "2.0.0-alpha.12", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably be 13
?
This is great and something I thought we might get to 'some day' after the recent fixes to css.ts. Would you be able to post a before/after of the built file sizes from this change; i.e.
One of the reasons css.ts was ported over was so that we could tree shake it a bit. |
Something isn't right here because I'm getting the same values when running
Before
After
|
In a significant update here I moved to using This massively simplifies the I've moved around some test files to better separate concerns. Some of the tests were "testing the framework" given they had been copied over from https://github.com/reworkcss/css/blob/master/test/parse.js. I removed any that were no longer relevant but left any of the cases added in https://github.com/rrweb-io/rrweb/pull/1440/files#diff-ca07555d1c1965f9c7ef3b5df3772a19953138b8eac62deb7786e549b25b455d as we know they've specifically broken in the past and we would like to avoid breaking them in the future |
Super! What sort of filesize numbers are there with the |
Sorry @eoghanmurray, probably wasn't clear but I updated my earlier comment with latest build numbers having run
|
@@ -9,6 +9,9 @@ import { | |||
} from './types'; | |||
import { isElement, Mirror, isNodeMetaEqual } from './utils'; | |||
|
|||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires | |||
const postcss = require('postcss'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with the various import methods, but feel this needs a bit of an explanation as to why you are doing it this way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is causing tests to fail with require is not defined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it that we need a typescript version of https://github.com/giuseppeg/postcss-pseudo-classes
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This require business might be fixed with this PR: #1033
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the heads up @Juice10. I've been meaning to get back to this PR but have had some vacation recently. The good news is that this seems to have resolved all known CSS issues for us. I can hold off until the Vite changes are merged if that is imminent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@daibhin, PR has been merged, although what you have done (replacing require by import) seems perfectly good
Hopefully the following doesn't derail the conversation, and even if we go ahead with the following, that doesn't detract from the worth of the current PR... So okay I just had a thought; all this CSS processing is on the replay side, right? === edit: I've drafted this up in #1480 |
@eoghanmurray cleaned up the whitespacing but bringing in the commit you mentioned. Also rebased to include the new test (it passed without changes). The current failing test seems unrelated but perhaps you can run it again |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broadly approve but have a few questions before merging.
}, | ||
}; | ||
|
||
// Adapted from https://github.com/giuseppeg/postcss-pseudo-classes/blob/master/index.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, and I think I questioned somewhere whether we needed to import this.
I'm having some doubts now though, as just notice the following is possible with that plugin:
restrictTo: ['hover'],
did you consider that?
This approach of copying over a subset of the code has it's attractions too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered adding the package but thought it easier just to copy the code. When I inlined it there were a bunch of options we didn't really need e.g. restrictTo
so just simplified the whole thing down. We can always go back and add the original in future, but I chose to go with the simpler (no import / no extra options) until we knew if we needed any more
value: val ? trim(val[0]).replace(commentre, '') : '', | ||
}); | ||
selectorParts.forEach(function (selectorPart) { | ||
const pseudos = selectorPart.match(/::?([^:]+)/g); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could possibly be more specific and include the hover
string here given we know that's what we will be matching against
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as in that's the only one we need to support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually finds all pseudo elements on a selector, not just the hover. I simplified a different regex down in https://github.com/rrweb-io/rrweb/pull/1458/files#diff-8561a438ce9ce73d7e38ce75f7971111e91ea0365bf4588a82620655d8fc8e14R55
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did that commit make it in to the merge? I can't see anything by following the link above? I'm still seeing const pseudos = selectorPart.match(/::?([^:]+)/g);
in current version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I wrote up a simplified version in #1535, which I'm just looking at as it has a failing test; however I'm not so sure that the test failure isn't more correct!
We added the test in question in #1440 and it looks like the following:
body > ul :is(li:not(:first-of-type) a:hover, li:not(:first-of-type).active a) {background: red;}
The focus then was on ensuring that the above wasn't parsed as two separate selectors because of the internal comma, however that hasn't broken, but I think we missed that there was also a :hover
in there which should mean that the whole selector should be duplicated (which is how the test fails).
In the version from this PR, everything between the brackets of :is
is bundled in with the :is
, so the internal :hover
is effectively ignored. I haven't investigated why it was ignored previously. I'll duplicate this comment over in #1535 if you'd prefer to continue conversation there.
@Juice10 thanks for fixing up the imports. Do you know if the failing test is related to my changes somehow? |
Example: FAIL test/document-nodejs.test.ts > RRDocument for nodejs environment > RRDocument API > querySelectorAll TypeError: e[api] is not a function ❯ byTag ../../node_modules/nwsapi/src/nwsapi.js:390:37 ❯ Array.<anonymous> ../../node_modules/nwsapi/src/nwsapi.js:327:113 ❯ collect ../../node_modules/nwsapi/src/nwsapi.js:1578:32 ❯ Object._querySelectorAll [as select] ../../node_modules/nwsapi/src/nwsapi.js:1533:36 ❯ RRDocument.querySelectorAll src/document-nodejs.ts:96:24
@daibhin failing test was for 2872d0e was due to an upgraded package, thats fixed now (by locking the package version). The failure for c7153b7 seems to be due to jest being extended where we switched over to vitest. I just fixed that issue, but it looks like a chunk of the :hover tests are failing (you'll see that soon for 9df9946 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks really good, and is so much easier to adapt!
* feat: add new css parser * make selectors change * selectors and tests * media changes * remove old css references * better variable name * use postcss and port tests * fix media test * inline plugins * fix failing multiline selector * correct test result * move tests to correct file * cleanup all tests * remove unused css-tree * update bundle * cleanup dependencies * revert config files to master * remove d.ts files * update snapshot * reset rebuilt test * apply fuzzy css matching * remove extra test * Fix imports * Newer versions of nswapi break rrdom-nodejs tests. Example: FAIL test/document-nodejs.test.ts > RRDocument for nodejs environment > RRDocument API > querySelectorAll TypeError: e[api] is not a function ❯ byTag ../../node_modules/nwsapi/src/nwsapi.js:390:37 ❯ Array.<anonymous> ../../node_modules/nwsapi/src/nwsapi.js:327:113 ❯ collect ../../node_modules/nwsapi/src/nwsapi.js:1578:32 ❯ Object._querySelectorAll [as select] ../../node_modules/nwsapi/src/nwsapi.js:1533:36 ❯ RRDocument.querySelectorAll src/document-nodejs.ts:96:24 * Migrate from jest to vitest * Order of selectors has changed with postcss * Remove unused eslint --------- Co-authored-by: Justin Halsall <[email protected]>
* feat: add new css parser * make selectors change * selectors and tests * media changes * remove old css references * better variable name * use postcss and port tests * fix media test * inline plugins * fix failing multiline selector * correct test result * move tests to correct file * cleanup all tests * remove unused css-tree * update bundle * cleanup dependencies * revert config files to master * remove d.ts files * update snapshot * reset rebuilt test * apply fuzzy css matching * remove extra test * Fix imports * Newer versions of nswapi break rrdom-nodejs tests. Example: FAIL test/document-nodejs.test.ts > RRDocument for nodejs environment > RRDocument API > querySelectorAll TypeError: e[api] is not a function ❯ byTag ../../node_modules/nwsapi/src/nwsapi.js:390:37 ❯ Array.<anonymous> ../../node_modules/nwsapi/src/nwsapi.js:327:113 ❯ collect ../../node_modules/nwsapi/src/nwsapi.js:1578:32 ❯ Object._querySelectorAll [as select] ../../node_modules/nwsapi/src/nwsapi.js:1533:36 ❯ RRDocument.querySelectorAll src/document-nodejs.ts:96:24 * Migrate from jest to vitest * Order of selectors has changed with postcss * Remove unused eslint --------- Co-authored-by: Justin Halsall <[email protected]>
## Summary rrweb-io/rrweb#1458 introduced issues with certain customers' applications such as: ```js Uncaught CssSyntaxError: <css input>:1778:83: Unknown word Uncaught CssSyntaxError: <css input>:1:65502: Unknown word Uncaught CssSyntaxError: <css input>:1:2: Unclosed block ``` example of such a session: https://app.highlight.io/92422/sessions/qGaSpGVNh4Ewqj8k23lNC5zNtcB1 affected highlight.run clients are >=9.1.5 with certain bundled CSS this may also affect the replayer so the new frontend usage of rrweb is affected ## How did you test this change? fixes playback of [session that used to not play](https://app.highlight.io/92422/sessions/qGaSpGVNh4Ewqj8k23lNC5zNtcB1) <img width="1487" alt="Screenshot 2024-08-19 at 15 54 49" src="https://github.com/user-attachments/assets/305779eb-6ee4-489f-999c-3c608f04d86b"> new client build working <img width="1403" alt="Screenshot 2024-08-19 at 16 07 24" src="https://github.com/user-attachments/assets/f6a46f8f-827f-42b0-acc2-cd01fc2ae249"> ## Are there any deployment considerations? new changeset ## Does this work require review from our design team? no
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## [email protected] ### Patch Changes - 262a073: revert postcss changes to css parsing in rrweb <rrweb-io/rrweb#1458> introduced a new CSS parser which causes issues with certain large CSS files ## @highlight-run/[email protected] ### Patch Changes - Updated dependencies [262a073] - [email protected] - @highlight-run/[email protected] - @highlight-run/[email protected] ## @highlight-run/[email protected] ### Patch Changes - Updated dependencies [262a073] - [email protected] ## @highlight-run/[email protected] ### Patch Changes - Updated dependencies [262a073] - [email protected] - @highlight-run/[email protected] - @highlight-run/[email protected] --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Vadim Korolik <[email protected]>
* feat: add new css parser * make selectors change * selectors and tests * media changes * remove old css references * better variable name * use postcss and port tests * fix media test * inline plugins * fix failing multiline selector * correct test result * move tests to correct file * cleanup all tests * remove unused css-tree * update bundle * cleanup dependencies * revert config files to master * remove d.ts files * update snapshot * reset rebuilt test * apply fuzzy css matching * remove extra test * Fix imports * Newer versions of nswapi break rrdom-nodejs tests. Example: FAIL test/document-nodejs.test.ts > RRDocument for nodejs environment > RRDocument API > querySelectorAll TypeError: e[api] is not a function ❯ byTag ../../node_modules/nwsapi/src/nwsapi.js:390:37 ❯ Array.<anonymous> ../../node_modules/nwsapi/src/nwsapi.js:327:113 ❯ collect ../../node_modules/nwsapi/src/nwsapi.js:1578:32 ❯ Object._querySelectorAll [as select] ../../node_modules/nwsapi/src/nwsapi.js:1533:36 ❯ RRDocument.querySelectorAll src/document-nodejs.ts:96:24 * Migrate from jest to vitest * Order of selectors has changed with postcss * Remove unused eslint --------- Co-authored-by: Justin Halsall <[email protected]>
rrweb-snapshot
parses stylesheets to adapt the CSS for playbackIn certain cases the parsing wasn't always correct:
PostHog/posthog#21427
#1379
Which led to improved CSS selector efforts first included in
[email protected]
(#1401)Sadly this caused playback issues that consumed 100% CPU and froze playback
PostHog/posthog#21791
CSS parsing is performed in the https://github.com/rrweb-io/rrweb/blob/master/packages/rrweb-snapshot/src/css.ts which was pulled from https://github.com/reworkcss/css (which hasn't been updated in over 3 years)
I propose moving to https://github.com/csstree/csstree which creates an actual AST which can be used to effectively debug via https://astexplorer.net
I couldn't figure out some import issues in the
test/integration.test.ts
All
test/css.test.ts
tests still pass which confirms this is as good as the trickiest cases previously handled without any of the slowness introduced in #1401