From 8c7d721b4beb13cac506934107fa4b8608af4208 Mon Sep 17 00:00:00 2001 From: DAB0mB Date: Sat, 12 Jan 2019 10:11:56 +0800 Subject: [PATCH] Initial commit --- .babelrc | 28 + .circleci/config.yml | 37 + .eslintrc | 8 + .gitignore | 4 + .npmignore | 2 + LICENSE | 21 + README.md | 90 + package.json | 57 + src/babel-plugin-react-persist.test.js | 364 ++ src/index.js | 177 + webpack_config.js | 46 + yarn.lock | 6349 ++++++++++++++++++++++++ 12 files changed, 7183 insertions(+) create mode 100644 .babelrc create mode 100644 .circleci/config.yml create mode 100644 .eslintrc create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 package.json create mode 100644 src/babel-plugin-react-persist.test.js create mode 100644 src/index.js create mode 100644 webpack_config.js create mode 100644 yarn.lock diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..fd924fc --- /dev/null +++ b/.babelrc @@ -0,0 +1,28 @@ +{ + "presets": [ + "@babel/preset-env" + ], + "plugins": [ + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-syntax-import-meta", + "@babel/plugin-proposal-class-properties", + "@babel/plugin-proposal-json-strings", + [ + "@babel/plugin-proposal-decorators", + { + "legacy": true + } + ], + "@babel/plugin-proposal-function-sent", + "@babel/plugin-proposal-export-namespace-from", + "@babel/plugin-proposal-numeric-separator", + "@babel/plugin-proposal-throw-expressions" + ], + "env": { + "test": { + "plugins": [ + "@babel/plugin-transform-modules-commonjs" + ] + } + } +} diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..b1dbc18 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,37 @@ +# Javascript Node CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-javascript/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: circleci/node:9.2.0 + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/mongo:3.4.4 + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + # run tests! + - run: npm test + + diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..5364fd0 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,8 @@ +{ + "env": { "es6": true, "node": true }, + "extends": "eslint:recommended", + "parser": "babel-eslint", + "rules": { + "no-console": 0 + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dac34e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build +node_modules +npm-debug.log +yarn-error.log diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..2218721 --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +!build +webpack_config.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bc5d8d1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2018 Eytan Manor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c3d920e --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +[![CircleCI](https://circleci.com/gh/DAB0mB/babel-plugin-react-persist/tree/master.svg?style=svg)](https://circleci.com/gh/DAB0mB/babel-plugin-react-persist/tree/master) + +# babel-plugin-react-persist + +A Babel plug-in that optimizes your React components' implementation by automatically detecting declarations that should persist between rendering phases and replacing them with `useCallback()` and `useMemo()` whenever necessary. This plug-in can also be used with inline anonymous functions in JSX attributes and solve excessive processing power issues. **Note that this plug-in is experimental and shouldn't be used in production yet**. Compatible with React 16.7 and above (hooks support). + +### Example + +#### in + +```jsx +export default ({ + data, + sortComparator, + filterPredicate, + history, +}) => { + const transformedData = data + .filter(filterPredicate) + .sort(sortComparator) + + return ( +
+
+ ) +} +``` + +#### out + +```jsx +export default (({ + data, + sortComparator, + filterPredicate, + history, +}) => { + const transformedData = React.useMemo(() => + data + .filter(filterPredicate) + .sort(sortComparator) + , [data, filterPredicate, sortComparator]) + + const _onClick = React.useCallback(() => + history.pop() + , [history]) + + return ( +
+
+ ) +}) +``` + +### Usage + +`babel-plugin-react-persist` is installable via NPM (or Yarn): + + $ npm install babel-plugin-react-persist + +Add to `.babelrc` under `plugins` and be sure to load it **before** any JSX transformation related plug-ins. + +```json +{ + "presets": ["@babel/preset-react"], + "plugins": ["babel-plugin-react-persist"] +} +``` + +### License + +MIT. If you're including this in a repo above 1k stars I would really appreciate it if you could contact me first. diff --git a/package.json b/package.json new file mode 100644 index 0000000..0ce140c --- /dev/null +++ b/package.json @@ -0,0 +1,57 @@ +{ + "name": "babel-plugin-react-persist", + "version": "0.1.0", + "description": "Automatically useCallback() and useMemo()", + "license": "MIT", + "repository": "https://github.com/DAB0mB/babel-plugin-react-persist.git", + "main": "build/babel-plugin-react-persist.js", + "scripts": { + "build": "webpack --config webpack_config.js", + "test": "npm run build && jest", + "prepublish": "npm run build" + }, + "dependencies": { + "@babel/generator": "^7.2.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "devDependencies": { + "@babel/core": "^7.2.0", + "@babel/plugin-proposal-class-properties": "^7.2.1", + "@babel/plugin-proposal-decorators": "^7.2.0", + "@babel/plugin-proposal-export-namespace-from": "^7.2.0", + "@babel/plugin-proposal-function-sent": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-numeric-separator": "^7.2.0", + "@babel/plugin-proposal-throw-expressions": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-import-meta": "^7.2.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/preset-env": "^7.0.0", + "babel-core": "^7.0.0-bridge.0", + "babel-eslint": "^9.0.0", + "babel-jest": "^23.4.2", + "babel-loader": "^8.0.0", + "eslint": "^5.1.0", + "eslint-loader": "^2.1.0", + "jest": "^23.6.0", + "webpack": "^4.16.1", + "webpack-cli": "^3.1.0", + "webpack-node-externals": "^1.7.2" + }, + "jest": { + "testEnvironment": "node", + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.js$", + "globals": { + "NODE_ENV": "test" + }, + "moduleFileExtensions": [ + "js", + "jsx", + "json", + "node" + ] + } +} diff --git a/src/babel-plugin-react-persist.test.js b/src/babel-plugin-react-persist.test.js new file mode 100644 index 0000000..34ce7ae --- /dev/null +++ b/src/babel-plugin-react-persist.test.js @@ -0,0 +1,364 @@ +import * as babel from '@babel/core' +import jsxPlugin from '@babel/plugin-syntax-jsx' +import useCallbackPlugin from '.' + +describe('babel-plugin-react-persist', () => { + it('should replace defined functions', () => { + const code = transform(` + () => { + const callback = () => { + alert('clicked') + } + + return ( +