From 5989bf012652c3f8f2d89b66fecb84cec3d95465 Mon Sep 17 00:00:00 2001 From: Dale Bustad Date: Wed, 5 Mar 2025 13:39:22 -0800 Subject: [PATCH] feat: style deduplication (#5264) * chore: reintroduce locker logic * Update packages/@lwc/integration-karma/test/component/LightningElement/index.spec.js Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * feat: added style dedup in ssr (not working yet) * fix: reference to runtime context on emit fn * chore: rename CompilationContext to RuntimeContext (it was wrong before) * chore: update SSR fixtures with dedupe keys * feat: accept prefix for style dedupe identifiers * feat: create @lwc/ssr-client-utils package with pre-hydration dedupe mechanism * chore: add big TODO comment * feat(lwc-style): add register util TODO: make it actually get bundled * feat(lwc-style): replace dummies with dumber dummies * test: the SSRv1 fixture tests against SSRv2 fixtures * chore: fix tests and test config * chore: get all SSRv1 tests to pass with new lwc-style stuff * chore: comments * chore: more comments * refactor: make it possible to disable style dedupe in SSRv2 * chore: provide `@lwc/ssr-client-utils/register` import * chore: add comment about bare import Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * chore: use FIXME instead of "Followup needed" Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * refactor: destructure for better readability * chore: add TODO * refactor: make createMistmatchError generic Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * chore: add comment explaining regexp Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * chore: fix imprecision in code comment Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * chore: add comment explaining why we need repeated exec on regexp * chore: indentation is 0 when falsey instead of null * chore: address nit Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * chore: remove console.log Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> * chore: add comment * chore: bump CI * chore: add skip file for flakey test --------- Co-authored-by: John Hefferman Co-authored-by: jhefferman-sfdc <83669775+jhefferman-sfdc@users.noreply.github.com> Co-authored-by: Will Harney <62956339+wjhsf@users.noreply.github.com> Co-authored-by: Will Harney --- package.json | 2 +- .../engine-core/src/framework/hydration.ts | 7 +- .../src/__tests__/fixtures.spec.ts | 1 + .../dynamic/expected.html | 89 ++++----- .../static/expected.html | 49 +++-- .../dynamic/expected.html | 4 +- .../static/expected.html | 4 +- .../with-scoped-styles/dynamic/expected.html | 172 ++++++++---------- .../with-scoped-styles/static/expected.html | 53 +++--- .../expected.html | 4 +- .../scoped-styles/expected.html | 4 +- .../fixtures/light-dom-multiple/expected.html | 16 +- .../expected.html | 4 +- .../light-dom-scoped-styles/expected.html | 8 +- .../light-dom-styles-dir-host/expected.html | 8 +- .../fixtures/light-dom/expected.html | 4 +- .../fixtures/no-dup-styles/expected.html | 9 +- .../render-correct-tags/expected.html | 4 +- .../src/__tests__/fixtures/scope-token/.skip | 3 + .../scoped-slots/for-each/expected.html | 4 +- .../expected.html | 4 +- .../shadow-dom-styles-dir-host/expected.html | 8 +- .../expected.html | 16 +- .../expected.html | 8 +- .../expected.html | 8 +- .../scoped-and-unscoped/expected.html | 8 +- .../unscoped-only-with-class/expected.html | 4 +- .../expected.html | 4 +- .../unscoped-only/expected.html | 4 +- .../expected.html | 8 +- .../expected.html | 8 +- .../style-dedupe-with-prefix/config.json | 4 + .../style-dedupe-with-prefix/error.txt | 0 .../style-dedupe-with-prefix/expected.html | 19 ++ .../style-dedupe-with-prefix/index.js | 3 + .../modules/x/child/child.css | 3 + .../modules/x/child/child.html | 1 + .../modules/x/child/child.js | 3 + .../modules/x/parent/parent.html | 4 + .../modules/x/parent/parent.js | 3 + .../styles-escaping-safe/expected.html | 4 +- .../fixtures/styles-keyframes/expected.html | 4 +- .../fixtures/styles-shared/expected.html | 17 +- .../__tests__/fixtures/styles/expected.html | 4 +- packages/@lwc/ssr-client-utils/LICENSE.md | 108 +++++++++++ packages/@lwc/ssr-client-utils/README.md | 3 + packages/@lwc/ssr-client-utils/package.json | 51 ++++++ .../ssr-client-utils/register-lwc-style.js | 10 + packages/@lwc/ssr-client-utils/src/index.ts | 58 ++++++ packages/@lwc/ssr-client-utils/tsconfig.json | 9 + .../src/__tests__/fixtures.spec.ts | 6 + .../src/compile-js/generate-markup.ts | 1 + .../src/compile-template/index.ts | 2 + packages/@lwc/ssr-runtime/src/render.ts | 17 ++ packages/@lwc/ssr-runtime/src/styles.ts | 30 ++- scripts/test-utils/html-snapshot-matcher.ts | 101 ++++++++++ scripts/test-utils/index.ts | 1 + .../test-utils/swap-lwc-style-for-style.ts | 104 +++++++++++ scripts/test-utils/test-fixture-dir.ts | 18 +- 59 files changed, 851 insertions(+), 266 deletions(-) create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/scope-token/.skip create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/config.json create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/error.txt create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/expected.html create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/index.js create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/modules/x/child/child.css create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/modules/x/child/child.html create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/modules/x/child/child.js create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/modules/x/parent/parent.html create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/style-dedupe-with-prefix/modules/x/parent/parent.js create mode 100644 packages/@lwc/ssr-client-utils/LICENSE.md create mode 100644 packages/@lwc/ssr-client-utils/README.md create mode 100644 packages/@lwc/ssr-client-utils/package.json create mode 100644 packages/@lwc/ssr-client-utils/register-lwc-style.js create mode 100644 packages/@lwc/ssr-client-utils/src/index.ts create mode 100644 packages/@lwc/ssr-client-utils/tsconfig.json create mode 100644 scripts/test-utils/html-snapshot-matcher.ts create mode 100644 scripts/test-utils/swap-lwc-style-for-style.ts diff --git a/package.json b/package.json index 98727b3e61..96c80e559c 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "*.{css,js,json,md,mjs,ts,yaml,yml}": "prettier --write", "{packages/**/package.json,scripts/tasks/check-and-rewrite-package-json.js}": "node ./scripts/tasks/check-and-rewrite-package-json.js", "{LICENSE-CORE.md,**/LICENSE.md,yarn.lock,scripts/tasks/generate-license-files.js,scripts/shared/bundled-dependencies.js}": "node ./scripts/tasks/generate-license-files.js", - "*.{only,skip}": "eslint --cache --no-eslintrc --plugin '@lwc/eslint-plugin-lwc-internal' --rule '@lwc/lwc-internal/forbidden-filename: error'" + "*.{only,skip}": "eslint --cache --plugin '@lwc/eslint-plugin-lwc-internal' --rule '@lwc/lwc-internal/forbidden-filename: error'" }, "workspaces": [ "packages/@lwc/*", diff --git a/packages/@lwc/engine-core/src/framework/hydration.ts b/packages/@lwc/engine-core/src/framework/hydration.ts index 2eb6002c87..6c1a65c7d9 100644 --- a/packages/@lwc/engine-core/src/framework/hydration.ts +++ b/packages/@lwc/engine-core/src/framework/hydration.ts @@ -368,7 +368,12 @@ function hydrateElement(elm: Node, vnode: VElement, renderer: RendererAPI): Node patchElementPropsAndAttrsAndRefs(vnode, renderer); - if (!isDomManual) { + // When tags are initially encountered at the time of HTML parse, the tag is + // replaced with an empty + +
@@ -15,9 +17,8 @@