React Native 0.60.3 babel-plugin-transform-remove-console not working - reactjs

I am trying to remove console.log outputs from my react-native application's output, but when I run
ENVFILE=.env.production react-native run-android --variant=release
and
adb logcat
I still see my app's data being logged to the console.
I used the following documentation: https://facebook.github.io/react-native/docs/performance.html#using-consolelog-statements.
Here is my .babelrc file:
{
"presets": ["react-native"],
"env": {
"production": {
"plugins": ["transform-remove-console"]
}
}
}
What am I missing ?
Im on react-native 0.60.3
and using "babel-plugin-transform-remove-console": "^6.9.4",

I have "#babel/core": "^7.5.5" and "react-native": "^0.60.5"
The approach descibed in React Native Documentation was not working for me.After many try and error and exploring issues on GitHub I got it working :
In babel.config.js add this -
module.exports = api => {
const babelEnv = api.env();
const plugins = [];
//change to 'production' to check if this is working in 'development' mode
if (babelEnv !== 'development') {
plugins.push(['transform-remove-console', {exclude: ['error', 'warn']}]);
}
return {
presets: ['module:metro-react-native-babel-preset'],
plugins,
};
};
To see changes run using npm start -- --reset-cache
More Info at
https://github.com/babel/minify/issues/934
https://github.com/babel/minify/issues/950#issuecomment-539590159

Using babel.config.js instead of .babelrc, it seems that process.env.BABEL_ENV is used to determine whether to include configs listed under env.production. However, process.env.BABEL_ENV is set to undefined during build.
To get around this, I'm returning a different object depending on if process.env.BABEL_ENV OR process.env.NODE_ENV indicate production build.
YMMV.
module.exports = function(api) {
api.cache(true); // necessary
if (process.env.NODE_ENV === 'production' || process.env.BABEL_ENV === 'production') {
return {
"presets": ["module:metro-react-native-babel-preset"],
"plugins": ["react-native-paper/babel", "transform-remove-console"]
}
} else {
return {
"presets": ["module:metro-react-native-babel-preset"],
}
}
}

