JSX not transpiling with Gulp and Babel - reactjs

I have a Gulp script with which I am trying to launch a React application.
The Gulp file is named gulpfile.babel.js
I am adding the Babel preset 'env' as an option
There is also a .babelrc file in the same directory with the same preset option
The Gulp file includes:
const gulp = require('gulp');
const browserSync = require('browser-sync').create();
const babel = require('gulp-babel');
// convert jsx to JS
gulp.task('babelFiles', function() {
return gulp.src('js/*.#(js|jsx)')
.pipe(babel({
compact: false,
presets: ['env'],
}))
.pipe(gulp.dest('js'))
.pipe(browserSync.reload({
stream: true
}));
});
// Default task
gulp.task('default', ['babelFiles', 'browserSync']);
// Configure the browserSync task
gulp.task('browserSync', ['babelFiles'], function() {
browserSync.init({
server: {
baseDir: ''
},
})
})
When the Gulp task launches I see an error about an unexpected token:
29 | return (
> 30 | <div>
| ^
This tells me something is wrong with the JSX transpilation in the react setup? Would you happen to know what the problem could be here?

babel-preset-env does not include a preset to transpile your JSX to plain JavaScript. For that you'll need babel-preset-react:
npm i --save-dev babel-preset-react
Then apply it:
presets: ['env', 'react']
babel-preset-env determines which plugins you'll need for your JavaScript, such as plugins for ES2015, 2016, and 2017. It does no, however, account for things such as JSX.

Related

How can I use absolute paths in my React styleguidist component library?

I have a React component library that is used in a React app. The component library is setup using Styleguidist and webpack. I've setup webpack to use absolute paths using:
webpackConfig: {
resolve: {
modules: [path.resolve(__dirname, 'src/'), 'node_modules'],
}
}
This works within the context of the component library. When I build the component library, the package looks like this:
/core
/components
/Table
/Row
When I import the components into my app, I get an error:
Module not found: Can't resolve components/Row in /Users/myusername/Sites/mysite/node_modules/#mypackage/core/components/Table
I understand why the paths don't match in the context of node_modules, but I would've expected Webpack to transform those import paths during the build process. Is there something I'm missing? Or is this not possible?
While Styleguidist uses webpack, it turns out the build script we were using does not, so the webpack config is irrelevant. Instead, our build script (https://www.npmjs.com/package/cod-scripts) uses babel.
We ended up having to add a separate babel.config.js file to define absolute paths for babel using the babel-plugin-module-resolver package.
npm install babel-plugin-module-resolver --saveDev
npm install #babel/preset-react --saveDev
babel.config.js
module.exports = {
plugins: [
[
'module-resolver',
{
root: ['./src'],
},
],
],
presets: ['#babel/preset-react'],
};

Jest framework throwing error as "unexpected identifier" for Jquery import

When I try to import Jquery like
import $ from 'jquery';
inside test file
or like
import $ from 'jquery'; global.$ = global.jQuery = $;
inside the Jest setup file, I get error as
● Runtime Error- SyntaxError: Unexpected identifier
at new Function (<anonymous>)
at createMockFunction (node_modules/jest-mock/build/index.js:179:10)
at Array.forEach (<anonymous>)
at Array.forEach (<anonymous>)
How to fix this issue? Checked the path and node_modules for Jquery both are fine. using Jest version "^14.1.0".
I have a newer version of Jest (v24.7.0), so I'm not sure this answer works with the Jest version used in the question.
From a note on Jest documentation:
Note: babel-jest is automatically installed when installing Jest and will automatically transform files if a babel configuration exists in your project.
I found the solution on the Jest documentation itself:
Install these dependencies: npm install --save-dev babel-jest #babel/core #babel/preset-env
Add a configuration file for Babel similar to this one in your project's root directory:
// babel.config.js
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};
Try using #babel/preset-env. Here's an example .babelrc:
{
"env": {
"test": {
"presets": [["#babel/preset-env"]]
}
}
}
You can add additional configuration options, of course; the important part is that #babel/preset-env is set as a preset in your env.test object.

Building Typescript for Angular using Gulp

I'm trying to setup an angularjs project according to Johnpapa's Angular Style Guide whilst using TypeScript and Gulp as a build tool. I believe Gulp is currently recommended over Grunt but I'm not very experienced with Gulp.
What I have:
My project currently looks like this:
src/
+- ts/ # contains .ts source files
+- typings/ # contains .d.ts typing definitions
+- html/ # contains .html files
dist/
+- bundle.js # single .js file containing compiled typescript and sourcemaps
Following the angular style guide I have created a separate .ts file for each angular element.
my-app.module.ts
----------------
angular.module('myApp', []);
for initialization of the module and another for a simple implementation of a controller:
my-controller.controller.ts
----------------------------
export class MyController {
testString = 'test';
}
angular
.module('myApp')
.controller('MyController', MyController);
typescript is configured using a simple tsconfig.json. (Note that filesGlob is not active yet - it will become available from TypeScript 2.0)
tsconfig.json
-------------
{
"exclude" : [
"node_modules"
],
"filesGlob" : [
"./src/typings/index.d.ts",
"./src/ts/**/*.ts",
"!./node_modules/**/*.ts"
],
"compilerOptions": {
"noImplicitAny": true,
"target": "es5",
"sourceMap" : true,
"outFile" : "./dist/bundle.js",
"removeComments": false
}
}
What I want:
I would ideally like to
Have Gulp monitor new or updated .ts files in ./src/ts/**/*.ts
Concatenate all the files from ./src/ts/**/*.ts. This is required for angular to work properly. Other methods I've tried using requirejs or browserify can't find the other .ts files without having to manually input references to these files.
Compile using the definitions from tsconfig.json. This would take into consideration the typings in ./src/typings/index.d.ts (for external modules including 'angular'). Also sourcemaps.
Possibly an uglify or babelify step to finish it.
What I tried:
I've tried following the manual from the typescriptlang handbook but this uses browserify and won't work with angular.
Gulp-typescript also has a note on concatenating files but the out option doesn't work like this:
var gulp = require('gulp');
var ts = require('gulp-typescript');
var tsProject = ts.createProject('tsconfig.json');
gulp.task('default', function () {
var tsResult = tsProject.src().pipe(ts(tsProject));
return tsResult.js.pipe(gulp.dest('dist'));
});
This configuration will output an empty file with only comments.
Another method mentioned in this question:
gulp.task('ts', function () {
gulp.src('./src/ts/**/*.ts')
.pipe(ts({
noImplicitAny: true,
out: 'output.js'
}))
.pipe(gulp.dest('./tmp/ts'));
});
gulp.task('default', ['ts'], function() {
gulp.src(['./tmp/ts/output.js'])
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write('/'))
.pipe(gulp.dest('./dist/'));
});
But this gave two issues: 1. Even though I only pointed at the .ts files in ./src/ts the typescript compiler started spewing errors from .ts in ./node_modules. 2. It still didn't manage to concatenate everything.
I'm at quite a loss here. Can anyone help me set up this build script? I'm surprised I couldn't find a similar working demo anywhere.
Solution:
I've configured the gulp environment based on the solution in this answer and removed the 'export' statement for classes / objects that are not inside a typescript module.
If that helps, here is a Angular Typescript Gulp Tutorial that has a basic TypeScript, Angular, Gulp, etc. setup that concatenate the app and the vendor/nodes files. There is the demo code on github.
/* File: gulpfile.js */
// grab our gulp packages
var gulp = require('gulp');
// Include plugins
var plugins = require("gulp-load-plugins")({
pattern: ['gulp-*', 'gulp.*', 'main-bower-files', 'del'],
replaceString: /\bgulp[\-.]/
});
var browserSync = require('browser-sync').create();
var reload = browserSync.reload;
// create a default task to build the app
gulp.task('default', ['jade', 'typescript', 'bowerjs', 'bowercss', 'appcss'], function() {
return plugins.util.log('App is built!')
});
In my example, we use Jade to HTML:
// Jade to HTML
gulp.task('jade', function() {
return gulp.src('src/**/*.jade')
.pipe(plugins.jade()) // pip to jade plugin
.pipe(gulp.dest('dist')) // tell gulp our output folder
.pipe(reload({stream: true}))
;
});
For TypeScript, we compiled into one single app.js file:
// TYPESCRIPT to JavaScript
gulp.task('typescript', function () {
return gulp.src('src/**/*.ts')
.pipe(plugins.typescript({
noImplicitAny: true,
out: 'app.js'
}))
.pipe(gulp.dest('dist/js/'))
.pipe(reload({stream: true}))
;
});
For bower, we merge all the js files in vendor.js and CSS in vendor.css:
// BOWER
gulp.task('bowerjs', function() {
gulp.src(plugins.mainBowerFiles())
.pipe(plugins.filter('**/*.js'))
.pipe(plugins.debug())
.pipe(plugins.concat('vendor.js'))
.pipe(plugins.uglify())
.pipe(gulp.dest('dist/js'));
});
gulp.task('bowercss', function() {
gulp.src(plugins.mainBowerFiles())
.pipe(plugins.filter('**/*.css'))
.pipe(plugins.debug())
.pipe(plugins.concat('vendor.css'))
.pipe(gulp.dest('dist/css'));
});
Custom CSS:
// APP css
gulp.task('appcss', function () {
return gulp.src('src/css/**/*.css')
.pipe(gulp.dest('dist/css/'))
.pipe(reload({
stream: true
}));
});
// CLEAN
gulp.task('clean', function(done) {
var delconfig = [].concat(
'dist',
'.tmp/js'
);
// force: clean files outside current directory
plugins.del(delconfig, {
force: true
}, done);
});
This is what reloads the browser when changes occur:
// Watch scss AND html files, doing different things with each.
gulp.task('serve', ['default'], function () {
// Serve files from the root of this project
browserSync.init({
server: {
baseDir: "./dist/"
}
});
gulp.watch("src/**/*.jade", ['jade']).on("change", reload);
gulp.watch("src/**/*.ts", ['typescript']).on("change", reload);
gulp.watch("src/**/*.css", ['appcss']).on("change", reload);
});
My tsconfig.json looks like this... I put the JS files that are automatically compiled from the text editor (Atom) into .tmp/js/atom ... some people put the .js in the same directory as the .ts but I find it confusing... less files is better for me:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"outDir": ".tmp/js/atom"
},
"exclude": [
"node_modules",
"typings"
]
}

