Gulp and React require is not defined and browserify not working - reactjs

I have app structure:
-- dist
- index.html
-- js
- index.js
- package.json
- package-lock.json
- gulpfile.js
In index.html I have this:
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<link rel="stylesheet" type="text/css" href="/css/main.css">
</head>
<body>
<div id='root'></div>
<script type="text/javascript" src="/js/index.js"></script>
</body>
</html>
In index.js I have this simple React app:
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render((
<h1>Hello world</h1>),
document.getElementById('root')
);
And this script in Gulp with appropriate imports and packages:
gulp.task('js', () =>
gulp.src('js/*.js')
.pipe(babel({
presets: ['env', 'react', 'es2015']
}))
.pipe(gulp.dest('dist/js'))
);
gulp.task('webserver', function() {
gulp.src('dist')
.pipe(webserver({
livereload: true,
directoryListing: true,
open: 'http://localhost:8000/index.html'
}));
});
gulp.task('watch', function() {
gulp.watch('styles/**/*.less', ['less']);
gulp.watch('js/**/*.js', ['js']);
gulp.src('dist')
.pipe(webserver({
open: 'http://localhost:8000/index.html'
}));
});
// + less
gulp.task('default', [ 'less', 'watch', 'js']);
It correctly creates copy of js files and add them to the dist/js folder and the server start running. The first load throw error in console Failed to load resource: the server responded with a status of 404 (Not Found) index.js:1 but on second load it works fine but throw error Uncaught ReferenceError: require is not defined index:3.
I found on the internet similar cases and the advice was to use browserify or webpack. I tried this script to bundle everything instead of the above code:
gulp.task('js', function () {
var b = browserify({
entry: './js/*.js',
debug: true,
transform: [babelify.configure({
presets: ['env', 'react', 'es2015']
})]
});
return b.bundle()
.pipe(source('index.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', log.error)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./dist/js/'));
});
The application loads but the React is not there. it creates accordingly index.js and index.map but the DOM is not updated from the React.
It's the first time using Gulp so I am not sure what I am doing wrong.

Related

HTML href not finding resource in project

I've been trying to learn angularJS, specifically 1.5 using components. My IDE is c9 so the server uses port: process.env.PORT which when I start will show the project at https://projectName-username.c9users.io (with angular-ui-router it has '/#!' on the end). This ide doesn't seem to compile es6 without using something like gulp. So I copy pasted much of the gulp code from the tutorial into my own project so that I could continue using the es6 syntax to build my own project.Everything is working pretty well except I am trying to link bootstrap 4 and my own css files from inside the project rather than a cdn and I can't seem to get the file path correct. When running the gulp file it says serving files from ./build so I tried writing the path from there but it has 404 on the resource.The closest I've come to was no errors thrown trying <link rel="stylesheet" src="#!/src/bower_components/bootstrap/dist/css/bootstrap.min.css"> but checking the network it says it's loading https://billardsWebsite-rawlejuglal.c9users.io/ with type stylesheet but nothing is actually there. Below is my file structure, the index.html file and then the gulpfile. If anyone can enlighten me on how to structure my links to find these resources I would appreciate it.
billardsWebsite
-.c9
-.git
-build
-index.html
-main.js
-node_modules
-src
-bower_components
-boostrap
-dist
-css
-bootstrap.min.css
-js
-css
-styles.css
-index.html
-.bowerrc
-.bower.json
-gulpfile.js
-package.json
-Procfile
Index.html (src/index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<title ng-bind="pageTitle"></title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="#!/src/bower_components/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
<div ui-view></div>
<!-- jQuery first, then Tether, then Bootstrap JS. -->
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script src="main.js"></script>
</body>
</html>
gulpfile.js
var gulp = require('gulp');
var notify = require('gulp-notify');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
var babelify = require('babelify');
var ngAnnotate = require('browserify-ngannotate');
var browserSync = require('browser-sync').create();
var rename = require('gulp-rename');
var templateCache = require('gulp-angular-templatecache');
var uglify = require('gulp-uglify');
var merge = require('merge-stream');
// Where our files are located
var jsFiles = "src/js/**/*.js";
var viewFiles = "src/js/**/*.html";
var interceptErrors = function(error) {
var args = Array.prototype.slice.call(arguments);
// Send error to notification center with gulp-notify
notify.onError({
title: 'Compile Error',
message: '<%= error.message %>'
}).apply(this, args);
// Keep gulp from hanging on this task
this.emit('end');
};
gulp.task('browserify', ['views'], function() {
return browserify('./src/js/app.js')
.transform(babelify, {presets: ["es2015"]})
.transform(ngAnnotate)
.bundle()
.on('error', interceptErrors)
//Pass desired output filename to vinyl-source-stream
.pipe(source('main.js'))
// Start piping stream to tasks!
.pipe(gulp.dest('./build/'));
});
gulp.task('html', function() {
return gulp.src("src/index.html")
.on('error', interceptErrors)
.pipe(gulp.dest('./build/'));
});
gulp.task('views', function() {
return gulp.src(viewFiles)
.pipe(templateCache({
standalone: true
}))
.on('error', interceptErrors)
.pipe(rename("app.templates.js"))
.pipe(gulp.dest('./src/js/config/'));
});
// This task is used for building production ready
// minified JS/CSS files into the dist/ folder
gulp.task('build', ['html', 'browserify'], function() {
var html = gulp.src("build/index.html")
.pipe(gulp.dest('./dist/'));
var js = gulp.src("build/main.js")
.pipe(uglify())
.pipe(gulp.dest('./dist/'));
return merge(html,js);
});
gulp.task('default', ['html', 'browserify'], function() {
browserSync.init(['./build/**/**.**'], {
server: "./build",
port: process.env.PORT || '3000',
notify: false,
ui: {
port: 3001
}
});
gulp.watch("src/index.html", ['html']);
gulp.watch(viewFiles, ['views']);
gulp.watch(jsFiles, ['browserify']);
});

HelloWorld example returns a syntax error on React

I tried to check all the libraries/packages that I needed to run a simple example of HelloWorld on React.js without success.
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
The error is the following:
/Users/Silvio/WebstormProjects/untitled/main.js:5
<h1>Hello, world!</h1>,
^
SyntaxError: Unexpected token <
I have installed babel and ReactDOM.
In your .babelrc file you need to specify the following
{
"presets": ["react", "stage-0", "es2015"]
}
Also you need to install the above presets like
npm install -S babel-preset-react babel-preset-stage-0 babel-preset-es2015
Along with that you webpack.config.js must look something like below to enable babel for .js or .jsx file extensions
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './main.js',
output: { path: __dirname, filename: 'bundle.js' },
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
}
]
},
};
You can refer here and here for more details
The code itself is correct, but you probably aren't running it properly as it is meant to be run in the browser, not in Node.js. If require is used to import dependencies, main.js must first be processed by a bundler like webpack before it is ready for use.
The following snippet is essentially the same code that you have posted but the dependencies (React and ReactDOM) are imported via script tags.
ReactDOM.render(<h1>Hello, world</h1>, document.getElementById("example"))
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello, world</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
</head>
<body>
<div id="example"></div>
</body>
</html>
Here Babel, which transpiles JSX (<h1>Hello, world</h1>) is provided by the snippet editor. This minimal example imports Babel as a dependency and transpiles the JSX portion at run time.
You need to run this through babel first - with react and stage-0 presets enabled.
We do this for our sample code here:
https://github.com/flexicious/react-redux-datagrid

