Code Monkey home page Code Monkey logo

babel-plugin-optimize-clsx's Introduction

babel-plugin-optimize-clsx

Babel plugin to optimize the use of clsx, classnames, and all libraries with a compatible API

Install

yarn add babel-plugin-optimize-clsx --dev
or
npm install babel-plugin-optimize-clsx --save-dev

Requirements

Name Version
Babel ^7.0.0
Node >=8

Examples

Object properties

clsx({
	[classes.disabled]: disabled,
	[classes.focusVisible]: focusVisible && !disabled,
});

// Transforms to

clsx(disabled && classes.disabled, focusVisible && !disabled && classes.focusVisible);

Conditional expressions

clsx({
	[classes.disabled]: disabled,
	[classes.focusVisible]: focusVisible && !disabled,
});

// Transforms to

clsx(disabled ? classes.disabled : focusVisible && classes.focusVisible);

Combine arguments

clsx({
	[classes.focusVisible]: this.state.focusVisible,
	[focusVisibleClassName]: this.state.focusVisible,
});

// Transforms to

clsx(this.state.focusVisible && [classes.focusVisible, focusVisibleClassName]);

PropTypes

function foo(props) {
	const { position: p } = props;
	const x = clsx({
		[classes.x]: p === 'top',
		[classes.y]: p === 'bottom',
	});
}

foo.propTypes = {
	position: PropTypes.oneOf(['top', 'bottom']),
};

// Transforms to

function foo(props) {
	const { position: p } = props;
	const x = clsx(p === 'top' ? classes.x : classes.y);
}

foo.propTypes = {
	position: PropTypes.oneOf(['top', 'bottom']),
};

String literals

const x = clsx({
	btn: true,
	'col-md-1': true,
	['btn-primary']: true,
});

// Transforms to

const x = 'btn col-md-1 btn-primary';

Unnecessary function calls

const x = clsx({
	btn: true,
	'btn-foo': isDisabled,
	'btn-bar': !isDisabled,
});

// Transforms to

const x = 'btn ' + (isDisabled ? 'btn-foo' : 'btn-bar');

Benchmarks

Benchmarks can be found in the benchmark directory

Options

Name Type Default value
libraries string[] ['clsx', 'classnames']

By default the plugin looks for import and require statements for clsx and classnames and uses that to know which function calls to optimize. If you're using another library with a compatible API you can overwrite that with this option.

{
	"plugins": [
		[
			"babel-plugin-optimize-clsx",
			{
				"libraries": ["clsx", "classnames", "my-custom-library"]
			}
		]
	]
}

Name Type Default value
functionNames string[] []

If you want the plugin to match on all functions with a specific name, no matter where it comes from you can specify them using this option. An example for this is if you have clsx as a global function and thus don't import it.

{
	"plugins": [
		[
			"babel-plugin-optimize-clsx",
			{
				"functionNames": ["myClsxImplementation"]
			}
		]
	]
}

Name Type Default value
removeUnnecessaryCalls boolean true

By default the plugin will remove unnecessary function calls and if all calls are removed, imports. If you need to keep them, you can set this option to false.

Example of some unnecessary calls

import clsx from 'clsx';
const x = clsx('foo', 'bar');
const y = clsx({ classA: foo === 'a', classB: foo !== 'a' });
const z = clsx({
	classA: foo === 'a',
	classB: foo !== 'a',
	classC: bar === 'c',
	classD: bar !== 'c',
});

// Transforms to

const x = 'foo bar';
const y = foo === 'a' ? 'classA' : 'classB';
const z = (foo === 'a' ? 'classA ' : 'classB ') + (bar === 'c' ? 'classC' : 'classD');

Name Type Default value
collectCalls boolean false

Writes all function calls, before they are optimized, to a file. Used to help test the plugin on repositories.

babel-plugin-optimize-clsx's People

Contributors

antonk52 avatar dependabot-preview[bot] avatar merceyz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

babel-plugin-optimize-clsx's Issues

Support JSX props

Hey ๐Ÿ‘‹

Was wondering if you'd be interested in supporting JSX props as valid targets for optimisation? Our component library uses the clsx API for it's className prop and would be a valid target for optimisation.

e.g.

<Box className={{
  [classes.disabled]: disabled,
  [classes.focusVisible]: focusVisible && !disabled,
}} />

// Transforms to

<Box className={[disabled && classes.disabled, focusVisible && !disabled && classes.focusVisible]} />

Understand this is a slightly different scenario but still relevant.

Issues integrating with DestinyItemManager

I tried this out for DIM in DestinyItemManager/DIM#4225 but ended up having to roll back because we saw the list of classes for some of our components getting collapsed into nothing. I tried writing a test in this repo that matched what we were doing, but it worked there. So it must have been something about our particular setup, either with babel/webpack caching or something else.

The code that was getting messed up looked like this:

classNames('store-cell', 'account-wide', `bucket-${bucket.id}`);

I think if I remember right this was getting transformed into the string "bucket-".

I'm not sure if there were other parts that were getting broken. It had looked fine when running in the development server, but after I had to roll back I noticed that if I was running in the dev server it would render fine on the first pass, but if I hot-reloaded a file then it would start deleting my classes.

Incorrect handling of objects with computed property names

I've noticed incorrect behavior when clsx is called with an object with computed property names.
A simplified case:

const checkedClassName = 'checked';

const stateClasses = {
    [checkedClassName]: isChecked,
};

return (
    <div className={clsx(stateClasses)} />
);

produces the following output:

var checkedClassName = 'checked';
var stateClasses = (0, _clsx["default"])(isChecked && checkedClassName);
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
    className: clsx(stateClasses)
});

Notice the clsx instead of _clsx in 4th line.

If, however, the stateClasses object is used in any way before being passed in to clsx, all the calls are correctly transformed:

const checkedClassName = 'checked';

const stateClasses = {
    [checkedClassName]: isChecked,
};

console.log(stateClasses);

return (
    <div className={clsx(stateClasses)} />
);

is transformed into

var checkedClassName = 'checked';
var stateClasses = (0, _defineProperty2["default"])({}, checkedClassName, isChecked);
console.log(stateClasses);
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
    className: (0, _clsx["default"])(stateClasses)
});

Support Tagged template literals

Hi @merceyz thanks for this plugin.

I was wonder if it possible to support Tagged template literals. Here an example with cslx:

const classes = clsx`bg-white text-gray-800`;
const multiline = clsx`
  bg-white
  text-gray-800
`;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.