How to transpile React ES6 classes using Grunt + Browserify + Reactify? - javascript

I want to use the new ES6 React classes that was introduced with React v0.13, but I am unable to get it to compile correctly. Say I have the following React component defined in the new class syntax:
(function() {
'use strict';
import React from 'react';
class _UserDashboard extends React.Component {
render() {
return(
<div className="user-dashboard">
<Books />
</div>
);
}
}
export const UserDashboard = React.createClass(_UserDashboard.prototype);
}());
The trouble I run into here is that at compile time using Grunt and Browserify and a Reactify transform, Reactify throws an error when it encounters the import keyword:
ReactifyError: /Users/****/Sites/***/assets/js/components/UserDashboard.jsx: Parse Error: Line 7: Unexpected reserved word while parsing file: /Users/****/Sites/****/assets/js/components/UserDashboard.jsx
The problem here seems to have to do with Reactify's use of react-tools, see here and here. But I'm not sure if it is possible to enable the es6module option within Reactify yet.
I tried these two variations to no avail:
...
transform: [[ 'reactify', {'es6module': true} ]]
...
and
...
transform: [[ 'reactify', {'es6':true, 'es6module':true} ]]
...
Does anyone know how this can be done?

You should be able to do all of this with Babel and babelify (the corresponding Browserify plugin).
Babel itself is an ES6+ to ES5 transpiler, but it comes with first class JSX support:
JSX and React
Babel works perfectly with React, featuring a built-in JSX transformer.
Your Browserify transform would become:
{
"browserify": {
"transform": ["babelify"]
}
}
Edit: As of Babel 6, many components have been moved out into a separate presets packages which you'll need to install and include in the transform command.
For React and JSX, you'll need babel-preset-react.
For ES6, you'll need babel-preset-es2015
Together these can be specified in the transform.
transform: [[babelify, { presets: ["react", "es2015"] }]]

Babelify is a best option for my point of view. Small clarification to #Dan's answer. For the babel v 6.0 you will need to install 2 preset.
ES2015
React
with something similar to npm install --save-dev babel-preset-react and npm install --save-dev babel-preset-es2015 commands and then specify this in babelify settings with: transform: [[babelify, {presets: ["es2015", "react"]}]]
And if in your code you use some newest react features like ...other for example, you also need add stage-0 preset.

Related

How can i see all my deprecated methods functions in react native?

