Skip to content

Commit

Permalink
Adds a --css-modules option (#370)
Browse files Browse the repository at this point in the history
* feat: adds a `--cssmodules` option

* chore: Allow scopeName to come from args

* chore: --css-modules is now tristate

* docs: Wrote docs around how to use css-modules

* chore: Fixed all tristate logic, and readable first

* test: Wrote tests for all avenues

* chore: Add's newlines to the end of files
  • Loading branch information
maraisr committed Feb 9, 2020
1 parent 5ca1514 commit 5100c7b
Show file tree
Hide file tree
Showing 20 changed files with 377 additions and 1 deletion.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,26 @@ Acts just like `microbundle build`, but watches your source files and rebuilds o

Just point the input to a `.ts` file through either the cli or the `source` key in your `package.json` and you’re done.

### Using CSS Modules

By default any css file imported as `.module.css`, will be treated as a css-module. If you wish to treat all .css
imports as a module, specify the cli flag `--css-modules true`. If you wish to disable all css-module behaviours set the
flag to `false`.

The default scope name when css-modules is turned on will be, in watch mode `_[name]__[local]__[hash:base64:5]` and when
you build `_[hash:base64:5]`. This can be overriden by specifying the flag, eg
`--css-modules "_something_[hash:base64:7]"`. _Note:_ by setting this, it will be treated as a true, and thus, all .css
imports will be scoped.

| flag | import | is css module? |
| ----- | ------------------------------ | :----------------: |
| null | import './my-file.css'; | :x: |
| null | import './my-file.module.css'; | :white_check_mark: |
| false | import './my-file.css'; | :x: |
| false | import './my-file.module.css'; | :x: |
| true | import './my-file.css'; | :white_check_mark: |
| true | import './my-file.module.css'; | :white_check_mark: |

### Specifying builds in `package.json`

You can specify output builds in a `package.json` as follows:
Expand Down Expand Up @@ -151,6 +171,7 @@ Options
--raw Show raw byte size (default false)
--jsx A custom JSX pragma like React.createElement (default: h)
--tsconfig Specify the path to a custom tsconfig.json
--css-modules Configures .css to be treated as modules (default: null)
-h, --help Displays this message
Examples
Expand Down
52 changes: 52 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ function createConfig(options, entry, format, writeMeta) {
preset: 'default',
}),
].filter(Boolean),
autoModules: shouldCssModules(options),
modules: cssModulesConfig(options),
// only write out CSS for the first bundle (avoids pointless extra files):
inject: false,
extract: !!writeMeta,
Expand Down Expand Up @@ -664,3 +666,53 @@ function createConfig(options, entry, format, writeMeta) {

return config;
}

function shouldCssModules(options) {
const passedInOption = processCssmodulesArgument(options);

// We should module when my-file.module.css or my-file.css
const moduleAllCss = passedInOption === true;

// We should module when my-file.module.css
const allowOnlySuffixModule = passedInOption === null;

return moduleAllCss || allowOnlySuffixModule;
}

function cssModulesConfig(options) {
const passedInOption = processCssmodulesArgument(options);
const isWatchMode = options.watch;
const hasPassedInScopeName = !(
typeof passedInOption === 'boolean' || passedInOption === null
);

if (shouldCssModules(options) || hasPassedInScopeName) {
let generateScopedName = isWatchMode
? '_[name]__[local]__[hash:base64:5]'
: '_[hash:base64:5]';

if (hasPassedInScopeName) {
generateScopedName = passedInOption; // would be the string from --css-modules "_[hash]".
}

return { generateScopedName };
}

return false;
}

