{"id":17375893,"url":"https://github.com/drewml/styled-components-apollo-duplicate-styles","last_synced_at":"2025-07-20T04:33:19.493Z","repository":{"id":72799387,"uuid":"424755195","full_name":"DrewML/styled-components-apollo-duplicate-styles","owner":"DrewML","description":"Minimal Reproduction of a conflict with Styled Components + Apollo Client + SSR","archived":false,"fork":false,"pushed_at":"2021-11-05T14:57:53.000Z","size":17,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T19:53:29.270Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DrewML.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-04T22:17:42.000Z","updated_at":"2021-11-05T14:57:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"98f781d4-d19a-4281-8b43-625598a071c6","html_url":"https://github.com/DrewML/styled-components-apollo-duplicate-styles","commit_stats":{"total_commits":1,"total_committers":1,"mean_commits":1.0,"dds":0.0,"last_synced_commit":"7b94b6d5b8aa63b36b1855ec2785dc824c235102"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DrewML/styled-components-apollo-duplicate-styles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrewML%2Fstyled-components-apollo-duplicate-styles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrewML%2Fstyled-components-apollo-duplicate-styles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrewML%2Fstyled-components-apollo-duplicate-styles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrewML%2Fstyled-components-apollo-duplicate-styles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DrewML","download_url":"https://codeload.github.com/DrewML/styled-components-apollo-duplicate-styles/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrewML%2Fstyled-components-apollo-duplicate-styles/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266067276,"owners_count":23871324,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-16T04:04:11.725Z","updated_at":"2025-07-20T04:33:19.439Z","avatar_url":"https://github.com/DrewML.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Minimal Repro - Apollo Client + Styled Components + SSR duplication\n\n## Summary\n\nUnder the following conditions, `styled-components` will create duplicate global styles during Server-Side Rendering:\n\n1. App implements SSR stragies from both `styled-components` and `@apollo/client`\n1. App has at least one `useQuery` call\n1. App has at least one `createGlobalStyle` component in the tree\n\n## Minimal App\n\nThe application in [`test.js`](./test.js) is a minimal React application with:\n\n1. One component created with [`createGlobalStyle`](https://styled-components.com/docs/api#createglobalstyle)\n1. One component created with `styled.div`\n1. One component that makes a [`useQuery`](https://www.apollographql.com/docs/react/data/queries/#usequery-api) call\n1. `styled-components` SSR support via `ServerStyleSheet`/`collectStyles`/`getStyleTags`/`babel-plugin-styled-components`\n1. `@apollo/client` SSR support via [`getMarkupFromTree`](https://www.apollographql.com/docs/react/performance/server-side-rendering/)\n\n## Test Cases w/ SSR Output (can be generated with `npm start`)\n\n### styled-components + apollo + ssr default setup:\n\nThis is the barebones Apollo + Styled Components setup, to help illustrate the bug. Note that there are 2 copies of the `html` element styles in the SSR output, but there should only be one.\n\n```html\n\u003chtml\u003e\n  \u003cstyle data-styled=\"true\" data-styled-version=\"5.3.3\"\u003e\n    .kERQPB {\n      position: relative;\n    } /*!sc*/\n    data-styled.g1[id='sc-bdvvtL'] {\n      content: 'kERQPB,';\n    } /*!sc*/\n    html {\n      display: block;\n    } /*!sc*/\n    data-styled.g2[id='sc-global-dxkSA1'] {\n      content: 'sc-global-dxkSA1,';\n    } /*!sc*/\n    html {\n      display: block;\n    } /*!sc*/\n    data-styled.g3[id='sc-global-dxkSA2'] {\n      content: 'sc-global-dxkSA2,';\n    } /*!sc*/\n  \u003c/style\u003e\n  \u003cdiv class=\"sc-bdvvtL kERQPB\"\u003eresponse from GraphQL server\u003c/div\u003e\n\u003c/html\u003e\n```\n\n### With temporary hack:\n\nThis is the barebones setup from the first test case, but with a hack! The code hooks into Apollo Client's `getMarkupFromTree` and, before each React render, resets the global styles (`gs`) object on the `ServerStyleSheet` so it's empty. The idea is that we only care about CSS for the _very last_ render, so we'll ignore the global styles until the end.\n\nThis hack is far from perfect. Although the global _declarations_ are not duplicated, there's still superfluous output (note the 1 extra `data-styled.g*` class).\n\n```html\n\u003chtml\u003e\n  \u003cstyle data-styled=\"true\" data-styled-version=\"5.3.3\"\u003e\n    .kERQPB {\n      position: relative;\n    } /*!sc*/\n    data-styled.g1[id='sc-bdvvtL'] {\n      content: 'kERQPB,';\n    } /*!sc*/\n    html {\n      display: block;\n    } /*!sc*/\n    data-styled.g2[id='sc-global-dxkSA1'] {\n      content: 'sc-global-dxkSA1,';\n    } /*!sc*/\n  \u003c/style\u003e\n  \u003cdiv class=\"sc-bdvvtL kERQPB\"\u003eresponse from GraphQL server\u003c/div\u003e\n\u003c/html\u003e\n```\n\n## Why?\n\nI believe the issue is a disconnect between how Apollo Client's `getMarkupFromTree`/`getDataFromTree` works, and how `styled-components` expects SSR to work.\n\nApollo Client works by calling `ReactDOMServer.renderToString` _many_ times in a row. This is necessary because there's no way to figure out ahead of time how many `useQuery` calls are nested in the component tree.\n\nHowever, `styled-components` expects to only run through `renderToString` _once_. Ideally, we'd only generate styles on the _very last_ call to `renderToString`. However, due to the architecture of Apollo Client, there is no way to know how many React renders will be necessary.\n\n## How can Styled-Components address this?\n\nI believe a minimal fix is possible if the `ServerStyleSheet` in `styled-components` provided an API to clear/reset the stylesheet.\n\nWhen using Apollo Client w/ SSR, you only use the markup from the _final_ render. Ideally, we'd also just capture styles from the final render.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrewml%2Fstyled-components-apollo-duplicate-styles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrewml%2Fstyled-components-apollo-duplicate-styles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrewml%2Fstyled-components-apollo-duplicate-styles/lists"}