Gulp, Reactify, and Babelify not transforming together

This is my gulpfile code:
gulp.task('react', function () {
browserify('app/src/main.jsx')
.transform(reactify)
.transform(babelify)
.bundle()
.pipe(source('app.js'))
.pipe(streamify(uglify()))
.pipe(gulp.dest('dist/js/'));
});
Only the first transform statement runs, and therefor throws an error due to the lack of additional transform (I'm writing in ES6 and JSX w/ react).
I'm at a complete loss and would really appreciate help.
Reactify should no longer be used. You don't say what version you are on, but as of Babel 6 "preset's" are the standard way to achieve compilation.
Run the following
npm install save-dev babel-preset-react babel-preset-es2015
You should also make sure Babelify is up to date. Then your Gulp config becomes
var babelify = require("babelify");
gulp.task('react', function () {
browserify('app/src/main.jsx')
.transform(babelify, {presets: ["es2015", "react"]})
.bundle()
.pipe(source('app.js'))
.pipe(streamify(uglify()))
.pipe(gulp.dest('dist/js/'));
});
See the options page for more information.

Browserify recipe for AngularJS + source maps + minification

I am looking for a working recipe that can minify my AngularJS code and still provide a source map. Currently I have this gulp task but minification won't work:
gulp.task('browserify', function(cb) {
var bundler = browserify({
entries: [paths.browserEntry],
globals: false,
debug: !settings.PRODUCTION
})
bundler
.bundle()
.on('error', cb)
.on('log', util.log)
.pipe(gulpif(!settings.PRODUCTION, mold.transformSourcesRelativeTo(paths.js)))
.pipe(source(paths.js))
.pipe(buffer()) // because the next steps do not support streams
.pipe(concat('bundle.js'))
.pipe(gulpif(settings.server.minify.js, rename({suffix: '.min'})))
.pipe(gulpif(settings.server.minify.js, uglify()))
.pipe(gulp.dest(paths.js))
.on('end', function() {
cb()
})
})
Any clues?
You may see an example here. The example will output a minified bundle.min.js plus a bundle.map. The crucial points which makes the example works:
Installed debowerify
Installed minifyify
package.json - added transform property
"browserify": {
"transform": [
"debowerify"
]
}
Gruntfile.js - using preBundleCB to make minifyify work
preBundleCB: function (b) {
b.plugin( minifyify,
{ output: './dist/bundle.map',
map:'bundle.map'
});
}
Hope the example is useful to you.

Resources