/*
This is done becuase if you use the cli default property, you get a primiatve "null" or "false",
but when using the cli arguments, you always get back strings. This method aims at correcting those
for both realms. So that both realms _convert_ into primatives.
*/
function processCssmodulesArgument(options) {
if (options['css-modules'] === 'true' || options['css-modules'] === true)
return true;
if (options['css-modules'] === 'false' || options['css-modules'] === false)
return false;
if (options['css-modules'] === 'null' || options['css-modules'] === null)
return null;

return options['css-modules'];
}
5 changes: 5 additions & 0 deletions src/prog.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export default handler => {
.option('--name', 'Specify name exposed in UMD builds')
.option('--cwd', 'Use an alternative working directory', '.')
.option('--sourcemap', 'Generate source map', true)
.option(
'--css-modules',
'Turns on css-modules for all .css imports. Passing a string will override the scopeName. eg --css-modules="_[hash]"',
null,
)
.example("microbundle --no-sourcemap # don't generate sourcemaps")
.option('--raw', 'Show raw byte size', false)
.option(
Expand Down
198 changes: 197 additions & 1 deletion test/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ Build \\"basicCss\\" to dist:
exports[`fixtures build basic-css with microbundle 2`] = `7`;
exports[`fixtures build basic-css with microbundle 3`] = `".testing{display:-webkit-box;display:flex;color:red;background:#00f}"`;
exports[`fixtures build basic-css with microbundle 3`] = `"._rHGVB{display:-webkit-box;display:flex;color:red;background:#00f}"`;
exports[`fixtures build basic-css with microbundle 4`] = `
"export default function(){var e=document.createElement(\\"div\\");return e.className=\\"testing\\",e}
Expand Down Expand Up @@ -1043,6 +1043,202 @@ exports[`fixtures build class-properties with microbundle 5`] = `
"
`;
exports[`fixtures build css-modules--false with microbundle 1`] = `
"Used script: microbundle --no-sourcemap --css-modules false
Directory tree:
css-modules--false
dist
css-modules--false.css
css-modules--false.esm.js
css-modules--false.js
css-modules--false.umd.js
package.json
src
index.js
not_scoped.css
not_scoped.module.css
Build \\"cssModulesFalse\\" to dist:
49 B: css-modules--false.js.gz
23 B: css-modules--false.js.br
48 B: css-modules--false.esm.js.gz
32 B: css-modules--false.esm.js.br
157 B: css-modules--false.umd.js.gz
110 B: css-modules--false.umd.js.br"
`;
exports[`fixtures build css-modules--false with microbundle 2`] = `4`;
exports[`fixtures build css-modules--false with microbundle 3`] = `
"body{display:-webkit-box;display:flex;color:red;background:#00f}.test_class_that_shouldnt_be_scoped{background-color:#00f}
.not_scoped_class{color:pink}"
`;
exports[`fixtures build css-modules--false with microbundle 4`] = `
"export default function(){}
"
`;
exports[`fixtures build css-modules--false with microbundle 5`] = `
"module.exports=function(){};
"
`;
exports[`fixtures build css-modules--false with microbundle 6`] = `
"!function(e,n){\\"object\\"==typeof exports&&\\"undefined\\"!=typeof module?module.exports=function(){}:\\"function\\"==typeof define&&define.amd?define(function(){return function(){}}):(e=e||self).cssModulesFalse=function(){}}(this);
"
`;
exports[`fixtures build css-modules--null with microbundle 1`] = `
"Used script: microbundle --no-sourcemap
Directory tree:
css-modules--null
dist
css-modules--null.css
css-modules--null.esm.js
css-modules--null.js
css-modules--null.umd.js
package.json
src
index.js
not_scoped.css
scoped.module.css
Build \\"cssModulesNull\\" to dist:
110 B: css-modules--null.js.gz
72 B: css-modules--null.js.br
109 B: css-modules--null.esm.js.gz
70 B: css-modules--null.esm.js.br
201 B: css-modules--null.umd.js.gz
142 B: css-modules--null.umd.js.br"
`;
exports[`fixtures build css-modules--null with microbundle 2`] = `4`;
exports[`fixtures build css-modules--null with microbundle 3`] = `
"body{display:-webkit-box;display:flex;color:red;background:#00f}._2Dgv6{background-color:#00f}
._2kWDE{color:pink}"
`;
exports[`fixtures build css-modules--null with microbundle 4`] = `
"export default function(){var e=document.createElement(\\"div\\");return e.className=\\"_2kWDE\\",e}
"
`;
exports[`fixtures build css-modules--null with microbundle 5`] = `
"module.exports=function(){var e=document.createElement(\\"div\\");return e.className=\\"_2kWDE\\",e};
"
`;
exports[`fixtures build css-modules--null with microbundle 6`] = `
"!function(e,n){\\"object\\"==typeof exports&&\\"undefined\\"!=typeof module?module.exports=n():\\"function\\"==typeof define&&define.amd?define(n):(e=e||self).cssModulesNull=n()}(this,function(){return function(){var e=document.createElement(\\"div\\");return e.className=\\"_2kWDE\\",e}});
"
`;
exports[`fixtures build css-modules--string with microbundle 1`] = `
"Used script: microbundle --no-sourcemap --css-modules '_contains_this_[hash]'
Directory tree:
css-modules--string
dist
css-modules--string.css
css-modules--string.esm.js
css-modules--string.js
css-modules--string.umd.js
package.json
src
index.js
scoped.css
scoped.module.css
Build \\"cssModulesString\\" to dist:
166 B: css-modules--string.js.gz
118 B: css-modules--string.js.br
166 B: css-modules--string.esm.js.gz
117 B: css-modules--string.esm.js.br
264 B: css-modules--string.umd.js.gz
193 B: css-modules--string.umd.js.br"
`;
exports[`fixtures build css-modules--string with microbundle 2`] = `4`;
exports[`fixtures build css-modules--string with microbundle 3`] = `
"body{display:-webkit-box;display:flex;color:red;background:#00f}._contains_this_81567d0efc15a456670452d3277e1a68{background-color:#00f}
._contains_this_0a8c24df242c2cd708036873307aea94{color:pink}"
`;
exports[`fixtures build css-modules--string with microbundle 4`] = `
"export default function(){var a=document.createElement(\\"div\\");return a.className=\\"_contains_this_0a8c24df242c2cd708036873307aea94 _contains_this_81567d0efc15a456670452d3277e1a68\\",a}
"
`;
exports[`fixtures build css-modules--string with microbundle 5`] = `
"module.exports=function(){var e=document.createElement(\\"div\\");return e.className=\\"_contains_this_0a8c24df242c2cd708036873307aea94 _contains_this_81567d0efc15a456670452d3277e1a68\\",e};
"
`;
exports[`fixtures build css-modules--string with microbundle 6`] = `
"!function(e,n){\\"object\\"==typeof exports&&\\"undefined\\"!=typeof module?module.exports=n():\\"function\\"==typeof define&&define.amd?define(n):(e=e||self).cssModulesString=n()}(this,function(){return function(){var e=document.createElement(\\"div\\");return e.className=\\"_contains_this_0a8c24df242c2cd708036873307aea94 _contains_this_81567d0efc15a456670452d3277e1a68\\",e}});
"
`;
exports[`fixtures build css-modules--true with microbundle 1`] = `
"Used script: microbundle --no-sourcemap --css-modules true
Directory tree:
css-modules--true
dist
css-modules--true.css
css-modules--true.esm.js
css-modules--true.js
css-modules--true.umd.js
package.json
src
index.js
scoped.css
scoped.module.css
Build \\"cssModulesTrue\\" to dist:
118 B: css-modules--true.js.gz
80 B: css-modules--true.js.br
117 B: css-modules--true.esm.js.gz
77 B: css-modules--true.esm.js.br
212 B: css-modules--true.umd.js.gz
149 B: css-modules--true.umd.js.br"
`;
exports[`fixtures build css-modules--true with microbundle 2`] = `4`;
exports[`fixtures build css-modules--true with microbundle 3`] = `
"body{display:-webkit-box;display:flex;color:red;background:#00f}._1E6DU{background-color:#00f}
._2kWDE{color:pink}"
`;
exports[`fixtures build css-modules--true with microbundle 4`] = `
"export default function(){var e=document.createElement(\\"div\\");return e.className=\\"_2kWDE _1E6DU\\",e}
"
`;
exports[`fixtures build css-modules--true with microbundle 5`] = `
"module.exports=function(){var e=document.createElement(\\"div\\");return e.className=\\"_2kWDE _1E6DU\\",e};
"
`;
exports[`fixtures build css-modules--true with microbundle 6`] = `
"!function(e,n){\\"object\\"==typeof exports&&\\"undefined\\"!=typeof module?module.exports=n():\\"function\\"==typeof define&&define.amd?define(n):(e=e||self).cssModulesTrue=n()}(this,function(){return function(){var e=document.createElement(\\"div\\");return e.className=\\"_2kWDE _1E6DU\\",e}});
"
`;
exports[`fixtures build custom-babelrc with microbundle 1`] = `
"Used script: microbundle
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/css-modules--false/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "css-modules--false",
"scripts": {
"build": "microbundle --no-sourcemap --css-modules false"
}
}
4 changes: 4 additions & 0 deletions test/fixtures/css-modules--false/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import './not_scoped.css';
import './not_scoped.module.css';

export default function() {}
9 changes: 9 additions & 0 deletions test/fixtures/css-modules--false/src/not_scoped.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
body {
display: flex;
color: red;
background: blue;
}

.test_class_that_shouldnt_be_scoped {
background-color: blue;
}
3 changes: 3 additions & 0 deletions test/fixtures/css-modules--false/src/not_scoped.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.not_scoped_class {
color: pink;
}
6 changes: 6 additions & 0 deletions test/fixtures/css-modules--null/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "css-modules--null",
"scripts": {
"build": "microbundle --no-sourcemap"
}
}
8 changes: 8 additions & 0 deletions test/fixtures/css-modules--null/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import './not_scoped.css';
import scoped from './scoped.module.css';

export default function() {
const el = document.createElement('div');
el.className = scoped.scoped_class;
return el;
}
9 changes: 9 additions & 0 deletions test/fixtures/css-modules--null/src/not_scoped.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
body {
display: flex;
color: red;
background: blue;
}

.test_class_that_shouldnt_be_scoped {
background-color: blue;
}
3 changes: 3 additions & 0 deletions test/fixtures/css-modules--null/src/scoped.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.scoped_class {
color: pink;
}
6 changes: 6 additions & 0 deletions test/fixtures/css-modules--string/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "css-modules--string",
"scripts": {
"build": "microbundle --no-sourcemap --css-modules '_contains_this_[hash]'"
}
}
9 changes: 9 additions & 0 deletions test/fixtures/css-modules--string/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import global from './scoped.css';
import scoped from './scoped.module.css';

export default function() {
const el = document.createElement('div');
el.className =
scoped.scoped_class + ' ' + global.test_class_that_should_be_scoped;
return el;
}
Loading

0 comments on commit 5100c7b

Please sign in to comment.