This is the gulpfile.js:
var gulp = require('gulp'),
browserify = require('gulp-browserify'),
babel = require('gulp-babel'),
babelify = require("babelify");
gulp.task('js', function () {
gulp.src(config.paths.js.src)
.pipe(browserify({
insertGlobals : true,
debug : true
}))
.pipe(gulp.dest(config.paths.js.dest))
});
In package.json I have added:
"browserify": {
"transform": [["babelify", { "presets": ["react"] }]]
}
And this is the file with react:
ReactDOM.render(
<Overlay message="TEST" />,
document.getElementById('content')
);
finally, the error is:
components/main-component.js:15
<div class="overlay">
^
ParseError: Unexpected token
at wrapWithPluginError (/home/novak/Documents/myProjects/OpenWorld/node_modules/gulp-browserify/index.js:44:1
Note: I am not using ES2015, just normal js.
I have tried a lot of things to put into the gulp task, but it always gives me some error. Could anybody advise me how to make this work please?
Some more sources:
main-component.js:
var React = require('react');
var ReactDOM = require('react-dom');
var Print = require('./main-template');
var Overlay = React.createClass({
getInitialState: function() {
return { show: false };
},
render: function() {
if (!this.state.show) {
return;
}
return(
<div class="overlay">
<div class="content">
<Print message="{this.props.message}"/>
</div>
</div>
);
}
});
ReactDOM.render(
<Overlay message="TEST" />,
document.getElementById('game-content')
);
module.exports = Overlay;
You need to convert .jsx to .js since Browser don't know the JSX. So you need to transform it before.
Steps to covert jsx to js:
Make sure that you have installed
gulp-babel
babel-plugin-transform-react-jsx
by
npm install gulp-babel babel-plugin-transform-react-jsx
Then in your gulp file
var gulp = require('gulp');
var babel = require('gulp-babel');
gulp.task("babel", function(){
return gulp.src("src to jsx/*.jsx").
pipe(babel({
plugins: ['transform-react-jsx']
})).
pipe(gulp.dest("src to js/*.js"));
});
Related
I am using browserify and babel to compile and bundle my react app. The files from client/ are bundled up into a single file static/bundle.js. But I use a relative import which seems to not be handled correctly.
Here's my file structure
client/
components/
main.js
App.js
static/
bundle.js
gulpfile.js
and here's my gulpfile and the offending import
// client/App.js
import React, { Component } from 'react';
import { render } from 'react-dom';
import App from './components/main.js';
render(
<App />,
document.getElementById('root'),
);
// gulpfile.js
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
gulp.task('build', function() {
browserify({
entries: 'client/App.js',
extensions: ['.js'],
debug: true
})
.transform(babelify, {presets: ['es2015', 'react']})
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('static'));
});
The problem is the line import App from './components/main.js';.
When I look in static/bundle.js, there is a line var _main = require('./components/main.js');, which doesn't make sense because relative to bundle.js there is no ./components/main.js. That was defined relative to client/App.js.
Does browserify not handle such things and is there another tool I should be using in addition, or am I doing something else incorrect?
You have to add paths to your browserify options. If you do not add that browserify doesn't know where to look for to find your module.
module.exports = function(grunt){
grunt.initConfig({
browserify: {
options:{
browserifyOptions: {
// ...
paths: [
'./node_modules',
'./client'
]
}
},
// ...
},
// ...
});
}
This was an issue before they solve it.
I have react and react-dom installed and imported in via the System.config below, but I still get this error below:
Uncaught (in promise) Error: Unexpected token <(…)
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ES2015 Module Example</title>
</head>
<body>
<script src="lib/system.js"></script>
<script>
System.config({
"baseURL": "src",
// Set defaultJSExtensions to true so you don't have to use .js extension when importing the es6 module.
"defaultJSExtensions": true,
// 'plugin-babel' or 'traceur' or 'typescript'
transpiler: 'traceur',
map: {
'react': './node_modules/react/dist/react.min.js',
'react-dom': './node_modules/react-dom/dist/react-dom.min.js',
'traceur': './lib/traceur.min.js',
'plugin-babel': './lib/plugin-babel/plugin-babel.js',
'systemjs-babel-build': './lib/plugin-babel/systemjs-babel-browser.js'
},
});
System.import("app.js");
</script>
</body>
<div id="example"></div>
</html>
app.js:
import React from 'react';
import ReactDOM from 'react-dom';
var Hello = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('example')
);
Any ideas what else do I have to configure?
browserify is the best solution (for production & development) - to me:
npm install --save-dev babel-preset-react
gulp:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var livereload = require('gulp-livereload');
gulp.task('build', function() {
// app.js is your main JS file with all your module inclusions
return browserify({entries: 'src/app.js', debug: true})
.transform("babelify", { presets: ["es2015", "react"] })
.bundle()
.pipe(source('compile.min.js'))
.pipe(buffer())
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write('./maps'))
.pipe(gulp.dest('js'))
.pipe(livereload());
});
gulp.task('default', ['build']);
As for non-production with SystemJS (painfully slow):
<!DOCTYPE html>
<script src="https://jspm.io/system#0.19.js"></script>
<script>
System.config({
transpiler: 'babel',
babelOptions: {}
});
System.import('./main.js');
</script>
You still can use gulp for development. Just add this to the gulpfile:
gulp.task('watch', ['build'], function () {
livereload.listen();
gulp.watch('js/*.js', ['build']);
});
gulp.task('default', ['watch']);
This saves you from other tedious dev workflows as listed here.
Unexpected token < usually occurs in html5 applications, when the server is configured to return the contents of index.html instead of 404 pages (so pressing f5 on dynamic routing still works). Check then network panel in your browsers developer console, and see which js file was served with html contents.
I am working on a project where I am using gulp. However, gulp keeps throwing an error saying it cannot find the AppAPI.js file in my work environment. I am building with Reactjs and Flux. I believe the problem may be in my gulpfile, but after trying various versions of the code, I have not been able to get anywhere. Could someone take a look and see if indeed my code is wrong or if there could be something else going wrong? Here is my gulpfile:
var gulp = require('gulp');
var browserify = require('browserify');
var reactify = require('reactify'); // Converts jsx to js
var source = require('vinyl-source-stream'); // Converts string to a stream
gulp.task('browserify', function(){
browserify('./src/js/main.js')
.transform('reactify')
.bundle()
.pipe(source('main.js'))
.pipe(gulp.dest('dist/js'));
});
gulp.task('copy', function(){
gulp.src('src/index.html')
.pipe(gulp.dest('dist'));
gulp.src('src/css/*.*')
.pipe(gulp.dest('dist/css'));
gulp.src('src/js/vendors/*.*')
.pipe(gulp.dest('dist/js'));
});
gulp.task('default', ['browserify', 'copy'], function(){
return gulp.watch('src/**/*.*', ['browserify', 'copy']);
});
I am requiring appAPI.js in my main.js file:
var App = require('./components/App');
var React = require('react');
var ReactDOM = require('react-dom');
var AppAPI = require('./utils/appAPI.js');
ReactDOM.render(
<App />,
document.getElementById('app')
);
Here is the appAPI.js code:
var AppActions = require('../actions/AppActions');
module.exports = {
}
I am using webpack to bundle/transform jsx.
From the command line I'm running "webpack --watch". This creates my bundle without errors. Here's my webpack config and Application.js
'use strict';
var webpack = require('webpack');
module.exports = {
resolve: {
extensions: ['', '.js']
},
devtool: 'eval',
entry: './client.js',
output: {
path: __dirname+'/build/js',
filename: 'client.js'
},
module: {
loaders: [
{ test: /\.css$/, loader: 'style!css' },
{ test: /\.js$/, loader: 'jsx-loader?harmony' }
]
}
};
var React = require('react'),
classSet = require('react/addons'),
Nav = require('./Nav.js'),
Home = require('./Home.js'),
Recipe = require('./Recipe.js'),
RecipeArchive = require('./RecipeArchive.js'),
About = require('./About.js'),
Timestamp = require('./Timestamp.js'),
RouterMixin = require('flux-router-component').RouterMixin;
var Application = React.createClass({
mixins: [RouterMixin],
getInitialState: function () {
this.store = this.props.context.getStore('ApplicationStore');
return this.store.getState();
},
componentDidMount: function () {
var self = this;
self._changeEventListener = function () {
var state = self.store.getState();
self.setState(state);
};
self.store.on('change', self._changeEventListener);
},
componentWillUnmount: function () {
var self = this;
self.store.removeListener('change', self._changeEventListener);
self._changeEventListener = null;
},
render: function () {
return (
<div>test</div>
);
}
});
module.exports = Application;
Then I'm running my node server which throws an error.
node server.js
results in:
/Users//Documents/routing/components/Application.js:39
<div>test</div>
^
SyntaxError: Unexpected token <
How should I be running my project to allow me to include jsx/harmony in my .js files?
UPDATE: Solution
As Brandon pointed out, I needed to use node-jsx for transforms in Node. At the top I've of my server.js file I've added and alls working:
require('node-jsx').install({ extension: '.js', harmony: true });
Webpack just creates a client-side bundle; when you run your Node app, it doesn't use webpack to load the files. Prevously you could use something like node-jsx to require JSX files in Node.js, but that project has since been deprecated in favor of Babel. In particular, you can use babel-register to require JSX files in Node.
I have modular javascript application and I need to have js frameworks in one file "global-libs.js", which dependencies will be accessible for every file using webpack. Other js files will only use these dependencies but it will not be part of the final bundle. I'am using Gulp for these task in combination of Webpack.
This is task for webpack and transpile my jsx into js where should be only my code, not external libraries
gulp.task('js',['jsx'], function () {
/**This dependency is external, its not part of the bundle */
return gulp.src(config.paths.workDir + config.paths.jsPath + '/**/*.js')
.pipe(webpack({
externals: {
"react": "React"
}
}))
.pipe(rename('onlyCustomJs.js'))
.pipe(gulpif(args.production, uglify()))
.pipe(gulp.dest(config.paths.portlets.newNotePortlet + config.paths.jsPath))
});
This task should create files only with externals libraries and dependency React should be accessible using require in every js webpack file.
gulp.task('global', function(){
/**This will be accessible globally*/
return gulp.src(config.paths.srcDir + config.paths.jsPath + '/global-libs.js')
.pipe(webpack({
output: {
libraryTarget: "var",
library: "React"
}
}))
.pipe(rename('global-libs.js'))
.pipe(gulp.dest(config.paths.portlets.evremTheme + config.paths.jsPath))
});
This file uses global react dependency. But it tells me that React is undefined at var HelloMessage = React..
/** #jsx React.DOM */
var React = require('react');
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.renderComponent(HelloMessage({name: "Hello world"}), document.getElementById('example'));
This is global-libs.js file
var React = require('react');
var jQuery = require('jquery');
Thank you!
Maybe It's not to best solution but I solved by these changes.
//These is dependencies which will be bundled in one global-libs.js file and will be accessible from everywhere through require().
module.exports = React = require('react');
module.exports = jQuery = require('jquery');
Webpack only merge these two files and publish them through module.exports
gulp.task('global', function(){
/**This will be accessible globally*/
return gulp.src(config.paths.srcDir + config.paths.jsPath + '/global-libs.js')
.pipe(webpack())
.pipe(rename('global-libs.js'))
.pipe(gulp.dest(config.paths.destDir + config.paths.jsPath))
});
My gulp task for bundling my conde is like this. Only specified externals dependencies which will not be part of the bundle.
gulp.task('js',['jsx'], function () {
/**This dependency is external, its not part of the bundle */
return gulp.src(config.paths.workDir + config.paths.jsPath + '/**/*.js')
.pipe(webpack({
externals: {
"react": "React",
"jquery": "jQuery"
}
}))
.pipe(rename('bundle.js'))
.pipe(gulpif(args.production, uglify()))
.pipe(gulp.dest(config.paths.destDir + config.paths.jsPath))
});
In result I can import dependencies like this.
/** #jsx React.DOM */
var React = require('react');
var jQuery = require('jquery');
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.renderComponent(HelloMessage({name: "Hello world"}), jQuery('#example')[0]);