Here are the core concepts which I feel are important:
- Must be able to use composes from anywhere in the project.
- Have individual JSON files to load per each module.
- Be able to use duplicate class names across multiple modules with separate scope.
I already had grunt-postcss up and running on my project so I decided to stick with what is already working. I found a handy postcss-modules plugin which handles the class conversions to unique keys and builds JSON files.
yarn add postcss-modules
This leaves me with a package.json file which looks like this
You may notice a strange key “css-modules-loader-core”: “https://github.com/lipemat/css-modules-loader-core.git”. I ended up forking the loader-core module because I couldn’t get the original to resolve while using “composes”. This is a known problem that is not getting much traction so I decided it would be more stable to fork and self maintain. Also adding the “resolutions” key prevents other libraries from getting other versions which break module location when using Yarn.
Out of the box, this plugin generates a single JSON file for you entire tree and does not account for duplicate class names. Not an ideal results so I headed over to my postcss config and made some adjustments.
This main part that we care about is here:
This allows the postcss-modules to work inside the import processes generating separate JSON files for each module and giving us unique selectors for duplicates. Also if you notice I have configured “globalModulePaths” which point to existing postcss styles for non modular elements. Anything within the specified directories is treated as normal non modular postcss and will generate standard css. It is particularly handy when your working with a framework like WordPress which has many classes hardcoded. globalModulePaths uses regular expression to check against the pcss file paths. In this example anything in a resources/pcss folder will be considered non modular. I included expressions for both Windows and Mac.
At this point we can start adding .pcss files to same directories we have our PHP templates located. We can then add a standard postcss @import to the bottom of our main .pcss file and grunt will start generating the unique identifiers and JSON files.
For instance, lets say I have a main pcss file called style.pcss which lives in my original pcss dir. I would add these lines.
I already have a template-parts directory which lives in the same directory as pcss and contains a test.php file. I’m now going to create the test.pcss file to match the test.php file. Running grunt will include the new test.pcss file in my main styles and generate a test.pcss.json file.
My template-parts directory now looks like this:
Everything is good to go as far as postcss and grunt are concerned but we still don’t have a way to actually use the styles. I went ahead and built a handy class to be used for this.