How can i see all my deprecated methods functions in react native? i have a old react native project and its not working fine errors are coming one by one so i updated all of my packages which were outdated but after that many errors are coming too while running the project
i tired to fix some but now i get to know that my projects and many deprecated functions and it become very hard to solve one by one i do have many files in one project, So is their any easy way so see all deprecated functions methods variables etc. i do run npm outdated to see deprecated npm packages but it was not a solution..
i dont want my code updated i just want to search or see that what functions and methods are deprecated
eslint-plugin-deprecation lets deprecated functions and more be shown.
Install it with npm i -D eslint-plugin-deprecation. If not already installed, install just enough Typescript to run make this ESLint plugin work but not so much to force the whole project to use it: npm i -D typescript#4.0 #types/jest #types/react #types/react-native #types/react-test-renderer #tsconfig/react-native. This is a subset of the official guide.
Create tsconfig.json if it doesn't exist:
{
"extends": "#tsconfig/react-native/tsconfig.json"
}
Replace or add to .eslintrc.js:
module.exports = {
root: true,
extends: '#react-native-community',
"parser": "#typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["deprecation"],
"rules": {
"deprecation/deprecation": "warn",
},
};
Create .eslintignore:
.eslintrc.js
As an example, add and use a deprecated function in a newly created project's App.js:
// ...
import {
Colors,
DebugInstructions,
Header,
LearnMoreLinks,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
/**
* #deprecated
*/
function dontUseThis() {}
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
const Section = ({children, title}): Node => {
dontUseThis(); // Newly added line 37 as an example of a deprecated function
const isDarkMode = useColorScheme() === 'dark';
return (
// ...
Then deprecated functions will be shown when npm run lint is used:
$ npm run lint
> AwesomeProject#0.0.1 lint
> eslint .
/run/user/1000/AwesomeProject/App.js
10:14 warning 'Node' is defined but never used no-unused-vars
37:3 warning 'dontUseThis' is deprecated. deprecation/deprecation
✖ 2 problems (0 errors, 2 warnings)

npx babel not reading configuration from babel.config.js

When running npx babel index.js from the command line, I was hoping I would see my babel configurations being applied from babel.config.js
However it does not seem the case as was wondering why this might be?
// babel.config.js
module.exports = function babel(api) {
api.cache(true);
return {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'babel-plugin-root-import',
{
rootPathSuffix: './src',
rootPathPrefix: '~/',
},
],
],
};
};
// index.js
import { AppRegistry } from 'react-native';
import App from '~/App';
AppRegistry.registerComponent("App Name", () => App)
// Expected output from npx babel index.js
import { AppRegistry } from 'react-native';
import App from './src/App'; // Note the change from '~' to './src' using babel-plugin-root-import
AppRegistry.registerComponent("App Name", () => App)
I noticed in the npx babel --help it stated that --no-babelrc flag ignores configuration from .babelrc and .babelignore files. Does this suggest that babel.config.js files aren't considered when calling this command?
Cheers
babel.config.js config change is introduced in babel 7; so if you are using babel 6.*, it doesn't understand project wide configuration yet; either use .babelrc or upgrade to babel 7 to be able to use new features; I'd did the upgrade its pretty smooth and painless, just make sure you have clean git directory ( in case of emergency :) and do it.

Can I use Babel to transpile to ES5 but keep import/export instead of commonjs?

I want to create an npm library that delivers modules using ES import/export instead of commonjs (like for example lodash-es does). If I'm not mistaken, the delivered code must be ES5 and has import/export.
I can't figure out how to configure Babel to do that. I expect that the option targets.esmodules should do the trick.
When I have the following code in calc.js:
// calc.js
export function add (a, b) {
const result = a + b
return result
}
and babel configuration .babelrc:
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"esmodules": true
}
}
]
]
}
When running babel:
babel calc.js
The output is:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.add = add;
function add(a, b) {
var result = a + b;
return result;
}
Which is commonjs (exports.add). The option targets.esmodules seems to have no effect. How can I get Babel to generate an es module (export function add)? Or am I misunderstanding the idea of delivering ES modules on npm?
It looks like based on the Rollup docs that you should indeed transpile a version that has only import/export, but has transpiled out all of the other non-ES5 syntax. The Webpack docs say something similar. This format assumes that your users are using tools like Rollup or Webpack, which natively support import/export statements, but then presumably transpile them to an ES5 compatible syntax without needing to run your library through Babel.
And it looks like Redux in particular pulls this off by using the Rollup format option and then in their .babelrc file they use the "modules": false option to tell Babel not to transpile module statements. It's not clear to me how Lodash manages it, since looking over their source code I don't see any build scripts anywhere in the repo.

JavaScript export / import doesn't work

it might be a silly question but I can't fix it anyway. I have a JavaScript file with various functions I'd like to export.
export function AddNumbers(...numbers)
{
let value = 0;
for(var i = 0;i < numbers.length;i++)
{
value += numbers[i];
}
return value;
}
When I call this method (using mocha) I get an error message "export function AddNumbers(...numbers) Unexpected token export". The project is build as ES6. Does anybody know what I'm doing wrong?
Best regards,
Torsten
You need to use module.exports as NodeJS uses CommonJS Module syntax which requires to use module.exports and not just export which is defined by ES6 module syntax. So, make sure CommonJS is also configured properly in your project.
Another solution is to use Babel. Install it with
npm install babel-core --save-dev
npm install babel-preset-es2015 --save-dev
Create in root directory a file .babelrc with following content
{
"preset" : ["es2015"]
}
and finally change the script in package.json to run into:
"scripts": {
"test": "mocha Tests --require babel-core/register"
}
and now export / import works.

How to remove global "use strict" added by babel

