Shopify / hydrogen-v1

React-based framework for building dynamic, Shopify-powered custom storefronts.
https://shopify.github.io/hydrogen-v1/
MIT License
3.75k stars 326 forks source link

[BUG] Named client component export `Cart` clashes with Hydrogen Cart component #289

Closed jplhomer closed 2 years ago

jplhomer commented 2 years ago

Describe the bug I think we have a naming issue in our ClientMarker wrapping logic. If a userland component is named the same thing as a Hydrogen component (and is not a default export, seemingly), the names clash and we get this error in the server console:

5:00:20 PM [vite] Internal server error: /Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx: Identifier 'Cart' has already been declared. (5:13)

  3 |
  4 | export default wrapInClientMarker({ name: 'Cart', id: '/Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx', component: Cart, named: false });
> 5 | export const Cart = wrapInClientMarker({ name: 'Cart', id: '/Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx', component: namedImports['Cart'], named: true });
    |              ^
  6 | export const CartIcon = wrapInClientMarker({ name: 'CartIcon', id: '/Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx', component: namedImports['CartIcon'], named: true });
  7 |
  Plugin: vite:react-babel
  File: /Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx
  3  |  
  4  |  export default wrapInClientMarker({ name: 'Cart', id: '/Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx', component: Cart, named: false });
  5  |  export const Cart = wrapInClientMarker({ name: 'Cart', id: '/Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx', component: namedImports['Cart'], named: true });
     |               ^
  6  |  export const CartIcon = wrapInClientMarker({ name: 'CartIcon', id: '/Users/joshlarson/src/github.com/half-helix/shopify_supply/src/components/Cart.client.jsx', component: namedImports['CartIcon'], named: true });
  7  |  
      at Object._raise (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:541:17)
      at Object.raiseWithData (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:534:17)
      at Object.raise (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:495:17)
      at ScopeHandler.checkRedeclarationInScope (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:1688:12)
      at ScopeHandler.declareName (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:1654:12)
      at Object.checkLVal (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:11086:24)
      at Object.parseVarId (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:14044:10)
      at Object.parseVar (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:14019:12)
      at Object.parseVarStatement (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:13836:10)
      at Object.parseStatementContent (/Users/joshlarson/src/github.com/half-helix/shopify_supply/node_modules/@babel/parser/lib/index.js:13421:21)
Error: entry-server.jsx could not be loaded. This likely occurred because of a Vite compilation error.

To Reproduce

  1. In Cart.client.jsx in the starter template, change export default to export
  2. Check the server console

Expected behaviour Names should not clash.

Screenshots If applicable, add screenshots to help explain your problem.

Additional context Add any other context about the problem here. eg.

jplhomer commented 2 years ago

@frandiox any ideas on this and whether it's a quick fix?

frandiox commented 2 years ago

@jplhomer I think the actual problem is when having a component exported twice, once as default and once as named export:

export const MyComponent = function() {}
export default MyComponent

This would get compiled to something like:

import MyComponent, * as namedImports from 'xyz'

export const MyComponent = namedImports.MyComponent
export default MyComponent

Which is obviously wrong because the identifier MyComponent is declared twice. At least is not related to using the same name as Hydrogen components, which would be harder to fix I think 😅

jplhomer commented 2 years ago

Ahh good catch!