From c9494f367257e23725ec2e5234702c72aefbb050 Mon Sep 17 00:00:00 2001 From: "Ahmed T. Ali" Date: Thu, 26 Nov 2020 11:08:23 +0100 Subject: [PATCH] perf(macro): faster Rem value transformation No longer traverse the whole module just to transform Rem values. --- .github/workflows/main.yml | 3 ++ package.json | 5 +-- src/babel/inject-styles.ts | 51 +++++++++++++++++++++++++++ src/macro.ts | 70 ++++---------------------------------- yarn.lock | 2 +- 5 files changed, 65 insertions(+), 66 deletions(-) create mode 100644 src/babel/inject-styles.ts diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ccaa471..cc20ae3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,6 +42,9 @@ jobs: - name: Install dependencies run: yarn + - name: Build the package + run: yarn build + - name: Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/package.json b/package.json index 61512a5..8e45a0b 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,9 @@ "babel-plugin-macros" ], "scripts": { - "prepare": "bob build", + "build": "rimraf -rf build && bob build", "lint": "eslint \"**/*.{js,ts,tsx}\"", - "test": "bob build && jest", + "test": "yarn build && jest", "semantic-release": "semantic-release", "utils-gen": "ts-node ./scripts/utils-gen.ts", "bootstrap:example": "yarn --cwd example", @@ -69,6 +69,7 @@ "react-native": "^0.63.3", "react-native-web": "^0.14.8", "react-test-renderer": "^17.0.1", + "rimraf": "^3.0.2", "semantic-release": "^17.3.0", "ts-node": "^9.0.0", "type-fest": "^0.20.1", diff --git a/src/babel/inject-styles.ts b/src/babel/inject-styles.ts new file mode 100644 index 0000000..7c8403d --- /dev/null +++ b/src/babel/inject-styles.ts @@ -0,0 +1,51 @@ +// Packages +import * as t from '@babel/types'; +import traverse from '@babel/traverse'; +import { NodePath } from '@babel/core'; + +// Ours +import { importStyleSheet, importUtil } from './add-import'; + +export function injectStyles( + program: NodePath, + stylesVariableId: t.Identifier, + styles: Record> +) { + // Use StyleSheet.create + // => const styles = StyleSheet.create({...}) + const stylesheet = t.variableDeclaration('const', [ + t.variableDeclarator( + stylesVariableId, + t.callExpression( + t.memberExpression( + importStyleSheet(program), + t.identifier('create') + ), + [t.valueToNode(styles)] + ) + ), + ]); + + // Handle Rem values + traverse(stylesheet, { + noScope: true, + StringLiteral: (path) => { + // Replace Rem values with function calls + if (path.node.value.match(/rem/)) { + const remValue = parseFloat( + path.node.value.replace(/rem|\(|\)/g, '') + ); + + path.replaceWith( + t.callExpression(importUtil(program, 'rem'), [ + t.numericLiteral(remValue), + ]) + ); + } + }, + }); + + // Create stylesheet + // => const styles = StyleSheet.create({...}) + program.unshiftContainer('body' as any, stylesheet); +} diff --git a/src/macro.ts b/src/macro.ts index 4108b7a..e4b7874 100644 --- a/src/macro.ts +++ b/src/macro.ts @@ -1,69 +1,14 @@ // Packages import * as t from '@babel/types'; -import traverse from '@babel/traverse'; -import { NodePath } from '@babel/core'; import { createMacro, MacroHandler } from 'babel-plugin-macros'; // Ours import { evalNode } from './babel/eval-node'; import { StyledMacro } from './styling/types'; import { resolveTokens } from './styling/tokens'; +import { importUtil } from './babel/add-import'; +import { injectStyles } from './babel/inject-styles'; import { DEFAULT_VARIANT } from './styling/utils/defaultVariant'; -import { importStyleSheet, importUtil } from './babel/add-import'; - -const transformRem = (program: NodePath) => { - traverse(program.parent, { - StringLiteral: (path) => { - if (!t.isObjectProperty(path.parent)) { - return; - } - - // Transform values only - if (!t.isNodesEquivalent(path.parent.value, path.node)) { - return; - } - - const { value } = path.node; - - // Replace Rem values with function calls - if (value.match(/rem/)) { - const remValue = parseFloat(value.replace(/rem|\(|\)/g, '')); - - // => { style: rem(number) } - path.replaceWith( - t.callExpression(importUtil(program, 'rem'), [ - t.numericLiteral(remValue), - ]) - ); - } - }, - }); -}; - -const createStyleSheet = ( - program: NodePath, - stylesId: t.Identifier, - styles: Record> -) => { - // Use StyleSheet.create - // => const styles = StyleSheet.create({...}) - const stylesheet = t.variableDeclaration('const', [ - t.variableDeclarator( - stylesId, - t.callExpression( - t.memberExpression( - importStyleSheet(program), - t.identifier('create') - ), - [t.valueToNode(styles)] - ) - ), - ]); - - // Create stylesheet - // => const styles = StyleSheet.create({...}) - program.unshiftContainer('body' as any, stylesheet); -}; const styledMacro: MacroHandler = ({ references, state }) => { const program = state.file.path; @@ -72,7 +17,9 @@ const styledMacro: MacroHandler = ({ references, state }) => { const styles: Record> = {}; // Variable name to be used later with StyleSheet.create - const stylesId = program.scope.generateUidIdentifier('styles'); + const stylesVariableId = program.scope.generateUidIdentifier( + 'styles' + ); references.default?.forEach((refPath) => { if (!t.isCallExpression(refPath.parent)) { @@ -129,7 +76,7 @@ const styledMacro: MacroHandler = ({ references, state }) => { // => { style: styles.styleId } t.objectProperty( t.identifier('style'), - t.memberExpression(stylesId, styleId) + t.memberExpression(stylesVariableId, styleId) ), ]); }) @@ -161,10 +108,7 @@ const styledMacro: MacroHandler = ({ references, state }) => { // Inject generated styles to the module if (Object.keys(styles).length > 0) { - createStyleSheet(program, stylesId, styles); - - // Convert Rem string literals to function calls - transformRem(program); + injectStyles(program, stylesVariableId, styles); } }; diff --git a/yarn.lock b/yarn.lock index ecdca7b..65be12e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10334,7 +10334,7 @@ rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: dependencies: glob "^7.1.3" -rimraf@^3.0.0: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==