reactioncommerce / example-storefront

Example Storefront is Reaction Commerce’s headless ecommerce storefront - Next.js, GraphQL, React. Built using Apollo Client and the commerce-focused React UI components provided in the Storefront Component Library (reactioncommerce/reaction-component-library). It connects with Reaction backend with the GraphQL API.
https://www.mailchimp.com/developer/open-commerce
Apache License 2.0
606 stars 288 forks source link

StyledComponents Error: Trying to insert a new style tag, but the given Node is unmounted! #503

Closed aldeed closed 5 years ago

aldeed commented 5 years ago

Type: critical

Describe the bug Running latest develop on a fresh reset of the project, I'm seeing this error on the /cart/checkout route:

Error was not caught Error: Trying to insert a new style tag, but the given Node is unmounted!

* Are you using a custom target that isn't mounted?
* Does your document not have a valid head element?
* Have you accidentally removed a style tag manually?

    at new StyledComponentsError (styled-components.browser.cjs.js:162)
    at makeStyleTag (styled-components.browser.cjs.js:547)
    at makeTag (styled-components.browser.cjs.js:871)
    at StyleSheet.makeTag$$1 [as makeTag] (styled-components.browser.cjs.js:1105)
    at StyleSheet.getTagForId (styled-components.browser.cjs.js:1123)
    at StyleSheet.deferredInject (styled-components.browser.cjs.js:1163)
    at new ComponentStyle (styled-components.browser.cjs.js:2071)
    at createStyledComponent (styled-components.browser.cjs.js:1900)
    at templateFunction (styled-components.browser.cjs.js:2186)
    at Module.../../node_modules/@reactioncommerce/components/CartItem/v1/CartItem.mjs (CartItem.mjs:26)
    at __webpack_require__ (bootstrap:789)
    at fn (bootstrap:150)
    at Module.../../node_modules/@reactioncommerce/components/CartItem/v1/index.mjs (index.mjs:1)
    at __webpack_require__ (bootstrap:789)
    at fn (bootstrap:150)
    at Module../custom/componentsContext.js (componentsContext.js:1)
    at __webpack_require__ (bootstrap:789)
    at fn (bootstrap:150)
    at Module.<anonymous> (variantById.js:12)
    at Module../pages/_app.js (_app.js:31)
    at __webpack_require__ (bootstrap:789)
    at fn (bootstrap:150)
    at routes.js:29
    at register (page-loader.js:124)
    at PageLoader.registerPage (page-loader.js:162)
    at Object.1 (routes.js:29)
    at __webpack_require__ (bootstrap:789)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at _app.js:1

The page loads but shows the "Your shopping cart is empty" message even though it isn't empty.

There is also this warning:

It looks like there are several instances of 'styled-components' initialized in this application. This may cause dynamic styles not rendering properly, errors happening during rehydration process and makes your application bigger without a good reason.

See https://s-c.sh/2BAXzed for more info.

I've checked the things they recommend and there don't appear to be two styled-components dependencies. I'm guessing a NextJS/SSR issue.

I think this started with bumping the @reactioncommerce/components dependency to a version that exports EcmaScript modules. It would be good to find a solution that does not involve undoing that change since we need it for Webpack tree shaking, but it could be a quick-fix solution if we need one.

To Reproduce Steps to reproduce the behavior:

  1. Add an item to your cart
  2. Go to the checkout page

Expected behavior Checkout page loads as normal

Desktop (please complete the following information):

UPDATE: Rolling back the component library fixes it as a workaround for now:

docker-compose run --rm web yarn add -E @reactioncommerce/components@0.62.1
docker-compose restart
aldeed commented 5 years ago

This seems to be resolved. It was related to some sort of browser caching or cookie, perhaps from changing between environments. I'm not sure which, but one of the following should resolve if you see this:

janus-reith commented 5 years ago

I experience the same issue, but can't exactly tell the version as my fork of the starterkit diverges. The error comes up when directly visiting /cart/checkout, it works when being routed from another page.

And I think there actually are two versions of styled-components causing the issue: The @reaction/components module is using styled-components 3.3.3 while the starterkit is using 3.4.10.

That page is using a component which uses styled-components: https://github.com/reactioncommerce/reaction-next-starterkit/blob/be9aac4ce1afbf266c9970f165ae451c23a976cd/src/components/CheckoutActions/CheckoutActions.js#L6

Somehow yarn didn't allow me to downgrade styled-components in the starterkit to 3.3.3 to see if that fixes it - Even when I explicitly installed styled-components@^3.3.3 and deleted my lockfile before, the new lockfile would have 3.4.10 again.

Installing the latest version of @reaction/components v0.65.2 also didn't fix it.

aldeed commented 5 years ago

@janus-reith It may be true that there are multiple versions, but it's also true that whenever I see this error, if I log in it goes away. The cause is still a mystery to me, but it seems like logging in fixes whatever is causing the double load. It's possible it could have something to do with the server side rendering?

janus-reith commented 5 years ago

Probably it is related to SSR, as the error came up on direct page visits, but not when routed from somewhere else. There were cases when it just came as a warning, but in other cases it rendered the current page unfunctional. I couldn't really narrow it down yet.

As far as I got it, the way reaction-component-library is exported and used it still contains untranspiled styled-components functionality, (and other stuff too) but that is a way that supports proper tree shacking and reduces overhead. (I'm not sure about the technical details here, but there seem to be other packages that also use styled-component on the inside but don't "leak" it, so that is my conclusion here.).

Therefore I wonder if it would be feasible to export styled-components from the component library and use it from there instead of directly including it in the starterkit? Actually there is very little code in the starterkit which is actually using it

aldeed commented 5 years ago

I've investigated this more and passed it off to @willopez .

The error happens because both the styled-components commonjs entry point and the styled-components ES modules entry point get pulled into the bundle.

Why this happens is unclear, but it is likely either a webpack bug or something incorrect about the styled-components package.json, or both.

The proximate cause is importing styled-components from a .js file in the app itself. As long as it's only imported from the Reaction component library, things are fine. As soon as you import once within any .js file in the app, webpack seems to prefer the commonjs file for that import, and you end up with both being loaded on the page.

Some things we've identified to try:

willopez commented 5 years ago

Attempts to resolved this issue:

Update the component library styled-components dependency to v4. This is a breaking change but might fix it if it's a package problem. We can release a new major version of the component library for this change. Tried, problem persists

willopez commented 5 years ago

I have created an isolated app the reproduces the issue:

https://github.com/willopez/double-styled-components

This rules out, SSR causing the problem.

@aldeed It seems that the way the components-library packages the components is at the root of this issue.

aldeed commented 5 years ago

This does appear to be a Webpack bug. I created an even more minimal reproduction and created a Webpack issue here: https://github.com/webpack/webpack/issues/9329

@willopez and I did figure out a workaround, though, which is to use Webpack alias to map all styled-components imports explicitly to the .mjs entry point. @willopez is going to do that for now until there is a real solution from Webpack folks.