Repository: styled-components/babel-plugin-styled-components
Pull request #281 (2020-04-22 21:44:31)

Add namespace option
This is a fix of [2974](https://github.com/styled-components/styled-components/issues/2974).

I have already implemented fork of this repo and tested it with my adoption: 
[@rajzik/babel-plugin-styled-components](https://github.com/rajzik/babel-plugin-styled-components-namespace).

It is working well and it creates a unique name with the given namespace.
This will resolve all issues with micro frontends class name duplication.

pgangwani: Dear core contributors,
Could you please review this PR?
This is only option I see working for me where I have micro-frontend setup composed using ESI at akamai (cdn). Please suggest if there is any other way which we are missing.

@mxstbr  @probablyup @kitten

bowsersenior: I was looking for exactly this feature to solve a production bug with clashing class names generated by styled-components. It would be awesome to have this feature available!
rajzik: @bowsersenior as for now, I have released fork with namespace setting 
[plugin-namespace](https://github.com/rajzik/babel-plugin-styled-components-namespace).
It is just fork with namespace added so you can substitute babel-plugin-styled-component with mine.
I am using it, and it works well. 
luanraithz: I'm also having a production bug related to multiple styled-components instances conflicting.
dlcognite: this would also solve a lot of the issues i am having as well, ping again :P 

Patch:
diff --git a/src/utils/options.js b/src/utils/options.js
index d1a1930..f079618 100644
--- a/src/utils/options.js
+++ b/src/utils/options.js
@@ -11,6 +11,14 @@ export const useMinify = state => getOption(state, 'minify')
 export const useTranspileTemplateLiterals = state =>
   getOption(state, 'transpileTemplateLiterals')
 
+export const useNamespace = state => {
+  const namespace = getOption(state, 'namespace', '')
+  if (namespace) {
+    return `${namespace}__`
+  }
+  return ''
+}
+
 export const usePureAnnotation = state => getOption(state, 'pure', false)
 
 export const useCssProp = state => getOption(state, 'cssProp', true)
diff --git a/src/visitors/displayNameAndId.js b/src/visitors/displayNameAndId.js
index 95c1a88..42c1c1f 100644
--- a/src/visitors/displayNameAndId.js
+++ b/src/visitors/displayNameAndId.js
@@ -1,6 +1,11 @@
 import path from 'path'
 import fs from 'fs'
-import { useFileName, useDisplayName, useSSR } from '../utils/options'
+import {
+  useFileName,
+  useDisplayName,
+  useSSR,
+  useNamespace,
+} from '../utils/options'
 import getName from '../utils/getName'
 import prefixLeadingDigit from '../utils/prefixDigit'
 import hash from '../utils/hash'
@@ -130,7 +135,9 @@ const getNextId = state => {
 
 const getComponentId = state => {
   // Prefix the identifier with a character because CSS classes cannot start with a number
-  return `${prefixLeadingDigit(getFileHash(state))}-${getNextId(state)}`
+  return `${useNamespace(state)}${prefixLeadingDigit(
+    getFileHash(state)
+  )}-${getNextId(state)}`
 }
 
 export default t => (path, state) => {


Test patch:
diff --git a/test/fixtures/use-namespace/.babelrc b/test/fixtures/use-namespace/.babelrc
new file mode 100644
index 0000000..ab8caef
--- /dev/null
+++ b/test/fixtures/use-namespace/.babelrc
@@ -0,0 +1,10 @@
+{
+  "plugins": [
+    [
+      "../../../src",
+      {
+        "namespace": "test-namespace"
+      }
+    ]
+  ]
+}
\ No newline at end of file
diff --git a/test/fixtures/use-namespace/code.js b/test/fixtures/use-namespace/code.js
new file mode 100644
index 0000000..9715b42
--- /dev/null
+++ b/test/fixtures/use-namespace/code.js
@@ -0,0 +1,13 @@
+import styled from 'styled-components'
+
+const Test = styled.div`
+  color: red;
+`
+
+const before = styled.div`
+  color: blue;
+`
+
+styled.div``
+
+export default styled.button``
diff --git a/test/fixtures/use-namespace/output.js b/test/fixtures/use-namespace/output.js
new file mode 100644
index 0000000..7e6b892
--- /dev/null
+++ b/test/fixtures/use-namespace/output.js
@@ -0,0 +1,17 @@
+import styled from 'styled-components';
+const Test = styled.div.withConfig({
+  displayName: "code__Test",
+  componentId: "test-namespace__sc-3rfj0a-0"
+})(["color:red;"]);
+const before = styled.div.withConfig({
+  displayName: "code__before",
+  componentId: "test-namespace__sc-3rfj0a-1"
+})(["color:blue;"]);
+styled.div.withConfig({
+  displayName: "code",
+  componentId: "test-namespace__sc-3rfj0a-2"
+})([""]);
+export default styled.button.withConfig({
+  displayName: "code",
+  componentId: "test-namespace__sc-3rfj0a-3"
+})([""]);