I'm trying to learn about gulp, browserify and react and have been knocking up a little test project. This was fine until I decided to implement some animations in there. Specifically this:
var React = require("react");
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
I'm getting an error because "React.addons" is null.
I also have the issue that my build is taking an age - between 20 secs and a minute. I think the reason is partly because react itself is being included in my bundle, whereas I would ideally like to retrieve it from a CDN (or at least keep it separate).
This is my gulpfile:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
gulp.task('js', function () {
return browserify('./public/js/app.js', {
debug: false, bundleExternal: true
})
.transform(babelify, {"presets": ["es2015", "react"]})
.bundle()
.pipe(source('app.js'))
.pipe(gulp.dest('./build/js/'));
});
If I set "bundleExternal" to false then it does stop react being included in my js - but then nothing works because "react" is not found. I found something about browserify-shims but couldn't get it to work from gulp. And wasn't sure if it was the right way to go?
Apologies for the newbie question!
To include ReactCSSTransitionGroup you need to install it first:
npm install react-addons-css-transition-group
Then just require it:
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
Related
I have the following gulpfile.js:
var gulp = require('gulp'),
babel = require('gulp-babel'),
concat = require('gulp-concat'),
react = require('gulp-react'),
sass = require('gulp-sass'),
jsxToJs = function() {
//gulp.src('src/**/*.js')
gulp.src('./src/sections/header/header.js')
.pipe(react())
.pipe(babel({
presets: ['es2015']
}))
.pipe(concat('javascript.js'))
.pipe(gulp.dest('./'));
};
gulp.task('jsxToJs', jsxToJs);
gulp.task('build', ['jsxToJs', 'styles']);
gulp.task('watch', function () {
gulp.watch([
'./src/**/*.js',
'./src/**/*.scss'
], [
'jsxToJs',
'styles'
]);
});
gulp.task('default', ['build', 'watch']);
And I'm trying to compile the following functional React component:
let Header = (props) => {
return(
<div />
);
};
However, when I run the javascript.js file created by gulp I get the following error:
Uncaught TypeError: e.render is not a function
If I convert the component back to the old way of doing things like this (which is how I found it as I'm revisiting an old problem):
var Header = React.createClass({
render: function() {
}
});
Then it works.
Looking at the compiled JS shows me this - where I can see that render is being compiled out correctly with the old syntax, but for the new syntax, while it's being ESfivified it's not being reactified:
// not working
"use strict";
var Header = function Header(props) {
return React.createElement("div", );
};
// working
"use strict";
var Header = React.createClass({ displayName: "Header",
render: function render() {
return React.createElement("div", );
}
});
I've checked that I've installed my gulp requires correctly and I'm using Node 6.10.2. My gulp file has some extra things for scss in that I've removed for this question.
A couple of other points:
I'm not using a bundling tool like browserify as I think it's overkill for this project - so no imports or exports.
I'm just loading HTML pages that do JSONP to an endpoint and load a script on page that includes the JSON - this is done in a getInitialState in the page level HOCs.
Can anyone explain what I'm doing wrong?
The solution turned out to be pretty simple.
Babel requires presets to be provided in order to transpile.
I had the es2015 preset, but not the react one. Therefore react specific tranpilations were not occurring. This addition fixed the problem:
.pipe(react())
.pipe(babel({
presets: ['es2015', 'react']
}))
The mistake I was making, that sent me down the wrong rabbit hole in Google, was assuming that failing to reactify was something to do with the gulp-react function - silly me.
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.
I am trying to build a gulp based process that would use AngularJS from a bower package and a tool called debowerify (which I believe should let me plug in the installed bower components into the TSIFY/Browserify stream). Essentially, I want to build an app.js file for use in my application (with all the JS I need). I cannot for the life of me get AngularJS to work in this process. I am using an index.ts file (see below) to bring in my references for browserify to work with. It has been tricky with angular as the library is optimized out by the compilation process unless you use the import in some way hence the module call I was testing in the index.ts file.
index.ts
//#### Type Definitions ####
/// <reference path="../../typings/angularjs/angular.d.ts" />
/// <reference path="greeter.ts" />
import angular = require('angular');
import greeter = require('./Greeter');
var greet = new greeter();
greet.sayHello();
angular.module('app', []);
Here are my gulp defintions:
gulpfile.js
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
var tsify = require('tsify');
var debowerify = require('debowerify');
var exorcist = require('exorcist');
var config = {
publicDir: __dirname + '/app',
path: __dirname + '/src/typescript',
main: 'index.ts',
result: 'app.js'
};
gulp.task('compile-ts', function(){
var bundler = browserify({
basedir: config.path,
debug: true
})
.add(config.path + '/' + config.main)
.plugin(tsify)
.transform(debowerify);
return bundler.bundle()
.pipe(exorcist(config.publicDir + '/app.js.map'))
.pipe(source(config.result))
.pipe(gulp.dest(config.publicDir));
});
The custom TS files I built (ie: greeter.ts) work great. However, when I run my gulp compile-ts task I get no errors in the console only in the browser when it informs me that angular is undefined (on the call to angular.module). I have suspicions that CommonJS may not be supported for angular, but I also found information on the interwebs to the contrary of that. I am trying to avoid AMD if possible but if that is my only option I would certainly re-consider. I have this application working if I link to the angular script in my html rather than attempt to import it into my typescript, but I am just not satisfied with that approach as I know this should work.
Angular doesn't currently support CommonJS, replacing
import angular = require('angular');
with
require('angular');
solved it for me. See here.
I just got started using React. I went through the CommentBox tutorial without any issues. But the framework does not give much/any guidance to organizing your JS files or compiling a single minified JS file for a SPA. I already know the framework is flexible and does not enforce a standard and I'm sure these questions are probably dead obvious for someone who develops in the Javascript ecosystem.
I would imagine the consensus is to use Browserify and in the docs there's a link to a git starter project:
https://github.com/petehunt/react-browserify-template
This is a good start, but still it only compiles a single JS file "index.js". I read through some of the browserify handbook and I thought I simply had to 'require' my other files (and those files need to export themselves).
So I modified index.js to look like this:
/** #jsx React.DOM */
var React = require('react');
var pkg = require('./package.json');
var commentBox = require('./comment-box.js');
comment-box.js is basically a hello world test:
/** #jsx React.DOM */
var React = require('react');
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
);
}
});
React.renderComponent(
<CommentBox />,
document.getElementById('content')
);
module.exports = CommentBox;
If I run the react-browserify-template's start target it seems to generate browser-bundle.js fine:
npm start
But if I try the build target
npm build
...nothing happens. I changed the output of npm to verbose and I get the following:
npm info it worked if it ends with ok
npm verb cli [ 'node', '/usr/local/bin/npm', 'build' ]
npm info using npm#1.4.21
npm info using node#v0.10.24
npm verb exit [ 0, true ]
npm info ok
According to package.json it's supposed to generate a file "browser-bundle.min.js" but instead I get no output. I'm hoping someone can clear this up.
I figured out what the problem was. As I stated originally, it is probably obvious for someone who's been developing in the JS ecosystem :)
The package.json in the react-browserify-template has three scripts in the "scripts" section with the keys "start", "build", and "test".
As I said previously, start worked fine by running:
npm start
I wrongly assumbed that I could run the build script similarly:
npm build (this will never work and there will be no errors/output)
It turns out I needed to run the build script using:
npm run-script build
One extra line in the documentation might have saved me hours of trouble :D I'm now using this approach as it seems quite a bit simpler. Also, it sets NODE_ENV to production and uses envify which apparently is important: https://github.com/facebook/react/issues/1772
One other thing, some of the official examples such as todomvc-flux use the lowercase 'react' in the require function:
var React = require('react');
so I suppose that's the recommended syntax (?)
Working solution using Felix's gist. Note: This is not 100% equivalent to the react-browserify-template which uses envify and the production flag to get rid of some React debugging (mainly "Download the React DevTools for a better development experience: http://fb.me/react-devtools" which is printed to the console on startup).
Perhaps a mod can give Felix credit for the solution?
App.js
/**
* #jsx React.DOM
*/
"use strict";
var React = require('React');
var CommentBox = require('./components/CommentBox.js');
React.renderComponent(
<CommentBox />,
document.getElementById('content')
);
components/CommentBox.js
/** #jsx React.DOM */
var React = require('React');
var CommentList = require('./CommentList.js');
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList />
</div>
);
}
});
module.exports = CommentBox;
components/CommentList.js
/** #jsx React.DOM */
var React = require('React');
var CommentList = React.createClass({
render: function() {
return (
<div className="commentList">
Hello, world! I am a CommentList.
</div>
);
}
});
module.exports = CommentList;
I can't seem to get reactify to work with coffeeify. I followed the Reactify's readme to no avail.
app.coffee
### #jsx React.DOM ###
console.log 'hi'
browser command:
browserify -t coffeeify -t [ reactify -x coffee] ./src/coffeescripts/app.coffee
/Users/mueller.128/repos/klc/react_colorpicker/src/coffeescripts/app.coffee:1
/** #jsx React.DOM */
^
ParseError: regular expressions cannot begin with `*`
my attempt at using the browserify api in a gulp task
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var watchify = require('watchify');
var coffeeify = require('coffeeify');
var reactify = require('reactify');
gulp.task('browserify', function() {
return browserify('./src/coffeescripts/app.coffee')
.transform({ }, coffeeify)
.transform({ extension: "coffee" }, reactify)
.bundle({debug: true})
.pipe(source('./src/bundle.js'))
.pipe(gulp.dest('./build/javascripts/'));
});
Thanks for any help.
I ran into this same issue -- ParseError: regular expressions cannot begin with `*` -- when using coffee-reactify as duereg suggests. Following the recipe from the gulp recipe led me to this:
bundler = browserify 'test.cjsx', {
transform : [ require 'coffee-reactify' ]
}
...which exhibited the issue. Some ad-hoc logging in browserify revealed it's some kind of subtle bug where the transforms get added twice when specified in this way, confirming Ben's suspicion that the compiler was running twice. Changing it to the following:
bundler = browserify 'test.cjsx'
bundler.transform require 'coffee-reactify'
...fixed the issue entirely.
A functioning example:
gulp = require 'gulp'
gutil = require 'gulp-util'
browserify = require 'browserify'
source = require 'vinyl-source-stream'
bundler = browserify './test.cjsx'
bundler.transform require 'coffee-reactify'
bundle = ->
return bundler.bundle()
.on 'error', gutil.log.bind(gutil, 'Browserify Error')
.pipe source 'all-scripts.js'
.pipe gulp.dest './.dist'
gulp.task 'default', ->
bundle()
Where test.cjsx is just:
# #cjsx React.DOM
Someone recently opened a ticket on browserify's github.
browserify -t coffeeify -t [ reactify -x] ./app.coffee
I've had luck with the following gulp task. Note that you'll have to install the coffee-reactify plugin for this to work.
var gulp = require('gulp');
var browserify = require('gulp-browserify');
var rename = require('gulp-rename');
gulp.task('browserify', function() {
gulp.src('./src/coffeescripts/app.coffee', { read: false })
.pipe(browserify({
debug: true
transform: ['coffee-reactify'],
extensions: ['.coffee']
}))
.pipe(rename('./src/bundle.js'))
.pipe(gulp.dest('./build/javascripts/'))
});