install babel-plugin-transform-remove-console
yarn add babel-plugin-transform-remove-console -D
then add follow code in babel.config.js like this
module.exports = function (api) {
const babelEnv = api.env();
api.cache(true);
const plugins = [
[];
if (babelEnv === 'production') {
plugins.push(['transform-remove-console', {exclude: ['error', 'warn']}]);
}
return {
presets: ['babel-preset-expo'],
plugins,
};
};
then run this command
yarn start --reset-cache
NOTE:
this will remove console.log in the production build. if you wanna a test in development you can pass development instead of production

Related

How to configure the start script in webpack to use the api I want?

How to configure the start script in webpack to use the api I want?
For example when I run "npm start" my webpack source will use the productuion api like 'https://abc_loginapi.com, and when I run "npm run dev" the webpack source Mine will use local apis like http://localhost:9500/login.
My current way of doing it is quite manual, when I want to run one, I will comment the other one
export const API_HOST_LIST =
{
HostBaseURL: 'https://abc_loginapi.com'
// HostBaseURL: 'http://localhost:9500/login'
}
Is there any way to handle this problem, my source is webpack4 + reactJS
You can use environment variables to handle it, add env to script with --env argument, like this:
webpack --env prod // result { prod: true }
And call it in webpack config file
const path = require('path');
module.exports = env => {
// Use env.<YOUR VARIABLE> here:
console.log('Production: ', env.prod); // true
return {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
};
For more detail, check Webpack docs here
Like Phr0gggg mentions, using environment variables is one option.
Another option is to use the "NODE_ENV" variable.
In dev mode, process.env.NODE_ENV is equal to 'development' and in production, it's equal to 'productoin'
And you can use something like this:
const isProduction = process.env.NODE_ENV === "production"
const hostBaseUrl = () => {
if (isProduction) {
return 'http://localhost:9500';
}
return 'https://abc_loginapi.com';
}
export const API_HOST_LIST =
{
HostBaseURL: hostBaseUrl()
}
You can use process.env api to judge in webpack,
The code in webpack file like.
export const API_HOST_LIST =
{
HostBaseURL: process.env.NODE_ENV ==='dev'? 'http://localhost:9500/login':'https://abc_loginapi.com'
}
The code in package.json file like.
"scripts": {
"dev": "NODE_ENV=dev npm run start",
"start": "npm start"
}

Webpack obfuscator not working with craco, maps disabled

today I have a very large problem using react & craco, I can't seem to get my webpack-obfuscator to do anything. I have disabled source maps, but to no avail.
This is my craco config:
const path = require("path");
const WebpackObfuscator = require('webpack-obfuscator');
module.exports = {
webpack: {
configure: (webpackConfig) => {
// Because CEF has issues with loading source maps properly atm,
// lets use the best we can get in line with `eval-source-map`
if (webpackConfig.mode === 'development' && process.env.IN_GAME_DEV) {
webpackConfig.devtool = 'eval-source-map'
webpackConfig.output.path = path.join(__dirname, 'build')
}
return webpackConfig
},
plugins: {
add: [
new WebpackObfuscator ({
rotateStringArray: true
}),
],
},
},
devServer: (devServerConfig) => {
if (process.env.IN_GAME_DEV) {
// Used for in-game dev mode
devServerConfig.writeToDisk = true
}
return devServerConfig
}
}
I get no visible maps files when building, and I've put "GENERATE_SOURCEMAP=false" in my .env file that's located where the package.json is.
Hopefully someone has the answer as to why this is happening.
Kind regards, and thanks for reading.
To upgrade a short config, you can use a construct that, if the condition is met, updates the configuration without using WebpackObfuscator:
module.exports = {
webpack: {
configure: {
...(process.env.IN_GAME_DEV && process.env.NODE_ENV === 'development' && {devtool: 'eval-source-map'})
}
}
}
Also, if you need additional properties for the configuration, in addition to the dvttool, you can add them

import "!babel-loader!mdx-loader!foo.mdx" not working with react-scripts#5.0.0

Trying to upgrade an existing React project from react-scripts#4 to #5.0.0 fails for importing transpiled MDX sources.
/* eslint import/no-webpack-loader-syntax: off */
import AboutMDX from "!babel-loader!mdx-loader!./About.mdx"
AboutMDX does not receive an MDXComponent but instead now as of react-scripts 5 end up with a string which is the path name of the transpiled javascript source code file. How can I fix this change in behavior to correctly import the MDXComponent?
This has been an od(d)ysee because the whole MDX2+CRA5+remark/rehype ecosystem is prone to breakage in my experience. While MDX documents to use CRACO7 with CRA5, the MDX project when kindly asked points fingers to CRACO and wasn't helpful to me in getting me over ES modules and CSJ hurdles in order to finally get the pieces to work. While the following now works for me (at the moment) I don't know how robust this set up actually is.
upgrade to CRA 5
install CRACO 5
make sure to call the craco command instead of react in your package.json scripts.
make sure to clean up your (stale) dependencies.
add these dependencies and dev dependencies:
"#mdx-js/loader": "^2.2.1",
"#mdx-js/mdx": "^2.2.1",
"#mdx-js/react": "^2.2.1",
"#types/mdx": "^2.0.3",
"#craco/craco": "^7.0.0",
"#craco/types": "^7.0.0",
if in the past you had a declare module '*.mdx {...}' in a src/index.d.ts then remove this now completely, as it would conflict with what comes with the MDXv2 loader.
remove !babel-loader!mdx-loader! from all your *.mdx imports. Do not use !#mdx-js/loader! etc. either, as the webpack configuration below will take care of the preprocessing.
create a craco.config.js as follows; this is a more elaborate configuration that shows how to actually pull in ES modules with CRACO 5 still not supporting ESM in their configuration, but requiring to go through the dynamic import with delayed configuration setup hurdles:
const { addAfterLoader, loaderByName } = require('#craco/craco')
module.exports = async (env) => {
const remarkGfm = (await import('remark-gfm')).default
const remarkImages = (await import('remark-images')).default
const remarkTextr = (await import('remark-textr')).default
const rehypeSlug = (await import('rehype-slug')).default
const textrTypoApos = (await import('typographic-apostrophes')).default
const textrTypoQuotes = (await import('typographic-quotes')).default
const textrTypoPossPluralsApos = (await import('typographic-apostrophes-for-possessive-plurals')).default
const textrTypoEllipses = (await import('typographic-ellipses')).default
const textrTypoEmDashes = (await import('typographic-em-dashes')).default
const textrTypoEnDashes = (await import('typographic-en-dashes')).default
return {
webpack: {
configure: (webpackConfig) => {
addAfterLoader(webpackConfig, loaderByName('babel-loader'), {
test: /\.(md|mdx)$/,
loader: require.resolve('#mdx-js/loader'),
/** #type {import('#mdx-js/loader').Options} */
options: {
remarkPlugins: [
remarkGfm,
remarkImages,
[remarkTextr, {
plugins: [
textrTypoApos,
textrTypoQuotes,
textrTypoPossPluralsApos,
textrTypoEllipses,
// textrTypoEmDashes,
textrTypoEnDashes,
],
options: {
locale: 'en-us'
}
}],
],
rehypePlugins: [
rehypeSlug,
],
}
})
return webpackConfig
}
}
}
}

Setting up babel-plugin-styled-components + Typescript + create-react-app

We are currently trying to integrate the babel-plugin-styled-components into our typescript and create-react-app based setup for a better debugging experience and we are having difficulties doing so.
We are reluctant to eject the app, which is why we are trying to set it up using react-app-rewired and we also managed to get our typescript code to compile using react-app-rewire-typescript along with react-app-rewire-styled-components.
For some reason however, the displayName is not applied, which makes me think the babel plugin is not applied.
We are using "start": "react-app-rewired start" as our dev server script and the config-overrides.js looks like this:
const rewireTypescript = require('react-app-rewire-typescript');
const rewireStyledComponents = require('react-app-rewire-styled-components');
module.exports = function override(config, env) {
return rewireTypescript(rewireStyledComponents(config, env), env);
}
I have no idea what we are missing. Swapping the encapsulation of the rewire... functions also didn't help.
Does anyone here have experience with that or can point me in the right direction?
If you are using webpack, I found a solution that did not require using babel.
https://github.com/Igorbek/typescript-plugin-styled-components
To use it, you add a custom transform to your typescript loader with webpack:
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader',
options: {
getCustomTransformers: () => ({ before: [styledComponentsTransformer] })
}
}
This solves the displayName not showing when using styled-components and typescript.
I solved the issue by add something like this in config-overrides.js using react-app-rewired:
const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
const styledComponentsTransformer = createStyledComponentsTransformer();
module.exports = function override(config, env) {
const rule = config.module.rules.filter(l => l.oneOf)[0];
const tsLoader = rule.oneOf.filter(l => String(l.test) === String(/\.(ts|tsx)$/))[0];
tsLoader.use[0].options.getCustomTransformers = () => ({
before: [styledComponentsTransformer]
});
return config;
}

Evaluate conditionals at compile time in babel / webpack

I have a config file where I have a variable that can have the value X or Y depending if it's prod or dev.
I want to evaluate it at compile time.
I was able to get the NODE_ENV value from babel-plugin-transform-node-env-inline but can't figure out how to evaluate the expression. I tried babel-plugin-transform-conditionals but it throws strange code errors. Errors that don't exist.
I can evaluate at runtime since in that case both prod and dev values will be available in app.js, which I can't have.
No idea where to go from here!!
Any totally different solution would work too (like somehow compile a different file), but not sure how to go about it.
Not sure about your question, you can just write the if statement like this
if (process.env.NODE_ENV === 'development') {
// ...
}
It will be transform to
// or true
if (false) {
// ...
}
if it is false, then that's a kind of unreachable code, which will be stripped by UglifyJs plugin automatically (use new webpack.optimize.UglifyJsPlugin() in your webpack config)
also don't forget to use DefinePlugin (and cross-env if you are using windows) to declare the process.env.NODE_ENV variable or it may not work
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
I have never use the plugin you mention. But default webpack setup should work like what I have done in the following:
webpack.config.js
var config = {
entry: {
...
},
output: {
...
},
module: {
...
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
}
}),
// some other plugins
]
};
So the NODE_ENV is coming from your environment when you run webpack.
package.json
{
"scripts": {
"start": "NODE_ENV=development webpack-dev-server --progress --hot --inline --colors --host 0.0.0.0 --port 9999",
"production": "NODE_ENV=production webpack",
}
}
In your package.json run the webpack in environment you specify.
Your config.js
export default {
isDebug: process.env.NODE_ENV === "development",
logLevel: process.env.NODE_ENV === "development" ? "error" : "info"
};
Another example I use in my application for redux. I only wanted to have redux-logger during development.
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import logger from "redux-logger";
import promise from "redux-promise-middleware";
import reducer from "./reducers";
const middleware = process.env.NODE_ENV === "production" ? [promise(), thunk] : [promise(), thunk, logger()];
export default createStore(
reducer,
applyMiddleware(...middleware)
);
After the compile if you look at the generated code from the above redux example.
var middleware = true ? [(0, _reduxPromiseMiddleware2.default)(), _reduxThunk2.default] : [(0, _reduxPromiseMiddleware2.default)(), _reduxThunk2.default, (0, _reduxLogger2.default)()];
process.env.NODE_ENV === "production" have been evaluate to true.
Make one Webpack config for development, and one config for production, which you need anyway. Specify your variable in each config using the DefinePlugin, then you can reference that global variable anywhere in your bundle.

Resources