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
Related
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.
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.
I am using the following gulp.js file
var gulp = require('gulp');
var babel = require('gulp-babel');
gulp.task('bundle', bundle);
function bundle () {
gulp.src('./src/*.jsx')
.pipe(babel())
.pipe(gulp.dest('./dist'));
}
gulp.task('build', ['bundle']);
Before transpile "main.jsx" content
import React from 'react';
After Transpile, "js" files generated in the dist folder, has require('')
var _react = require('react');
while requesting for the page index.html
<body>
<div id="app" ></div>
<script src="main.js"></script>
</body>
Uncaught ReferenceError: require is not defined is shown in the console.
I know there is something wrong in the build task, but i am unable to figure out.
In the browser, you can not use require API, so you need to somehow bundle your code, you have few options:
Browserify
Webpack
Rollup
These module bundlers allow you to specify an 'entry' point and then bundle all the required modules together in a single file.
Similar questions that answer this problem:
Gulp + babelify + browserify issue
I created a new angular2 app using the angularCLI (just so you know my directory structure).
Running ng serve puts all my files in the dist folder and runs the hello world app in the browser with no issue.
I'm trying to run the same app in electron, but it is unable to find all the vendor files (including #angular) since it uses the file protocol in a script src:
This
<script src="vendor/es6-shim/es6-shim.js"></script>
<script src="vendor/reflect-metadata/Reflect.js"></script>
<script src="vendor/systemjs/dist/system.src.js"></script>
<script src="vendor/zone.js/dist/zone.js"></script>
produces this
file:///vendor/es6-shim/es6-shim.js Failed to load resource: net::ERR_FILE_NOT_FOUND
file:///vendor/reflect-metadata/Reflect.js Failed to load resource: net::ERR_FILE_NOT_FOUND
file:///vendor/systemjs/dist/system.src.js Failed to load resource: net::ERR_FILE_NOT_FOUND
file:///vendor/zone.js/dist/zone.js Failed to load resource: net::ERR_FILE_NOT_FOUND
How do you prepend the correct path in the file: protocol that electron uses?
My gulpfile.js:
var gulp = require('gulp'),
del = require('del'),
runSeq = require('run-sequence');
gulp.task('clean-electron', function(){
return del('dist/electron-package/**/*', {force: true});
});
gulp.task('copy:electron-manifest', function(){
return gulp.src('./package.json')
.pipe(gulp.dest('./dist/electron-package'))
});
gulp.task('copy:electron-scripts', function(){
return gulp.src('./src/electron_main.js')
.pipe(gulp.dest('./dist/electron-package'));
});
gulp.task('copy:vendor-for-electron', function() {
return gulp.src('./dist/vendor/**/*')
.pipe(gulp.dest('./dist/electron-package/vendor'))
});
gulp.task('copy:spa-for-electron', function(){
return gulp.src(["./dist/*.*", "./dist/app/**/*"])
.pipe(gulp.dest('dist/electron-package'));
});
gulp.task('electron', function(done){
return runSeq('clean-electron', ['copy:spa-for-electron', 'copy:vendor-for-electron', 'copy:electron-manifest', 'copy:electron-scripts' ], done);
});
The closest I got was doing this:
my index.html:
<script src="vendor/es6-shim/es6-shim.js"></script>
<script src="vendor/reflect-metadata/Reflect.js"></script>
<script src="vendor/systemjs/dist/system.src.js"></script>
<script src="vendor/zone.js/dist/zone.js"></script>
<script>
console.log("In my script tag:");
var systemConfigPath = 'system-config.js';
var mainPath = 'main.js';
if (window.location.protocol == "file:"){
require(__dirname + '/vendor/es6-shim/es6-shim.js');
require(__dirname + '/vendor/reflect-metadata/Reflect.js');
require(__dirname + '/vendor/systemjs/dist/system.src.js');
require(__dirname + '/vendor/zone.js/dist/zone.js');
systemConfigPath = __dirname + '/' + systemConfigPath;
mainPath = __dirname + '/' + mainPath ;
}
System.import(systemConfigPath).then(function () {
System.import(mainPath);
}).catch(console.error.bind(console));
but that still gives me issues as the vendor files reference other files inside the same directories:
Edit:
I am now trying to use webpack to build my electron app (with no success).
I also created a github repo if you would like to see the code.
From How should I configure the base href for Angular 2 when using Electron? the answer is to change you
<base href="/">
to
<base href="./">
Okay! so I am not sure it's the best answer, as it still produces some silly errors, but here we go...
My index.html now looks like this:
<body>
<electron-angular-boilerplate-app>Loading...</electron-angular-boilerplate-app>
<!--will give errors in electron... oh well-->
<script src="vendor/es6-shim/es6-shim.js"></script>
<script src="vendor/reflect-metadata/Reflect.js"></script>
<script src="vendor/systemjs/dist/system.src.js"></script>
<script src="vendor/zone.js/dist/zone.js"></script>
<script>
// if require is defined, we are on node / electron:
if (!(typeof(require) == "undefined")){
require('./vendor/es6-shim/es6-shim.js');
require("./vendor/reflect-metadata/Reflect.js");
require("./vendor/systemjs/dist/system.src.js");
require("./vendor/zone.js/dist/zone.js");
require("./system-config.js");
require("./main.js");
} else {
System.import('system-config.js').then(function () {
System.import('main');
}).catch(console.error.bind(console));
}
</script>
</body>
This allows both my angular cli application to run and my electron app to run. The <script src=... tags still produce errors in electron as it is not able to find them. I also had to remove the System.import line from electron, so hopefully that doesn't cause any issues later on.
and to run it, we just need to make sure that the app is built and run electron in the ./dist folder:
ng build && electron ./dist
Here is the branch with my working code:
https://github.com/jdell64/electronAngularBoilerplate/tree/so-37447020-answer
I copied a ReactJS project to a new folder, made some changes, and it's not finding the react NPM module. I stripped the app down to 1 simple file, took out all the major code. This is driving me nuts, I deleted the node_modules folder, and ran NPM install.
I'm using watchify:
watchify --debug -t reactify app3.jsx -o ./build/app-brow.js
I Restarted my Terminal console in case that was out of sync, still can't find react.
I copied the original project to another folder, and it works OK from that copy, there's something about the code/files below that I'm missing.
It shows Uncaught TypeError: undefined is not a function, here which is the JS return code in my render:
React.createElement("div", null,
"Test, TEST TEST."
)
FILES:
app.jsx
/** #jsx React.DOM */
var React = require('react');
var App = React.createClass({
render: function() {
return (
<div>
Test, TEST TEST.
</div>
);
}
});
React.renderComponent((
<App />
), document.body);
index.html
<!DOCTYPE html>
<html>
<head>
<title>Test 3</title>
</head>
<body>
HAH... If you see this there is an error, make sure JavaScript is enabled in your browser.
<script type="text/javascript" src="build/app-brow.js"></script>
</body>
</html>
package.json
{
"name": "Test3",
"dependencies": {
"react": "0.11.x",
"reactify": "0.14.0"
}
}
Reactify is compiling your JSX in the React 0.12 style, but you are using React 0.11. Either upgrade React to 0.12.x or downgrade Reactify to a version that uses react-tools 0.11.