Skip to content
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

fix: hydrate in twind-v1-plugin #1050

Merged
merged 28 commits into from
Mar 12, 2023

Conversation

y3km21
Copy link
Contributor

@y3km21 y3km21 commented Feb 26, 2023

This PR is a slightly modified version of hydrate from twind-v1-plugin (#946).

In this plugin, Cssrules of SSR are resumed by cssom() of twind.
There are demos for each of #946 and this PR. (I added a lot of classes to compare the performance.)

What is the issue with #946 plugin?

Twind's getSheet returns the sheet created from cssom to which resume is assigned, but since SSR's HtmlStyleSheet cannot be targeted to this sheet, resume at setup doesn't make sense.
As a result, CSSRules of ClientSide that partially overlaps with ServerSide is inserted.
Demo
pr946-demo-styles

I think this should be improved.

What was changed?

I made a sheet created by cssom with SSR's HtmlStyleSheet as the target, and bind the resume of the sheet created by getSheet.

export default function hydrate(options: TwindConfig) {
  const elem = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement;
  const sheet = cssom(elem);

  sheet.resume = getSheet().resume.bind(sheet);
  document.querySelector('[data-twind="claimed"]')?.remove();

  setup(options, sheet);
}

Demo
thisPR-demo-styles

The resume of the sheet is working, so there is no duplication.

What about performance?

I compared the performance of each plugin on chrome.

pr946-demo-per

thisPR-demo-per

The Scripting time for each is about the same.


Thank you very much for reading through to the end.
Please let me know if my understanding is wrong.🙏

Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Is it possible to write a test for this fix?

@y3km21
Copy link
Contributor Author

y3km21 commented Feb 27, 2023

@ry Yes, I will do it soon!
I have a few questions about creating a test.

  • Should I create a test like fresh/tests/fixture_twind-pr1050?
  • Should the content of the test be such that this PR passes and feat: add twind v1 plugin #946 fails?(For example, compare stylesheets in islands)

@hashrock
Copy link
Contributor

Thank you!

Should I create a test like fresh/tests/fixture_twind-pr1050?

just fresh/tests/fixture_twind is also fine!

Should the content of the test be such that this PR passes and #946 fails?(For example, compare stylesheets in islands)

Yes, it would be helpful!

@y3km21
Copy link
Contributor Author

y3km21 commented Feb 28, 2023

@hashrock Thanks!
I'll write a test.

@y3km21
Copy link
Contributor Author

y3km21 commented Mar 1, 2023

I added test!
The test contents are as follows

  1. Ensure that twind compiles class in static page.
  2. Ensure that twind does not cause duplication of cssrules in islands.
  3. Ensure that twind compiles dynamically inserted classes in islands.

deno task test results would look like this

Test No. #1050 #946 twind v0.16 plugin
1
2
3

Please let me know if I am missing or wrong!

tests/twind_test.ts Outdated Show resolved Hide resolved
tests/twind_test.ts Outdated Show resolved Hide resolved
tests/twind_test.ts Outdated Show resolved Hide resolved
tests/twind_test.ts Outdated Show resolved Hide resolved
tests/twind_test.ts Outdated Show resolved Hide resolved
Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the test. I think this looks good but it could use some clean up still.

@y3km21
Copy link
Contributor Author

y3km21 commented Mar 7, 2023

@ry Thanks for the review!
I have corrected the areas you reviewed.

But there is one thing I couldn't solve.
The textDecoderStream called here leaks.

const lines = serverProcess.stdout
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());

I have tried calling cancel() of lines and externally TextDecoderStream (ex. const decoder = TextDecoderStream();), but could't solve it.

For now, I got the textDecoder's rid from the resourceMap and manually close the resource.

const terminate = async () => {
await browser.close();
serverProcess.kill("SIGKILL");
await serverProcess.status;
// TextDecoder leaks, so close it manually.
const denoResourcesMap = new Map(
Object.entries(Deno.resources()).map(([rid, representation]) => {
return [representation, parseInt(rid)];
}),
);
const textDecoderRid = denoResourcesMap.get("textDecoder");
if (textDecoderRid != null) {
Deno.close(textDecoderRid);
}
};

Is there a correct cancel() call?
Or should I add sanitizeResources: false?

@y3km21
Copy link
Contributor Author

y3km21 commented Mar 8, 2023

Without --trace-ops, a leak occurred, so I added delay(10) before t.step.

@hashrock hashrock mentioned this pull request Mar 9, 2023
@hashrock hashrock merged commit 7f2ec61 into denoland:main Mar 12, 2023
@y3km21 y3km21 deleted the twind-v1-plugin-resume-working branch March 13, 2023 01:25
@y3km21
Copy link
Contributor Author

y3km21 commented Mar 13, 2023

@hashrock Thanks for merging!

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.

None yet

3 participants