-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add the option to provide a prefix to generated class names #1717
Conversation
🦋 Changeset detectedLatest commit: 7ad0484 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for compiled-css-in-js ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work with ax
? That parses the classname and I don't think it'll work without changes.
Have a read of https://github.com/atlassian-labs/compiled/blob/master/packages/react/src/runtime/ax.ts#L30 and probably add some tests there
@@ -205,6 +205,36 @@ describe('babel plugin', () => { | |||
expect(actual).toInclude('c_MyDiv'); | |||
}); | |||
|
|||
it.only('should add a prefix to style hash hashPrefix is present', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it.only('should add a prefix to style hash hashPrefix is present', () => { | |
it('should add a prefix to style hash hashPrefix is present', () => { |
hey @JakeLane I was playing around with the code but I couldn't find any clear solutions besides adding the hash prefix into the hash of the group. This way groups would wind up with the same hash and Essentially const group = hash(`${opts.atRule}${selectors}${node.prop}`).slice(0, 4);
// becomes
const group = hash(`${opts.hashPrefix}${opts.atRule}${selectors}${node.prop}`).slice(0, 4); Seems too easy to be true though, am I potentially missing something? edit: Obviously we'd lose the ability to check for the prefix when looking through the class names as they'd be hashed but that's not really why we're making this change to begin with so I think it's an acceptable tradeoff. |
packages/babel-plugin/src/types.ts
Outdated
* Adds a defined prefix to the generated classes' hashes. | ||
* Useful in micro frontend environments to avoid clashing/specificity issues. | ||
*/ | ||
hashPrefix?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah more descriptive naming is helpful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imo add
suggests the expected value is a boolean and not a string that we're setting. Would classHashPrefix
be better in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ye that's fine
I think this is fine. It might be good to validate VR test correctness manually; I don't think we have a way to change the babel config on VR tests right now. |
@@ -93,6 +94,15 @@ Extensions that we should consider code. We use these to identify if a file shou | |||
- Type: `string[]` | |||
- Default: `['.js', '.jsx', '.ts', '.tsx']` | |||
|
|||
#### hashPrefix | |||
|
|||
Adds a prefix to the generated hashed css rule names. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: mention what format hashPrefix
is required to be
e.g. how it needs to match the /^[a-zA-Z\-][a-zA-Z\-_0-9]*$/
regex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yep good idea!
*/ | ||
const atomicClassName = (node: Declaration, opts: PluginOpts) => { | ||
if (opts.hashPrefix && !isCssIdentifierValid(opts.hashPrefix)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: what if we move this check to the atomicifyRules
function later in the file? we don't expect opts.hashPrefix
to change during the build stage right
(not a strong preference, i don't mind either way)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can do! Probably a better idea, we most likely don't wanna be running regex matches all willy nilly
* | ||
*/ | ||
const isCssIdentifierValid = (value: string): boolean => { | ||
const validCssIdentifierRegex = /^[a-zA-Z\-][a-zA-Z\-_0-9]*$/; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where did you find this regex? it looks reasonable but it doesn't match with what i could easily find online e.g. https://stackoverflow.com/a/449000
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it myself as it was supposed to be in the middle of an already existing identifier. It's actually not 100% now that I look at it;
That said, since it's now being used in the hash and not as a standalone string it could be pretty much anything but I think it makes sense to continue to only accept identifiers to prevent any potential unwanted side effects. I'll refactor it
5d9e370
to
da5c433
Compare
*/ | ||
const isCssIdentifierValid = (value: string): boolean => { | ||
const validCssIdentifierRegex = /^[a-zA-Z\-_]+[a-zA-Z\-_0-9]*$/; | ||
return Boolean(value.match(validCssIdentifierRegex)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops sorry i just realised, can this be simplified to validCssIdentifierRegex.test(value)
instead?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
@@ -21,10 +34,14 @@ interface PluginOpts { | |||
* | |||
* @param node CSS declaration | |||
* @param opts AtomicifyOpts | |||
* | |||
* @throws Throws an error if `opts.classHashPrefix` contains invalid css class/id characters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this @throws
should be removed
177098b
to
7ad0484
Compare
{ classHashPrefix: 'myprefix' } | ||
); | ||
|
||
expect(actual).toInclude(hashedClassName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we check actual
include classHashPrefix
too?
All good. classHashPrefix
is part of hash.
What is this change?
This PR introduces a new configuration prop to
@compiled/babel-plugin
namedclassHashPrefix
(feel free to suggest a better alternative) that allows users to define a prefix to be added to when generating class name hashes.Why are we making this change?
We have an internal problem in a consumer of a remote module where it has its styles messed up due to the loss of specificity once the remote module is loaded. This is because both the wrapping application and the remote module use
@compiled
and due to the way we generate the class names, both end up generating a few with the same name.How are we making this change?
This is the first time I ever work with a Babel plugin so I might be missing something, all feedback is appreciated. I tried to follow the code and tests to figure out where we were generating the hashes and hooked it up with the new config prop.
Lastly, I only worked off of tests on this, guidance on how to better test it are welcomed 😅
edit: I assume I'm probably missing a changeset on this prdonePR checklist
Don't delete me!
I have...
website/