How React JS index.js file contacting index.html for id references? [duplicate]

This question already has answers here:
Where's the connection between index.html and index.js in a Create-React-App application?
(2 answers)
Closed 3 years ago.
I recently get started with react.
My index.html contains
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
and index.js contains
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
ReactDOM.render(
<App />,
document.getElementById('root')
);
My doubt is I didn't mention index.js in any script tag in index.html. But how it is referencing the root div element in index.html? I was wondering as it is working fine. Please explain me.
I had run these commands to create the app
npm install -g create-react-app
create-react-app hello-world
cd hello-world
npm start
Create-React-App has a very interesting setup.
I started digging in the package.json npm script start
"start": "react-scripts start"
That takes me to their binary react-scripts under node_modules/.bin
I'll post the relevant stuff here.
switch (script) {
case 'build':
case 'eject':
case 'start':
case 'test': {
const result = spawn.sync(
'node',
[require.resolve('../scripts/' + script)].concat(args),
{ stdio: 'inherit' }
);
So this tells me that they are looking for script inside ../scripts/ folder.
So I go to the react-scripts npm module(node_modules/react-scripts) and open up the node_modules/react-scripts/scripts/start.js file since I was doing npm start.
Now here is where I found the webpack config I was looking for.
They were specifically referring to node_modules/react-scripts/config/webpack.config.dev.js. I'll post the relevant stuff here.
entry: [
// Finally, this is your app's code:
paths.appIndexJs,
],
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
}),
So file referred by paths.appIndexJs is the entry file in the webpack config.
And they are using HtmlWebpackPlugin to load the html at the path paths.appHtml.
Final piece of the puzzle is linking this back to the files you posted.
Posting relevant stuff from paths.js
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
...
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveApp('src/index.js'),
...
}
So inside your application directory,
appHtml is file public/index.html
appIndexJs is file src/index.js
Your two files in question.
Wow! That was quite a journey..:P
Update 1 - As of react-scripts#3.x
The react-scripts binary under node_modules/.bin has changed the logic as below. Essentially doing the same thing.
if (['build', 'eject', 'start', 'test'].includes(script)) {
const result = spawn.sync(
'node',
nodeArgs
.concat(require.resolve('../scripts/' + script))
.concat(args.slice(scriptIndex + 1)),
{ stdio: 'inherit' }
);
The webpack configs for dev & prod has been combined into one.
const configFactory = require('../config/webpack.config');
The HTMLWebpackPlugin config looks like this - This is since they have to conditionally add production config on top of this
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
The paths file code has some updates
module.exports = {
...
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
...
};

Reactjs file size: script-file vs npm-version

I am using reactjs and gulp for the build-process. Currently I use react from npm with browserify. When I want to minify my App in production-mode the react code ends up with about 180kb.
This is the gulp code I use:
gulp.task('production', function () {
var bundler = browserify('./public/dev/js/main.js').transform(babelify, { presets: ['react'] });
return bundler.bundle()
.on('error', map_error)
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(rename('bundle-build.min.js'))
.pipe(envify({'_': 'purge', NODE_ENV: 'production'}))
.pipe(uglify())
.pipe(gulp.dest('./public/dist/js/'));
});
However, if I download the minified script files from the react-website and load the script files like this:
<script type="text/javascript" src="./react.min.js"></script>
<script type="text/javascript" src="./react-dom.min.js"></script>
it ends up with about 150kb.
Why is the with gulp minified version bigger? How can I bring it to the same size? Also, is there a difference in the development / production of the app between loading the provided script files or using it from npm?
Thanks in advance
Cheers

Gulp - How to collect used files only and convert them as single files in `dest`

I am using the gulp for run my angular app. But I am facing a problem here.
all bower_components files are copied in dest ans bower_components folder
my js files ( say 2 ) I am getting 2 js files in dest folder
same things happening for html and css files too.
What i requires is :
dest file should have only one html and js and css all or minified with source map included.( if necessary )
Basically, the gulp need to collect the files, what just i have used in the app instead of collecting from the folder as .js.
How to do this?
here is my current gulp code :
// gulp
var gulp = require('gulp');
// plugins
var connect = require('gulp-connect');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var clean = require('gulp-clean');
var runSequence = require('run-sequence');
// tasks
gulp.task('lint', function() {
gulp.src(['./app/**/*.js', '!./app/bower_components/**'])
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'));
});
gulp.task('clean', function() {
gulp.src('./dist/*')
.pipe(clean({force: true}));
});
gulp.task('minify-css', function() {
var opts = {comments:true,spare:true};
gulp.src(['./app/**/*.css', '!./app/bower_components/**'])
.pipe(minifyCSS(opts))
.pipe(gulp.dest('./dist/'))
});
gulp.task('minify-js', function() {
gulp.src(['./app/**/*.js', '!./app/bower_components/**'])
.pipe(uglify({
// inSourceMap:
// outSourceMap: "app.js.map"
}))
.pipe(gulp.dest('./dist/'))
});
gulp.task('copy-bower-components', function () {
gulp.src('./app/bower_components/**')
.pipe(gulp.dest('dist/bower_components'));
});
gulp.task('copy-html-files', function () {
gulp.src('./app/**/*.html')
.pipe(gulp.dest('dist/'));
});
gulp.task('connect', function () {
connect.server({
root: 'app/',
port: 8888
});
});
gulp.task('connectDist', function () {
connect.server({
root: 'dist/',
port: 9999
});
});
// default task
gulp.task('default',
['lint', 'connect']
);
gulp.task('build', function() {
runSequence(
['clean'],
['lint', 'minify-css', 'minify-js', 'copy-html-files', 'copy-bower-components', 'connectDist']
);
});
You should make use of the gulp-useref module, which parses the build blocks in the HTML, replace them and pass those files through.
Here the example setup:
index.html:
<!doctype html>
<html ng-app="app">
<head>
<!-- build:js app.js -->
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="myscript.js"></script>
<!-- endbuild -->
</head>
<body>
Hello world!
</body>
</html>
gulpfile.js:
var gulp = require('gulp');
var useref = require('gulp-useref');
gulp.task('default', function () {
return gulp.src('app/index.html')
.pipe(useref())
.pipe(gulp.dest('dist'));
});
Running the gulp now will result in having the two files in the dist folder:
index.html - having the build block replaced by the only script tag, <script src="app.js"></script>
app.js - the concatenation of the files listed in the build block of the original index.html file
The same can be done with the css files as well.
This way you will have no extra files in your dest folder, just what you have used in your app.
var concat = require("gulp-concat");
gulp.task('minify-js', function() {
gulp.src(['./app/**/*.js', '!./app/bower_components/**'])
.pipe(uglify({
output: {
beautify: false
},
outSourceMap: true,
properties : true,
mangle:false
}))
.pipe(concat('bundle.js'))
.pipe(gulp.dest('./dist/'))
});
this will concatenate all files in one bundle.js file.

Resources