react-native-boost 0.7.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -7
- package/dist/plugin/esm/index.mjs +219 -43
- package/dist/plugin/esm/index.mjs.map +1 -1
- package/dist/plugin/index.d.ts +54 -0
- package/dist/plugin/index.js +219 -43
- package/dist/plugin/index.js.map +1 -1
- package/dist/runtime/esm/index.mjs +15 -3
- package/dist/runtime/esm/index.mjs.map +1 -1
- package/dist/runtime/esm/index.web.mjs.map +1 -1
- package/dist/runtime/index.d.ts +49 -3
- package/dist/runtime/index.js +16 -4
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/index.web.d.ts +11 -0
- package/dist/runtime/index.web.js.map +1 -1
- package/package.json +3 -2
- package/src/plugin/index.ts +26 -4
- package/src/plugin/optimizers/text/index.ts +52 -21
- package/src/plugin/optimizers/view/index.ts +57 -10
- package/src/plugin/types/index.ts +61 -21
- package/src/plugin/utils/common/validation.ts +23 -28
- package/src/plugin/utils/generate-test-plugin.ts +7 -1
- package/src/plugin/utils/helpers.ts +15 -0
- package/src/plugin/utils/logger.ts +123 -2
- package/src/runtime/components/native-text.tsx +21 -5
- package/src/runtime/components/native-view.tsx +21 -5
- package/src/runtime/index.ts +20 -0
- package/src/runtime/types/index.ts +5 -0
- package/src/runtime/utils/constants.ts +6 -2
package/README.md
CHANGED
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
A powerful Babel plugin that automatically optimizes React Native apps through static source code analysis. It replaces standard React Native components with their native counterparts where possible, leading to significant performance improvements.
|
|
6
6
|
|
|
7
|
-
> [!WARNING]
|
|
8
|
-
> The library and its Babel plugin are still experimental. You should expect things to break. Please report any issues you encounter in the issues tab with reproducible examples, and use the library's ignore mechanisms to disable optimizations for problematic files or lines of code.
|
|
9
|
-
|
|
10
7
|
- ⚡ Automatic performance optimization through source code analysis
|
|
11
8
|
- 🔒 Safe optimizations that don't break your app
|
|
12
9
|
- 🎯 Virtually zero runtime overhead
|
|
@@ -23,10 +20,19 @@ The documentation is available at [react-native-boost.oss.kuatsu.de](https://rea
|
|
|
23
20
|
The app in the `apps/example` directory serves as a benchmark for the performance of the plugin.
|
|
24
21
|
|
|
25
22
|
<div align="center">
|
|
26
|
-
<img src="./apps/docs/docs/
|
|
23
|
+
<img src="./apps/docs/content/docs/information/img/benchmark-ios.png" width="500" />
|
|
27
24
|
</div>
|
|
28
25
|
|
|
29
|
-
More benchmarks are available in the [docs](https://react-native-boost.oss.kuatsu.de/docs/
|
|
26
|
+
More benchmarks are available in the [docs](https://react-native-boost.oss.kuatsu.de/docs/information/benchmarks).
|
|
27
|
+
|
|
28
|
+
## Compatibility
|
|
29
|
+
|
|
30
|
+
| `react-native-boost` | React Native |
|
|
31
|
+
| -------------------- | ---------------- |
|
|
32
|
+
| `0.x` | All versions[^1] |
|
|
33
|
+
| `1.x` | `>=0.83` |
|
|
34
|
+
|
|
35
|
+
[^1]: Starting from React Native `0.80`, `react-native-boost@0` prints import deprecation warnings.
|
|
30
36
|
|
|
31
37
|
## Installation
|
|
32
38
|
|
|
@@ -62,11 +68,11 @@ yarn start --clear
|
|
|
62
68
|
|
|
63
69
|
That's it! No imports in your code, rebuilding, or anything else is required.
|
|
64
70
|
|
|
65
|
-
Optionally, you can configure the Babel plugin with a few options described in the [documentation](https://react-native-boost.oss.kuatsu.de/docs/
|
|
71
|
+
Optionally, you can configure the Babel plugin with a few options described in the [documentation](https://react-native-boost.oss.kuatsu.de/docs/configuration/configure).
|
|
66
72
|
|
|
67
73
|
## How it works
|
|
68
74
|
|
|
69
|
-
A technical rundown of how the plugin works can be found in the [docs](https://react-native-boost.oss.kuatsu.de/docs/
|
|
75
|
+
A technical rundown of how the plugin works can be found in the [docs](https://react-native-boost.oss.kuatsu.de/docs/information/how-it-works).
|
|
70
76
|
|
|
71
77
|
## Contributing
|
|
72
78
|
|
|
@@ -15,6 +15,14 @@ const ensureArray = (value) => {
|
|
|
15
15
|
if (Array.isArray(value)) return value;
|
|
16
16
|
return [value];
|
|
17
17
|
};
|
|
18
|
+
const getFirstBailoutReason = (checks) => {
|
|
19
|
+
for (const check of checks) {
|
|
20
|
+
if (check.shouldBail()) {
|
|
21
|
+
return check.reason;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
};
|
|
18
26
|
|
|
19
27
|
const isIgnoredFile = (path, ignores) => {
|
|
20
28
|
const hub = path.hub;
|
|
@@ -32,17 +40,23 @@ const isIgnoredFile = (path, ignores) => {
|
|
|
32
40
|
}
|
|
33
41
|
return false;
|
|
34
42
|
};
|
|
43
|
+
const isForcedLine = (path) => {
|
|
44
|
+
return hasDecoratorComment(path, "@boost-force");
|
|
45
|
+
};
|
|
35
46
|
const isIgnoredLine = (path) => {
|
|
47
|
+
return hasDecoratorComment(path, "@boost-ignore");
|
|
48
|
+
};
|
|
49
|
+
function hasDecoratorComment(path, decorator) {
|
|
36
50
|
var _a, _b, _c;
|
|
37
|
-
if ((_a = path.node.leadingComments) == null ? void 0 : _a.some((comment) => comment.value.includes(
|
|
51
|
+
if ((_a = path.node.leadingComments) == null ? void 0 : _a.some((comment) => comment.value.includes(decorator))) {
|
|
38
52
|
return true;
|
|
39
53
|
}
|
|
40
54
|
const jsxElementPath = path.parentPath;
|
|
41
|
-
if ((_b = jsxElementPath.node.leadingComments) == null ? void 0 : _b.some((comment) => comment.value.includes(
|
|
55
|
+
if ((_b = jsxElementPath.node.leadingComments) == null ? void 0 : _b.some((comment) => comment.value.includes(decorator))) {
|
|
42
56
|
return true;
|
|
43
57
|
}
|
|
44
58
|
const propertyPath = jsxElementPath.parentPath;
|
|
45
|
-
if (propertyPath && propertyPath.isObjectProperty() && ((_c = propertyPath.node.leadingComments) == null ? void 0 : _c.some((comment) => comment.value.includes(
|
|
59
|
+
if (propertyPath && propertyPath.isObjectProperty() && ((_c = propertyPath.node.leadingComments) == null ? void 0 : _c.some((comment) => comment.value.includes(decorator)))) {
|
|
46
60
|
return true;
|
|
47
61
|
}
|
|
48
62
|
if (!jsxElementPath.parentPath) return false;
|
|
@@ -63,18 +77,18 @@ const isIgnoredLine = (path) => {
|
|
|
63
77
|
...expression.node.trailingComments || [],
|
|
64
78
|
...expression.node.innerComments || []
|
|
65
79
|
].map((comment) => comment.value.trim());
|
|
66
|
-
if (comments.some((comment) => comment.includes(
|
|
80
|
+
if (comments.some((comment) => comment.includes(decorator))) {
|
|
67
81
|
return true;
|
|
68
82
|
}
|
|
69
83
|
}
|
|
70
84
|
}
|
|
71
|
-
if (sibling.node.leadingComments && sibling.node.leadingComments.some((comment) => comment.value.includes(
|
|
85
|
+
if (sibling.node.leadingComments && sibling.node.leadingComments.some((comment) => comment.value.includes(decorator))) {
|
|
72
86
|
return true;
|
|
73
87
|
}
|
|
74
88
|
break;
|
|
75
89
|
}
|
|
76
90
|
return false;
|
|
77
|
-
}
|
|
91
|
+
}
|
|
78
92
|
const isValidJSXComponent = (path, componentName) => {
|
|
79
93
|
if (!types.isJSXIdentifier(path.node.name)) return false;
|
|
80
94
|
const parent = path.parent;
|
|
@@ -111,11 +125,8 @@ const isReactNativeImport = (path, expectedImportedName) => {
|
|
|
111
125
|
}
|
|
112
126
|
return false;
|
|
113
127
|
};
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
if (classification === "text") return true;
|
|
117
|
-
if (classification === "unknown" && !allowUnknownAncestors) return true;
|
|
118
|
-
return false;
|
|
128
|
+
const getViewAncestorClassification = (path) => {
|
|
129
|
+
return classifyViewAncestors(path);
|
|
119
130
|
};
|
|
120
131
|
function classifyViewAncestors(path) {
|
|
121
132
|
const context = {
|
|
@@ -729,25 +740,53 @@ const textBlacklistedProperties = /* @__PURE__ */ new Set([
|
|
|
729
740
|
"selectionColor"
|
|
730
741
|
// TODO: we can use react-native's internal `processColor` to process this at runtime
|
|
731
742
|
]);
|
|
732
|
-
const textOptimizer = (path,
|
|
733
|
-
}) => {
|
|
734
|
-
var _a, _b, _c;
|
|
735
|
-
if (isIgnoredLine(path)) return;
|
|
743
|
+
const textOptimizer = (path, logger) => {
|
|
736
744
|
if (!isValidJSXComponent(path, "Text")) return;
|
|
737
745
|
if (!isReactNativeImport(path, "Text")) return;
|
|
738
|
-
if (hasBlacklistedProperty(path, textBlacklistedProperties)) return;
|
|
739
|
-
if (hasExpoRouterLinkParentWithAsChild(path)) return;
|
|
740
746
|
const parent = path.parent;
|
|
741
|
-
|
|
747
|
+
const forced = isForcedLine(path);
|
|
748
|
+
const overridableChecks = [
|
|
749
|
+
{
|
|
750
|
+
reason: "contains blacklisted props",
|
|
751
|
+
shouldBail: () => hasBlacklistedProperty(path, textBlacklistedProperties)
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
reason: "is a direct child of expo-router Link with asChild",
|
|
755
|
+
shouldBail: () => hasExpoRouterLinkParentWithAsChild(path)
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
reason: "contains non-string children",
|
|
759
|
+
shouldBail: () => hasInvalidChildren(path, parent)
|
|
760
|
+
}
|
|
761
|
+
];
|
|
762
|
+
if (forced) {
|
|
763
|
+
const overriddenReason = getFirstBailoutReason(overridableChecks);
|
|
764
|
+
if (overriddenReason) {
|
|
765
|
+
logger.forced({ component: "Text", path, reason: overriddenReason });
|
|
766
|
+
}
|
|
767
|
+
} else {
|
|
768
|
+
const skipReason = getFirstBailoutReason([
|
|
769
|
+
{
|
|
770
|
+
reason: "line is marked with @boost-ignore",
|
|
771
|
+
shouldBail: () => isIgnoredLine(path)
|
|
772
|
+
},
|
|
773
|
+
...overridableChecks
|
|
774
|
+
]);
|
|
775
|
+
if (skipReason) {
|
|
776
|
+
logger.skipped({ component: "Text", path, reason: skipReason });
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
742
780
|
const hub = path.hub;
|
|
743
781
|
const file = typeof hub === "object" && hub !== null && "file" in hub ? hub.file : void 0;
|
|
744
782
|
if (!file) {
|
|
745
783
|
throw new PluginError("No file found in Babel hub");
|
|
746
784
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
785
|
+
logger.optimized({
|
|
786
|
+
component: "Text",
|
|
787
|
+
path
|
|
788
|
+
});
|
|
789
|
+
fixNegativeNumberOfLines({ path, logger });
|
|
751
790
|
addDefaultProperty(path, "allowFontScaling", types.booleanLiteral(true));
|
|
752
791
|
addDefaultProperty(path, "ellipsizeMode", types.stringLiteral("tail"));
|
|
753
792
|
processProps(path, file);
|
|
@@ -763,10 +802,7 @@ function hasInvalidChildren(path, parent) {
|
|
|
763
802
|
}
|
|
764
803
|
return !parent.children.every((child) => isStringNode(path, child));
|
|
765
804
|
}
|
|
766
|
-
function fixNegativeNumberOfLines({
|
|
767
|
-
path,
|
|
768
|
-
log
|
|
769
|
-
}) {
|
|
805
|
+
function fixNegativeNumberOfLines({ path, logger }) {
|
|
770
806
|
for (const attribute of path.node.attributes) {
|
|
771
807
|
if (types.isJSXAttribute(attribute) && types.isJSXIdentifier(attribute.name, { name: "numberOfLines" }) && attribute.value && types.isJSXExpressionContainer(attribute.value)) {
|
|
772
808
|
let originalValue;
|
|
@@ -776,9 +812,11 @@ function fixNegativeNumberOfLines({
|
|
|
776
812
|
originalValue = -attribute.value.expression.argument.value;
|
|
777
813
|
}
|
|
778
814
|
if (originalValue !== void 0 && originalValue < 0) {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
815
|
+
logger.warning({
|
|
816
|
+
component: "Text",
|
|
817
|
+
path,
|
|
818
|
+
message: `'numberOfLines' must be a non-negative number, received: ${originalValue}. The value will be set to 0.`
|
|
819
|
+
});
|
|
782
820
|
attribute.value.expression = types.numericLiteral(0);
|
|
783
821
|
}
|
|
784
822
|
}
|
|
@@ -837,9 +875,101 @@ function processProps(path, file) {
|
|
|
837
875
|
);
|
|
838
876
|
}
|
|
839
877
|
|
|
840
|
-
const
|
|
841
|
-
|
|
878
|
+
const LOG_PREFIX = "[react-native-boost]";
|
|
879
|
+
const ANSI_RESET = "\x1B[0m";
|
|
880
|
+
const ANSI_GREEN = "\x1B[32m";
|
|
881
|
+
const ANSI_YELLOW = "\x1B[33m";
|
|
882
|
+
const ANSI_MAGENTA = "\x1B[35m";
|
|
883
|
+
const ANSI_RED = "\x1B[31m";
|
|
884
|
+
const noopLogger = {
|
|
885
|
+
optimized() {
|
|
886
|
+
},
|
|
887
|
+
skipped() {
|
|
888
|
+
},
|
|
889
|
+
forced() {
|
|
890
|
+
},
|
|
891
|
+
warning() {
|
|
892
|
+
}
|
|
842
893
|
};
|
|
894
|
+
const createLogger = ({ verbose, silent }) => {
|
|
895
|
+
if (silent) return noopLogger;
|
|
896
|
+
return {
|
|
897
|
+
optimized(payload) {
|
|
898
|
+
writeLog("optimized", `Optimized ${payload.component} in ${formatPathLocation(payload.path)}`);
|
|
899
|
+
},
|
|
900
|
+
skipped(payload) {
|
|
901
|
+
if (!verbose) return;
|
|
902
|
+
writeLog("skipped", `Skipped ${payload.component} in ${formatPathLocation(payload.path)} (${payload.reason})`);
|
|
903
|
+
},
|
|
904
|
+
forced(payload) {
|
|
905
|
+
writeLog(
|
|
906
|
+
"forced",
|
|
907
|
+
`Force-optimized ${payload.component} in ${formatPathLocation(payload.path)} (skipped bailout: ${payload.reason})`
|
|
908
|
+
);
|
|
909
|
+
},
|
|
910
|
+
warning(payload) {
|
|
911
|
+
const context = formatWarningContext(payload);
|
|
912
|
+
const message = context.length > 0 ? `${context}: ${payload.message}` : payload.message;
|
|
913
|
+
writeLog("warning", message);
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
};
|
|
917
|
+
function formatWarningContext(payload) {
|
|
918
|
+
const location = formatPathLocation(payload.path);
|
|
919
|
+
if (payload.component && location.length > 0) {
|
|
920
|
+
return `${payload.component} in ${location}`;
|
|
921
|
+
}
|
|
922
|
+
if (payload.component) {
|
|
923
|
+
return payload.component;
|
|
924
|
+
}
|
|
925
|
+
return location;
|
|
926
|
+
}
|
|
927
|
+
function writeLog(level, message) {
|
|
928
|
+
const levelTag = formatLevel(level);
|
|
929
|
+
console.log(`${LOG_PREFIX} ${levelTag} ${message}`);
|
|
930
|
+
}
|
|
931
|
+
function formatLevel(level) {
|
|
932
|
+
if (level === "optimized") {
|
|
933
|
+
return colorize("[optimized]", ANSI_GREEN);
|
|
934
|
+
}
|
|
935
|
+
if (level === "skipped") {
|
|
936
|
+
return colorize("[skipped]", ANSI_YELLOW);
|
|
937
|
+
}
|
|
938
|
+
if (level === "forced") {
|
|
939
|
+
return colorize("[forced]", ANSI_RED);
|
|
940
|
+
}
|
|
941
|
+
return colorize("[warning]", ANSI_MAGENTA);
|
|
942
|
+
}
|
|
943
|
+
function colorize(value, colorCode) {
|
|
944
|
+
if (!shouldUseColor()) return value;
|
|
945
|
+
return `${colorCode}${value}${ANSI_RESET}`;
|
|
946
|
+
}
|
|
947
|
+
function shouldUseColor() {
|
|
948
|
+
var _a, _b;
|
|
949
|
+
if (process.env.NO_COLOR != null) return false;
|
|
950
|
+
if (process.env.FORCE_COLOR === "0") return false;
|
|
951
|
+
if (process.env.FORCE_COLOR != null) return true;
|
|
952
|
+
if (process.env.CLICOLOR === "0") return false;
|
|
953
|
+
if (process.env.CLICOLOR_FORCE != null && process.env.CLICOLOR_FORCE !== "0") return true;
|
|
954
|
+
if (((_a = process.stdout) == null ? void 0 : _a.isTTY) === true || ((_b = process.stderr) == null ? void 0 : _b.isTTY) === true) {
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
const colorTerm = process.env.COLORTERM;
|
|
958
|
+
if (colorTerm != null && colorTerm !== "") {
|
|
959
|
+
return true;
|
|
960
|
+
}
|
|
961
|
+
const term = process.env.TERM;
|
|
962
|
+
return term != null && term !== "" && term.toLowerCase() !== "dumb";
|
|
963
|
+
}
|
|
964
|
+
function formatPathLocation(payloadPath) {
|
|
965
|
+
var _a, _b, _c, _d;
|
|
966
|
+
if (!payloadPath) return "unknown file:unknown line";
|
|
967
|
+
const hub = payloadPath.hub;
|
|
968
|
+
const file = typeof hub === "object" && hub !== null && "file" in hub ? hub.file : void 0;
|
|
969
|
+
const filename = (_b = (_a = file == null ? void 0 : file.opts) == null ? void 0 : _a.filename) != null ? _b : "unknown file";
|
|
970
|
+
const lineNumber = (_d = (_c = payloadPath.node.loc) == null ? void 0 : _c.start.line) != null ? _d : "unknown line";
|
|
971
|
+
return `${filename}:${lineNumber}`;
|
|
972
|
+
}
|
|
843
973
|
|
|
844
974
|
const viewBlacklistedProperties = /* @__PURE__ */ new Set([
|
|
845
975
|
// TODO: process a11y props at runtime
|
|
@@ -857,22 +987,58 @@ const viewBlacklistedProperties = /* @__PURE__ */ new Set([
|
|
|
857
987
|
"style"
|
|
858
988
|
// TODO: process style at runtime
|
|
859
989
|
]);
|
|
860
|
-
const viewOptimizer = (path,
|
|
861
|
-
}, options) => {
|
|
862
|
-
var _a, _b, _c;
|
|
863
|
-
if (isIgnoredLine(path)) return;
|
|
990
|
+
const viewOptimizer = (path, logger, options) => {
|
|
864
991
|
if (!isValidJSXComponent(path, "View")) return;
|
|
865
992
|
if (!isReactNativeImport(path, "View")) return;
|
|
866
|
-
|
|
867
|
-
|
|
993
|
+
let ancestorClassification;
|
|
994
|
+
const getAncestorClassification = () => {
|
|
995
|
+
if (!ancestorClassification) {
|
|
996
|
+
ancestorClassification = getViewAncestorClassification(path);
|
|
997
|
+
}
|
|
998
|
+
return ancestorClassification;
|
|
999
|
+
};
|
|
1000
|
+
const forced = isForcedLine(path);
|
|
1001
|
+
const overridableChecks = [
|
|
1002
|
+
{
|
|
1003
|
+
reason: "contains blacklisted props",
|
|
1004
|
+
shouldBail: () => hasBlacklistedProperty(path, viewBlacklistedProperties)
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
reason: "has Text ancestor",
|
|
1008
|
+
shouldBail: () => getAncestorClassification() === "text"
|
|
1009
|
+
},
|
|
1010
|
+
{
|
|
1011
|
+
reason: "has unresolved ancestor and dangerous optimization is disabled",
|
|
1012
|
+
shouldBail: () => getAncestorClassification() === "unknown" && (options == null ? void 0 : options.dangerouslyOptimizeViewWithUnknownAncestors) !== true
|
|
1013
|
+
}
|
|
1014
|
+
];
|
|
1015
|
+
if (forced) {
|
|
1016
|
+
const overriddenReason = getFirstBailoutReason(overridableChecks);
|
|
1017
|
+
if (overriddenReason) {
|
|
1018
|
+
logger.forced({ component: "View", path, reason: overriddenReason });
|
|
1019
|
+
}
|
|
1020
|
+
} else {
|
|
1021
|
+
const skipReason = getFirstBailoutReason([
|
|
1022
|
+
{
|
|
1023
|
+
reason: "line is marked with @boost-ignore",
|
|
1024
|
+
shouldBail: () => isIgnoredLine(path)
|
|
1025
|
+
},
|
|
1026
|
+
...overridableChecks
|
|
1027
|
+
]);
|
|
1028
|
+
if (skipReason) {
|
|
1029
|
+
logger.skipped({ component: "View", path, reason: skipReason });
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
868
1033
|
const hub = path.hub;
|
|
869
1034
|
const file = typeof hub === "object" && hub !== null && "file" in hub ? hub.file : void 0;
|
|
870
1035
|
if (!file) {
|
|
871
1036
|
throw new PluginError("No file found in Babel hub");
|
|
872
1037
|
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1038
|
+
logger.optimized({
|
|
1039
|
+
component: "View",
|
|
1040
|
+
path
|
|
1041
|
+
});
|
|
876
1042
|
const parent = path.parent;
|
|
877
1043
|
replaceWithNativeComponent(path, parent, file, "NativeView");
|
|
878
1044
|
};
|
|
@@ -884,9 +1050,9 @@ var index = declare((api) => {
|
|
|
884
1050
|
visitor: {
|
|
885
1051
|
JSXOpeningElement(path, state) {
|
|
886
1052
|
var _a, _b, _c, _d;
|
|
887
|
-
const
|
|
888
|
-
const
|
|
889
|
-
|
|
1053
|
+
const pluginState = state;
|
|
1054
|
+
const options = (_a = pluginState.opts) != null ? _a : {};
|
|
1055
|
+
const logger = getOrCreateLogger(pluginState, options);
|
|
890
1056
|
if (isIgnoredFile(path, (_b = options.ignores) != null ? _b : [])) return;
|
|
891
1057
|
if (((_c = options.optimizations) == null ? void 0 : _c.text) !== false) textOptimizer(path, logger);
|
|
892
1058
|
if (((_d = options.optimizations) == null ? void 0 : _d.view) !== false) viewOptimizer(path, logger, options);
|
|
@@ -894,6 +1060,16 @@ var index = declare((api) => {
|
|
|
894
1060
|
}
|
|
895
1061
|
};
|
|
896
1062
|
});
|
|
1063
|
+
function getOrCreateLogger(state, options) {
|
|
1064
|
+
if (state.__reactNativeBoostLogger) {
|
|
1065
|
+
return state.__reactNativeBoostLogger;
|
|
1066
|
+
}
|
|
1067
|
+
state.__reactNativeBoostLogger = createLogger({
|
|
1068
|
+
verbose: options.verbose === true,
|
|
1069
|
+
silent: options.silent === true
|
|
1070
|
+
});
|
|
1071
|
+
return state.__reactNativeBoostLogger;
|
|
1072
|
+
}
|
|
897
1073
|
|
|
898
1074
|
export { index as default };
|
|
899
1075
|
//# sourceMappingURL=index.mjs.map
|