react-native: babel-plugin-transform-remove-console doesn't work with RN

Issue Description

I tried using babel-plugin-transform-remove-console as specified in the performance docs in my RN project (v0.34.1) and also in a newly initialized AwesomeProject (v0.35.0), but it looks like the RN packager (or JavaScriptCore?) doesn’t like the transformed code. Both throw the same error when running assembleRelease with gradle:

:app:bundleReleaseJsAndAssets
[2016-10-14 14:51:37] <START> Building Dependency Graph
[2016-10-14 14:51:37] <START> Crawling File System
[2016-10-14 14:51:37] <START> Finding dependencies
[2016-10-14 14:51:41] <END>   Crawling File System (3999ms)
[2016-10-14 14:51:41] <START> Building in-memory fs for JavaScript
[2016-10-14 14:51:41] <END>   Building in-memory fs for JavaScript (218ms)
[2016-10-14 14:51:41] <START> Building in-memory fs for Assets
[2016-10-14 14:51:41] <END>   Building in-memory fs for Assets (165ms)
[2016-10-14 14:51:41] <START> Building Haste Map
[2016-10-14 14:51:41] <START> Building (deprecated) Asset Map
[2016-10-14 14:51:41] <END>   Building (deprecated) Asset Map (59ms)
[2016-10-14 14:51:42] <END>   Building Haste Map (298ms)
[2016-10-14 14:51:42] <END>   Building Dependency Graph (4691ms)

TransformError: /Users/foo/AwesomeProject/node_modules/react-native/Libraries/JavaScriptAppEngine/Initialization/ExceptionsManager.js: /Users/foo/AwesomeProject/node_modules/react-native/Libraries/JavaScriptAppEngine/Initialization/ExceptionsManager.js: Property right of AssignmentExpression expected node to be of a type ["Expression"] but instead got null

:app:bundleReleaseJsAndAssets FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:bundleReleaseJsAndAssets'.
> Process 'command 'node'' finished with non-zero exit value 1

I also tested it on another project for the web, which is bundled with webpack and works as expected, so I didn’t open an issue at the babel repo yet because it might be RN related.

Note: In #8337, there was effort to integrate this functionality directly into RN, but adding the transform plugin guide into the docs was chosen instead.

Steps to Reproduce / Code Snippets

  1. Configure .babelrc according to the perf docs
  2. Add a console.log('blah') somewhere into one of the root index files

Expected Results

Transformed code without console.* calls.

Additional Information

  • React Native version: 0.35.0
  • Platform(s) (iOS, Android, or both?): Android
    • haven’t tested iOS, but suspect it’s not a platform issue
  • Operating System (macOS, Linux, or Windows?): macOS

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 22
  • Comments: 29 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Tnx ! i did this.

if(!__DEV__) {
    console = {};
    console.log = () => {};
    console.error = () => {};
}

The original plugin code is probably too broad in detecting what nodes to remove. If in addition to the object.name (which is ‘console’) we also check for the property.name (which may be ‘log’, ‘error’, warn’, etc.) then the problem reported is resolved. Below is the code that removes all console.log statements (but not console.warn, console.error, etc), which was sufficient for my purposes. You can further modify the code if you need to remove all kind of console statements.

/*istanbul ignore next*/"use strict";

exports.__esModule = true;

exports.default = function () {
  return {
    visitor: { /*istanbul ignore next*/
      CallExpression: function CallExpression(path) {
        var c = path.get("callee");
        if (c.matchesPattern("console", true)) {
          var prop = c.node.property;
          if (prop && prop.name === 'log') {        
            path.remove();
          }
        }
      }
    }
  };
};

/*istanbul ignore next*/module.exports = exports["default"];

@note89 As a workaround I would just write a log function that only writes to console.log when it’s in development mode and use the custom log function.

I do have the same problem when bundling an iOS app.

@jhen0409 Thanks I hope this functionality gets brought into RN, they really should considering this as an optimization step for final binary generation.

@oximer

Do you got an “unexpected keyword import” error? Try this:

{
  "presets": ["react-native"],
  "env": {
    "production": {
      "plugins": ["transform-remove-console"]
    }
  }
}

Just let everyone know it has been fixed by https://github.com/babel/babili/pull/421, the main problem is ExceptionsManager.js#L103-L104, we can waiting for new release of transform-remove-console.

OK so in conclusion this plugin either does not work on React Native or at least there is no real guarantee that this plugin will continue to work. I think the best thing to do here is to just remove the advice that people use this plugin - it’s sort of out of scope for React Native itself. I have a PR up to fix the docs at https://github.com/facebook/react-native/pull/12315 so I am going to close this issue. Thanks everyone for pointing this problem out and offering workarounds!

thank you for sharing that code @mp31415 if you don’t mind, could you please share the raw code (before it being transformed)? would like to put it in as part of production build task.

thank you in advance.

I’d like to note that it worked the expected way on both:

  1. development mode (no ./gradlew assembleRelease) ✅
  2. compiling without any babel configuration (no .babelrc) ✅

By the moment I am using @note89 solution, but I guess it is not the ideal.

Also to try with different .babelrc configurations I am running the packager with --reset-cache args. I was not perceiving any changes and I guess this tip can be useful to many arriving to this threat or related ones.

I bet this is related to https://github.com/facebook/react-native/commit/3137ba993dbc3645832283ab683d18950c4246ed (submitted by @javache , reviewed by @davidaurelio ) because that has some odd “declare var console: typeof console &” stuff going on in it. IMO if we’re going to support this transform we need some sort of test that ensures it actually works - otherwise I don’t see how to avoid breaking the functionality in the future. Actually since the code works this might be a bug with the babel transform itself. Could you try just running this babel transform on the ExceptionsManager file independently and see what’s going wrong?