I'm using function form of "use strict" and don't want global form which Babel adds after transpilation. The problem is I'm using some libraries that aren't using "use strict" mode and it might throw error after scripts are concatenated
As it has already been mentioned for Babel 6, it's the transform-es2015-modules-commonjs preset which adds strict mode.
In case you want to use the whole es2015 preset without module transformations, put this in your .babelrc file:
{
"presets": [
["es2015", { "modules": false }]
]
}
This will disable modules and strict mode, while keeping all other es2015 transformations enabled.
Babel 5
You'd blacklist "useStrict". For instance here's an example in a Gruntfile:
babel: {
options: {
blacklist: ["useStrict"],
// ...
},
// ...
}
Babel 6
Since Babel 6 is fully opt-in for plugins now, instead of blacklisting useStrict, you just don't include the strict-mode plugin. If you're using a preset that includes it, I think you'll have to create your own that includes all the others, but not that one.
There's now a babel plugin that you can add to your config that will remove strict mode: babel-plugin-transform-remove-strict-mode. It's a little ugly in that the "use strict" gets added and then removed, but it makes the config much nicer.
Docs are in the GitHub repo:
https://github.com/genify/babel-plugin-transform-remove-strict-mode
Your .babelrc ends up looking like this:
{
"presets": ["env"],
"plugins": ["transform-remove-strict-mode"]
}
I also came accross this rather ridiculous limitation that you cannot disable or overwrite settings from an existing preset, and have resorted to using this preset instead: https://www.npmjs.com/package/babel-preset-es2015-without-strict
plugins: [
[
require("#babel/plugin-transform-modules-commonjs"),
{
strictMode: false
}
],
]
You can tell babel that your code is a script with:
sourceType: "script"
in your babel config file. This will not add use strict. See sourceType option docs
Source: https://github.com/babel/babel/issues/7910#issuecomment-388517631
Babel 6 + es2015
We can disabled babel-plugin-transform-es2015-modules-commonjs to require babel-plugin-transform-strict-mode.
So comment the following code in node_modules/babel-plugin-transform-es2015-modules-commonjs/lib/index.js at 151 line
//inherits: require("babel-plugin-transform-strict-mode"),
just change .babelrc solution
if you don't want to change any npm modules, you can use .babelrc ignore like this
{
"presets": ["es2015"],
"ignore": [
"./src/js/directive/datePicker.js"
]
}
ignore that file, it works for me!
the ignored file that can't use 'use strict' is old code, and do not need to use babel to transform it!
Personally, I use the gulp-iife plugin and I wrap IIFEs around all my files. I noticed that the babel plugin (using preset es2015) adds a global "use strict" as well. I run my post babel code through the iife stream plugin again so it nullifies what babel did.
gulp.task("build-js-source-dev", function () {
return gulp.src(jsSourceGlob)
.pipe(iife())
.pipe(plumber())
.pipe(babel({ presets: ["es2015"] }))// compile ES6 to ES5
.pipe(plumber.stop())
.pipe(iife()) // because babel preset "es2015" adds a global "use strict"; which we dont want
.pipe(concat(jsDistFile)) // concat to single file
.pipe(gulp.dest("public_dist"))
});
This is not grammatically correct, but will basically work for both Babel 5 and 6 without having to install a module that removes another module.
code.replace(/^"use strict";$/, '')
Since babel 6 you can install firstly babel-cli (if you want to use Babel from the CLI ) or babel-core (to use the Node API). This package does not include modules.
npm install --global babel-cli
# or
npm install --save-dev babel-core
Then install modules that you need. So do not install module for 'strict mode' in your case.
npm install --save-dev babel-plugin-transform-es2015-arrow-functions
And add installed modules in .babelrc file like this:
{
"plugins": ["transform-es2015-arrow-functions"]
}
See details here: https://babeljs.io/blog/2015/10/31/setting-up-babel-6
For babel 6 instead of monkey patching the preset and/or forking it and publishing it, you can also just wrap the original plugin and set the strict option to false.
Something along those lines should do the trick:
const es2015preset = require('babel-preset-es2015');
const commonjsPlugin = require('babel-plugin-transform-es2015-modules-commonjs');
es2015preset.plugins.forEach(function(plugin) {
if (plugin.length && plugin[0] === commonjsPlugin) {
plugin[1].strict = false;
}
});
module.exports = es2015preset;
Please use "es2015-without-strict" instead of "es2015". Don't forget you need to have package "babel-preset-es2015-without-strict" installed. I know it's not expected default behavior of Babel, please take into account the project is not mature yet.
I just made a script that runs in the Node and removes "use strict"; in the selected file.
file: script.js:
let fs = require('fs');
let file = 'custom/path/index.js';
let data = fs.readFileSync(file, 'utf8');
let regex = new RegExp('"use\\s+strict";');
if (data.match(regex)){
let data2 = data.replace(regex, '');
fs.writeFileSync(file, data2);
console.log('use strict mode removed ...');
}
else {
console.log('use strict mode is missing .');
}
node ./script.js
if you are using https://babeljs.io/repl (v7.8.6 as of this writing), you can remove "use strict"; by selecting Source Type -> Module.
Using plugins or disabling modules and strict mode as suggested in the #rcode's answer didn't work for me.
But, changing the target from es2015|es6 to es5 in tsconfig.json file as suggested by #andrefarzart in this GitHub answer fixed the issue.
// tsconfig.json file
{
// ...
"compilerOptions": {
// ...
"target": "es5", // instead of "es2015"
}

Categories