Skip to content

Commit

Permalink
feat(react): enable support for CSS Modules and emitting *.css files …
Browse files Browse the repository at this point in the history
…in bundle (#4800)

* fix(import-css): update plugin to work with different output dirs

* feat(react): enable support for CSS Modules and emitting *.css files in bundle

* chore: update ordering for workspaces

* Update dry-trainers-protect.md

* Update package.json

* refactor: update primer/react to use postcss-preset-primer

* chore: update postcss config to mjs

* chore: restore original postcss config

---------

Co-authored-by: Josh Black <joshblack@users.noreply.github.com>
  • Loading branch information
joshblack and joshblack authored Aug 1, 2024
1 parent a7f0ddf commit 482b4d6
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["docs", "example-*", "codesandbox", "rollup-plugin-import-css"]
"ignore": ["docs", "example-*", "codesandbox"]
}
5 changes: 5 additions & 0 deletions .changeset/dry-trainers-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': major
---

Update Primer React to emit *.css files that are imported by emitted *.js files for styling
2 changes: 1 addition & 1 deletion .github/workflows/consumer_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Build @primer/react
run: npm run build -w @primer/react
run: npm run build -w rollup-plugin-import-css -w @primer/react
# Output the artifact as a tarball in `consumer-test`. Write the
# information for this package in `consumer-test/pack.json` so we can read
# from it later to install the package
Expand Down
63 changes: 63 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
"name": "primer",
"private": true,
"workspaces": [
"packages/rollup-plugin-import-css",
"packages/*",
"docs",
"examples/*"
],
"scripts": {
"setup": "./script/setup",
"build": "npm run build -w @primer/react",
"build": "npm run build -w rollup-plugin-import-css -w @primer/react",
"clean": "npm run clean -ws --if-present",
"clean:all": "npm run clean && rimraf node_modules docs/node_modules packages/*/node_modules examples/*/node_modules",
"format": "prettier --cache --write '**/*.{js,css,md,mdx,ts,tsx,yml}'",
Expand Down
8 changes: 7 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@
"./lib-esm/internal/*": null
},
"typings": "lib/index.d.ts",
"sideEffects": false,
"sideEffects": [
"lib-esm/**/*.css",
"lib/**/*.css"
],
"scripts": {
"build": "./script/build",
"clean": "rimraf dist lib lib-esm css",
Expand Down Expand Up @@ -199,7 +202,9 @@
"mdast-util-to-string": "4.0.0",
"micromark-extension-frontmatter": "2.0.0",
"micromark-extension-mdxjs": "3.0.0",
"postcss-custom-properties-fallback": "1.0.2",
"postcss-preset-env": "9.5.14",
"postcss-preset-primer": "^0.0.0",
"react": "18.3.1",
"react-dnd": "14.0.4",
"react-dnd-html5-backend": "14.0.2",
Expand All @@ -208,6 +213,7 @@
"recast": "0.23.7",
"rimraf": "5.0.5",
"rollup": "4.9.6",
"rollup-plugin-import-css": "^0.0.0",
"rollup-plugin-postcss": "4.0.2",
"rollup-plugin-visualizer": "5.9.2",
"semver": "7.6.2",
Expand Down
111 changes: 104 additions & 7 deletions packages/react/rollup.config.js → packages/react/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import fs from 'node:fs'
import path from 'node:path'
import {fileURLToPath} from 'node:url'
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import babel from '@rollup/plugin-babel'
import replace from '@rollup/plugin-replace'
import terser from '@rollup/plugin-terser'
import glob from 'fast-glob'
import customPropertiesFallback from 'postcss-custom-properties-fallback'
import {visualizer} from 'rollup-plugin-visualizer'
import {importCSS} from 'rollup-plugin-import-css'
import postcss from 'rollup-plugin-postcss'
import postssPresetPrimer from 'postcss-preset-primer'
import MagicString from 'magic-string'
import packageJson from './package.json'
import packageJson from './package.json' assert {type: 'json'}

const __dirname = path.dirname(fileURLToPath(import.meta.url))

const input = new Set([
// "exports"
Expand Down Expand Up @@ -80,6 +88,50 @@ function createPackageRegex(name) {
return new RegExp(`^${name}(/.*)?`)
}

const postcssPlugins = [
postssPresetPrimer(),
customPropertiesFallback({
importFrom: [
() => {
let customProperties = {}
const filePaths = glob.sync(['fallbacks/**/*.json', 'docs/functional/themes/light.json'], {
cwd: path.join(__dirname, '../../node_modules/@primer/primitives/dist/'),
ignore: ['fallbacks/color-fallbacks.json'],
})

for (const filePath of filePaths) {
const fileData = fs.readFileSync(
path.join(__dirname, '../../node_modules/@primer/primitives/dist/', filePath),
'utf8',
)

const jsonData = JSON.parse(fileData)
let result = {}

if (filePath === 'docs/functional/themes/light.json') {
for (const variable of Object.keys(jsonData)) {
result[`--${variable}`] = jsonData[variable].value
}
} else {
result = jsonData
}

customProperties = {
...customProperties,
...result,
}
}

return {customProperties}
},
],
}),
]

const postcssModulesOptions = {
generateScopedName: 'prc-[folder]-[local]-[hash:base64:5]',
}

const baseConfig = {
input: Array.from(input),
plugins: [
Expand Down Expand Up @@ -121,12 +173,12 @@ const baseConfig = {
commonjs({
extensions,
}),
postcss({
extract: 'components.css',
autoModules: false,
modules: {generateScopedName: 'prc_[local]_[hash:base64:5]'},
// plugins are defined in postcss.config.js
importCSS({
modulesRoot: 'src',
postcssPlugins,
postcssModulesOptions,
}),

/**
* This custom rollup plugin allows us to preserve directives in source
* code, such as "use client", in order to support React Server Components.
Expand Down Expand Up @@ -269,7 +321,52 @@ export default [
'process.env.NODE_ENV': JSON.stringify('production'),
preventAssignment: true,
}),
...baseConfig.plugins,
babel({
extensions,
exclude: /node_modules/,
babelHelpers: 'inline',
babelrc: false,
configFile: false,
presets: [
'@babel/preset-typescript',
[
'@babel/preset-react',
{
modules: false,
},
],
],
plugins: [
'macros',
'add-react-displayname',
'dev-expression',
'babel-plugin-styled-components',
'@babel/plugin-proposal-nullish-coalescing-operator',
'@babel/plugin-proposal-optional-chaining',
[
'babel-plugin-transform-replace-expressions',
{
replace: {
__DEV__: "process.env.NODE_ENV !== 'production'",
},
},
],
],
}),
resolve({
extensions,
}),
commonjs({
extensions,
}),
// PostCSS plugins are defined in postcss.config.js
postcss({
extract: 'components.css',
autoModules: false,
modules: {
generateScopedName: 'prc_[local]_[hash:base64:5]',
},
}),
terser(),
visualizer({sourcemap: true}),
],
Expand Down
2 changes: 1 addition & 1 deletion packages/react/script/build
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ npm run clean
npm run build:precompile-color-schemes

# Bundle
npx rollup -c --bundleConfigAsCjs
npx rollup -c

# Type check
npx tsc --project tsconfig.build.json
Expand Down
11 changes: 11 additions & 0 deletions packages/react/script/get-export-sizes.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ async function main() {
commonjs({
include: /node_modules/,
}),
{
name: 'empty-css-modules',
transform(_code, id) {
if (!id.endsWith('.css')) {
return
}
return {
code: `export default {}`,
}
},
},
virtual({
__entrypoint__: `export { ${identifier} } from '${filepath}';`,
}),
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/__tests__/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ async function setup(): Promise<Project> {
}

const extension = path.extname(source)
if (extension !== '' && extensions.includes(extension)) {
if (extension !== '' && !extensions.includes(extension)) {
return null
}

Expand Down
17 changes: 12 additions & 5 deletions packages/rollup-plugin-import-css/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ export function importCSS(options: ImportCSSOptions): Plugin {
return
}

// If we're working with a css asset that is not a CSS module, assume that
// it has been generated by our plugin and should be marked as external.
if (source.endsWith('.css') && !source.endsWith('.module.css')) {
const moduleInfo = this.getModuleInfo(importer)
if (moduleInfo?.meta['import-css']?.source === source) {
return {
id: path.resolve(path.dirname(importer), source),
id: source,
external: true,
}
}
Expand Down Expand Up @@ -87,9 +86,17 @@ export function importCSS(options: ImportCSSOptions): Plugin {
fileName,
})

const moduleInfo = this.getModuleInfo(id)
const cssSource = `./${path.basename(fileName)}`
if (moduleInfo) {
moduleInfo.meta['import-css'] = {
source: cssSource,
}
}

return {
code: `
import './${path.basename(fileName)}';
import '${cssSource}';
export default ${JSON.stringify(cssModuleClasses)}
`,
}
Expand Down

0 comments on commit 482b4d6

Please sign in to comment.