Include full error messages in React Native build (#15363)
The React Native build does not minify error messages in production, but it still needs to run the error messages transform to compile `invariant` calls to `ReactError`. To do this, I added a `noMinify` option to the Babel plugin. I also renamed it from `minify-error-messages` to the more generic `transform-error-messages`.
Andrew Clark committed
Apr 9, 2019 at 16:40 UTC
875d05d5532b0e0b50faec6656a168cd9bb1a039
7 files changed
+61
-32
scripts/error-codes/README.md
+1
-1
@@ -12,6 +12,6 @@ provide a better debugging support in production. Check out the blog post
12
can test it by running `yarn build -- --extract-errors`, but you should only
13
commit changes to this file when running a release. (The release tool will
14
perform this step automatically.)
15
-- [`minify-error-codes`](https://github.com/facebook/react/blob/master/scripts/error-codes/minify-error-codes)
15
+- [`transform-error-messages`](https://github.com/facebook/react/blob/master/scripts/error-codes/transform-error-messages)
16
is a Babel pass that rewrites error messages to IDs for a production
17
(minified) build.
scripts/error-codes/__tests__/__snapshots__/transform-error-messages.js.snap
renamed
+11
@@ -94,3 +94,14 @@ import invariant from 'shared/invariant';
94
}
95
})();"
96
`;
97
+
98
+exports[`error transform should support noMinify option 1`] = `
99
+"import _ReactError from 'shared/ReactError';
100
+
101
+import invariant from 'shared/invariant';
102
+(function () {
103
+ if (!condition) {
104
+ throw _ReactError(\`Do not override existing functions.\`);
105
+ }
106
+})();"
107
+`;
scripts/error-codes/__tests__/transform-error-messages.js
renamed
+15
-3
@@ -8,11 +8,11 @@
8
'use strict';
9
10
let babel = require('babel-core');
11
-let devExpressionWithCodes = require('../minify-error-messages');
11
+let devExpressionWithCodes = require('../transform-error-messages');
12
13
-function transform(input) {
13
+function transform(input, options = {}) {
14
return babel.transform(input, {
15
- plugins: [devExpressionWithCodes],
15
+ plugins: [[devExpressionWithCodes, options]],
16
}).code;
17
}
18
@@ -82,4 +82,16 @@ invariant(condition, 'What\\'s up?');
82
`)
83
).toMatchSnapshot();
84
});
85
+
86
+ it('should support noMinify option', () => {
87
+ expect(
88
+ transform(
89
+ `
90
+import invariant from 'shared/invariant';
91
+invariant(condition, 'Do not override existing functions.');
92
+`,
93
+ {noMinify: true}
94
+ )
95
+ ).toMatchSnapshot();
96
+ });
97
});
scripts/error-codes/transform-error-messages.js
renamed
+2
-1
@@ -19,6 +19,7 @@ module.exports = function(babel) {
19
visitor: {
20
CallExpression(path, file) {
21
const node = path.node;
22
+ const noMinify = file.opts.noMinify;
23
if (path.get('callee').isIdentifier({name: 'invariant'})) {
24
// Turns this code:
25
//
@@ -66,7 +67,7 @@ module.exports = function(babel) {
67
const errorMap = invertObject(existingErrorMap);
68
69
let prodErrorId = errorMap[errorMsgLiteral];
69
- if (prodErrorId === undefined) {
70
+ if (prodErrorId === undefined || noMinify) {
71
// There is no error code for this message. We use a lint rule to
72
// enforce that messages can be minified, so assume this is
73
// intentional and exit gracefully.
scripts/jest/preprocessor.js
+1
-1
@@ -15,7 +15,7 @@ const pathToBabel = path.join(
15
'package.json'
16
);
17
const pathToBabelPluginDevWithCode = require.resolve(
18
- '../error-codes/minify-error-messages'
18
+ '../error-codes/transform-error-messages'
19
);
20
const pathToBabelPluginWrapWarning = require.resolve(
21
'../babel/wrap-warning-with-env-check'
scripts/rollup/build.js
+7
-2
@@ -113,7 +113,7 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
113
return Object.assign({}, options, {
114
plugins: options.plugins.concat([
115
// Minify invariant messages
116
- require('../error-codes/minify-error-messages'),
116
+ require('../error-codes/transform-error-messages'),
117
// Wrap warning() calls in a __DEV__ check so they are stripped from production.
118
require('../babel/wrap-warning-with-env-check'),
119
]),
@@ -126,6 +126,11 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
126
case RN_FB_PROFILING:
127
return Object.assign({}, options, {
128
plugins: options.plugins.concat([
129
+ [
130
+ require('../error-codes/transform-error-messages'),
131
+ // Preserve full error messages in React Native build
132
+ {noMinify: true},
133
+ ],
134
// Wrap warning() calls in a __DEV__ check so they are stripped from production.
135
require('../babel/wrap-warning-with-env-check'),
136
]),
@@ -141,7 +146,7 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
146
// Use object-assign polyfill in open source
147
path.resolve('./scripts/babel/transform-object-assign-require'),
148
// Minify invariant messages
144
- require('../error-codes/minify-error-messages'),
149
+ require('../error-codes/transform-error-messages'),
150
// Wrap warning() calls in a __DEV__ check so they are stripped from production.
151
require('../babel/wrap-warning-with-env-check'),
152
]),
scripts/rollup/results.json
+24
-24
@@ -578,57 +578,57 @@
578
"filename": "ReactNativeRenderer-dev.js",
579
"bundleType": "RN_FB_DEV",
580
"packageName": "react-native-renderer",
581
- "size": 645983,
582
- "gzip": 137694
581
+ "size": 720540,
582
+ "gzip": 154199
583
},
584
{
585
"filename": "ReactNativeRenderer-prod.js",
586
"bundleType": "RN_FB_PROD",
587
"packageName": "react-native-renderer",
588
- "size": 252030,
589
- "gzip": 44064
588
+ "size": 252865,
589
+ "gzip": 44240
590
},
591
{
592
"filename": "ReactNativeRenderer-dev.js",
593
"bundleType": "RN_OSS_DEV",
594
"packageName": "react-native-renderer",
595
- "size": 645895,
596
- "gzip": 137660
595
+ "size": 720452,
596
+ "gzip": 154169
597
},
598
{
599
"filename": "ReactNativeRenderer-prod.js",
600
"bundleType": "RN_OSS_PROD",
601
"packageName": "react-native-renderer",
602
- "size": 252044,
603
- "gzip": 44061
602
+ "size": 252879,
603
+ "gzip": 44238
604
},
605
{
606
"filename": "ReactFabric-dev.js",
607
"bundleType": "RN_FB_DEV",
608
"packageName": "react-native-renderer",
609
- "size": 634566,
610
- "gzip": 134983
609
+ "size": 709123,
610
+ "gzip": 151511
611
},
612
{
613
"filename": "ReactFabric-prod.js",
614
"bundleType": "RN_FB_PROD",
615
"packageName": "react-native-renderer",
616
- "size": 245276,
617
- "gzip": 42773
616
+ "size": 246002,
617
+ "gzip": 42956
618
},
619
{
620
"filename": "ReactFabric-dev.js",
621
"bundleType": "RN_OSS_DEV",
622
"packageName": "react-native-renderer",
623
- "size": 634470,
624
- "gzip": 134930
623
+ "size": 709027,
624
+ "gzip": 151463
625
},
626
{
627
"filename": "ReactFabric-prod.js",
628
"bundleType": "RN_OSS_PROD",
629
"packageName": "react-native-renderer",
630
- "size": 245282,
631
- "gzip": 42767
630
+ "size": 246008,
631
+ "gzip": 42950
632
},
633
{
634
"filename": "ReactTestRenderer-dev.js",
@@ -725,15 +725,15 @@
725
"filename": "ReactNativeRenderer-profiling.js",
726
"bundleType": "RN_OSS_PROFILING",
727
"packageName": "react-native-renderer",
728
- "size": 258447,
729
- "gzip": 45443
728
+ "size": 259040,
729
+ "gzip": 45588
730
},
731
{
732
"filename": "ReactFabric-profiling.js",
733
"bundleType": "RN_OSS_PROFILING",
734
"packageName": "react-native-renderer",
735
- "size": 250755,
736
- "gzip": 44122
735
+ "size": 251432,
736
+ "gzip": 44320
737
},
738
{
739
"filename": "Scheduler-dev.js",
@@ -774,15 +774,15 @@
774
"filename": "ReactNativeRenderer-profiling.js",
775
"bundleType": "RN_FB_PROFILING",
776
"packageName": "react-native-renderer",
777
- "size": 258428,
778
- "gzip": 45445
777
+ "size": 259021,
778
+ "gzip": 45590
779
},
780
{
781
"filename": "ReactFabric-profiling.js",
782
"bundleType": "RN_FB_PROFILING",
783
"packageName": "react-native-renderer",
784
- "size": 250744,
785
- "gzip": 44126
784
+ "size": 251421,
785
+ "gzip": 44324
786
},
787
{
788
"filename": "react.profiling.min.js",