Error using gulp with bundle - HTML parsing error - javascript

So i got this very simple gulp task :
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
gulp.task('browserify', function() {
return browserify({ entries: ['main.js'] })
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('dist'));
});
gulp.task('default', ['browserify']);
Which is supposed to simply browserify my main.js to bundle.js and then store it in a dist folder.
Problem is, it seems that gulp doesnt like it when parsing HTML because i got this error :
events.js:85
throw er; // Unhandled 'error' event
^ Error: Parsing file C:\Dev\react_wkspc\main.js: Unexpected token (5:2)
my main.js is also very basic :
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>First test of react!</h1>,
document.getElementById('container');
);
and the error seems to come from this line <h1>First test of react!</h1>, which is, i believe, the proper way to uses React because it is the same script as the official React doc
i also tried with babelify and this script :
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var babelify = require('babelify');
var browserify = require('browserify');
gulp.task('browserify', function () {
browserify({
entries: 'main.js',
extensions: ['.js'],
debug: true
})
.transform(babelify)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('dist'));
});
gulp.task('default', ['browserify']);
and got the same error
SyntaxError: C:/Dev/react_wkspc/main.js: Unexpected token (5:2)

The missing steps from what I can read is
add babelify
make sure that you also have the proper babel presets installed such that your source can be parsed correctly.
Here is an example from a project of mine, with b being browserify
function bundleShare(b, output) {
return b
.transform(babelify.configure({
presets: ["es2015", "react"]
}))
.bundle()
.pipe(source(output))
.pipe(gulp.dest('./wwwroot/assets'));
}
In my package json I have the following dev dependencies
"
babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babelify": "^7.2.0",

Related

Connecting files via import does not work

For a day now, I can not understand why babel for gulp does not work for me, or I incorrectly connect the modules ...
The error in the browser is like this:
Uncaught ReferenceError: require is not defined
at main.min.js:1
I connect the modules like this:
import focusVisible from "focus-visible";
Code in main.min.js file:
"use strict";var e;(e=require("focus-visible"))&&e.__esModule;
Gulp task:
const { src, dest, series, watch, parallel } = require('gulp'),
fileinclude = require('gulp-file-include'),
rename = require("gulp-rename"),
uglify = require('gulp-uglify-es').default,
babel = require("gulp-babel"),
notify = require("gulp-notify"),
browserSync = require("browser-sync").create()
const changingScripts = () => {
return src(['src/js/main.js', 'src/js/pages/**/*.js'])
.pipe(babel())
.pipe(fileinclude())
.pipe(dest('dist/js'))
.pipe(uglify({
toplevel: true
}).on('error', notify.onError()))
.pipe(rename({
extname: '.min.js'
}))
.pipe(dest('dist/js'))
.pipe(browserSync.stream())
}
The package.json file is like this:
{
"name": "project_name",
"version": "1.0.0",
"description": "some description of the project",
"scripts": {},
"keywords": ["keyword_1", "keyword_2", "keyword_3"],
"author": "project_author",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.16.0",
"#babel/eslint-parser": "^7.16.3",
"#babel/preset-env": "^7.16.4",
"#babel/register": "^7.16.0",
"browser-sync": "^2.27.7",
"eslint": "^8.2.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.25.3",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-file-include": "^2.3.0",
"gulp-notify": "^4.0.0",
"gulp-rename": "^2.0.0",
"gulp-uglify-es": "^3.0.0"
}
}
The .babelrc file looks like this:
{
"presets": ["#babel/preset-env"]
}
It seems like everything has applied what is needed.
If you can help, I will be grateful.
The whole project got stuck because of this error ...
It is advisable to solve the problem without using Webpack :)
It seems like you could be missing a build step where you transform your code to be browser compatible. The require method is not available in the browser.
You have to use a tool which transforms your code so that it can be ran in the browser. One such tool is Browserify, another is rollup, and there may be more. These tools, generally speaking, bundle dependency sources in conjunction with your application code, which allows require statements to be transformed into some other pattern the browser does understand.
You can think of it like this (example is simplified):
Code written by you
// main.js
const stringify = require('stringify')
alert(stringify({ error: "No authorization" })
Dependency source in node_modules
// node_modules/stringify/index.js
function stringify(obj) {
return JSON.stringify(obj);
}
expost.default = stringify
Bundle result
// dist/main.js
function stringify(obj) {
return JSON.stringify(obj);
}
alert(stringify({ error: "No authorization" })
Gulp hosts an official example of usage in their repository for browserify:
'use strict';
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var log = require('gulplog');
var uglify = require('gulp-uglify');
var reactify = require('reactify');
gulp.task('javascript', function () {
// set up the browserify instance on a task basis
var b = browserify({
entries: './entry.js',
debug: true,
// defining transforms here will avoid crashing your stream
transform: [reactify]
});
return b.bundle()
.pipe(source('app.js', { sourcemaps: true }))
.pipe(buffer())
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', log.error)
.pipe(gulp.dest('./dist/js/', { sourcemaps: '../sourcemaps/' }));
});
Gulp Version control: Browserify + Transforms
I attempted to create an example for you, but it's difficult to say what the most usable gulp script would be for your project. I'll add an example, but please don't consider it as a fix that's ready for general use. It attempts to mimic the behaviour your current gulp script has. You may want other behaviour in the long run for instance because the bundling this script creates may not be as optimized as other configurations or tooling would allow.
const { dest } = require("gulp"),
browserify = require("browserify"),
babelify = require("babelify"),
glob = require("glob"),
source = require("vinyl-source-stream"),
fileinclude = require("gulp-file-include"),
rename = require("gulp-rename"),
uglify = require("gulp-uglify-es").default,
notify = require("gulp-notify"),
browserSync = require("browser-sync").create(),
es = require("event-stream");
const changingScripts = (done) => {
// Define files you want to have as inputs
var files = ["src/js/main.js", ...glob.sync("src/js/pages/**/*.js")];
// Bundle each file separately so that file structure is preserved in
// dist
var tasks = files.map((file) => {
return (
browserify({
entries: [file],
debug: true,
transform: [
// Apply babel transforms here so that browserify knows how to bundle
// the files
babelify.configure({
presets: ["#babel/preset-env"],
}),
],
})
.bundle()
// Transform the stream content bable bundling returns into a gulp
// friendly format
.pipe(source(file))
// Not sure how fileinclude is used in your project. May be that it
// doesn't work when it's configured in this way.
.pipe(fileinclude())
.pipe(dest("dist/js"))
.pipe(
uglify({
toplevel: true,
}).on("error", notify.onError())
)
.pipe(
rename({
extname: ".min.js",
})
)
.pipe(dest("dist/js"))
.pipe(browserSync.stream())
);
});
return es.merge(tasks).on("end", done);
};
exports.default = changingScripts;
Gulp: Creating multiple bundles with Browserify

AssertionError [ERR_ASSERTION]: Task function must be specified GULP (node js , keystone js )

I dont know why i am receiving this error AssertionError [ERR_ASSERTION]: Task function must be specified GULP (node js , keystone js ). What causes this error ? anyone can help ?. I am using keystone app and sass compilation?. gulp file that will restart keystonejs app and compile sass. Is this regarding on the gulp version my goal version in my package.json is "gulp": "^4.0.2",.
My Gulp file
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var jshintReporter = require('jshint-stylish');
var watch = require('gulp-watch');
var sass = require('gulp-sass');
var shell = require('gulp-shell')
var bs = require('browser-sync').create();
var paths = {
'src':['./models/**/*.js','./routes/**/*.js', 'keystone.js', 'package.json'],
'style': {
all: './public/styles/**/*.scss',
output: './public/styles/'
}
};
// gulp lint
gulp.task('lint', function(){
gulp.src(paths.src)
.pipe(jshint())
.pipe(jshint.reporter(jshintReporter));
});
// gulp watcher for lint
gulp.task('watch:lint', function () {
gulp.src(paths.src)
.pipe(watch())
.pipe(jshint())
.pipe(jshint.reporter(jshintReporter));
});
gulp.task('sass', function(){
gulp.src(paths.style.all)
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(paths.style.output))
.pipe(bs.stream());
});
gulp.task('watch:sass', function () {
gulp.watch(paths.style.all, ['sass']);
});
gulp.task('browser-sync', function(){
bs.init({
proxy: 'http://localhost:3000',
port: '4000'
});
});
gulp.task('runKeystone', shell.task('node keystone.js'));
gulp.task('watch', ['watch:sass', 'watch:lint']);
gulp.task('default', ['watch', 'runKeystone', 'browser-sync']);

Gulp doesn't combine or uglify

I seem to have configured Gulp to run in Netbeans. My goal is to have gulp simply combine all Javascript files from one directory into one file, and then "uglify" the that resulting file.
When I save one of my Javascript file, a new Javascript file is created, but, it is not combined with any other files, nor is it uglified. I don't get any error messages, but I don't get any desired results either. Where am I going wrong?
Here is my gulpfile.js:
var gulp = require('gulp'),
gp_concat = require('gulp-concat'),
gp_rename = require('gulp-rename'),
gp_uglify = require('gulp-uglify');
gulp.task('combine', function(){
return gulp.src(['*.js'])
.pipe(gp_concat('concat.js'))
.pipe(gulp.dest('dist'))
.pipe(gp_rename('uglify.js'))
.pipe(gp_uglify())
.pipe(gulp.dest('dist'));
});
gulp.task('default', ['combine'], function(){});
And here is my package.json:
{
"name": "xxxxxxxxxxxxxxxxxx",
"version": "1.0.0",
"keywords": ["util", "functional", "server", "client", "browser"],
"author": "xxxxxxxxxxxxxxxxxx",
"contributors": [],
"dependencies": {},
"scripts" :
{
"watch" : "watchify ../../html/xxxxxxxxxxxxxxxxxx/js/*.js -o ../../html/xxxxxxxxxxxxxxxxxx/bundle.js -v"
}
}
Note that these are files I copied from examples here on Stack Overflow and elsewhere in the web, so I'm sure I'm missing something.
Latest Update:
I am now using this revised Gulp file, with directory paths corrected:
var gulp = require('gulp'),
expect = require('gulp-expect-file'),
concat = require('gulp-concat'),
minify = require('gulp-minify'),
gutil = require('gulp-util'),
babel = require('gulp-babel'),
jsFiles = '../../html/public_html/js/*.js',
jsDest = '../../public_html/dist';
gulp.task('combine', function ()
{
return gulp.src(jsFiles)
.pipe(expect(jsFiles))
.pipe(babel({presets: ['babili']}))
.pipe(concat('concat.js'))
.pipe(minify().on('error', gutil.log))
.pipe(gulp.dest(jsDest));
});
When I run it, I still don't get any resulting combined file in my dist/folder.
I now get this error output:
[11:53:13] Using gulpfile ~\Documents\NetBeansProjects\Project_Name\gulpfile.js
[11:53:13] Starting 'combine'...
[11:53:13] Tested 5 tests, 5 passes, 0 failures: PASS
Done.
events.js:160
throw er; // Unhandled 'error' event
^
SyntaxError: ..\..\html\html\public_html\js\*.js
Unexpected token: operator (>) (line: 30, col: 34, pos: 95518
at JS_Parse_Error.get (eval at <anonymous> (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\uglify-js\tools\node.js:27:1), <anonymous>:86:23)
at PluginError.<anonymous> (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\gulp-util\lib\PluginError.js:37:60)
at Array.forEach (native)
at new PluginError (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\gulp-util\lib\PluginError.js:36:16)
at Transform.minify [as _transform] (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\gulp-minify\index.js:117:23)
at Transform._read (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:184:10)
at Transform._write (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:172:12)
at doWrite (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:237:10)
at writeOrBuffer (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:227:5)
at Transform.Writable.write (C:\Users\Project Username\Documents\NetBeansProjects\Project_Name\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:194:11)
Try this
var gulp = require('gulp'),
expect = require('gulp-expect-file'),
concat = require('gulp-concat'),
minify = require('gulp-minify');
gulp.task('combine', function() {
var files = ['*.js'];
gulp.src(files)
.pipe(expect(files))
.pipe(concat('concat.js'))
.pipe(minify())
.pipe(gulp.dest('dist/'));
});
```
You should also add the following lines "gulp-minify": "0.0.14" and "gulp-expect-file": "0.0.7" to the devDependencies of your package.json
I am not sure but it seems that the pattern ** (any folder) does not work in gulp. Hence your pattern *.js will search files with js extension in the root folder only.

Gulp/Babelify es6

I am using babel to transpile my es6 code. I'm also using gulp to do the tasks. My gulpfile.js looks like the following :
var gulp = require('gulp'),
es6Path = './src/*.js',
browserify = 'browserify',
babelify = require('babelify'),
source = require('vinyl-source-stream');
gulp.task('build', function () {
return browserify({entries: './src/script.js', extensions: ['.js'], debug: true})
.transform(babelify)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('dist'));
});
gulp.task('watch', ['build'], function () {
gulp.watch(es6Path, ['build']);
});
gulp.task('default', ['watch']);
But when I try to run gulp , I get this error :
Starting 'build'...
'build' errored after 100 μs
TypeError: string is not a function
Any idea why this happens ?
You set browserify to string 'browserify' then try to call it as a function. You need to require('browserify').

Keep original typescript source maps after using browserify

Background: I am compiling 2 dependent TypeScript files to js, which produces also source maps (one source map per file) using tsc 1.0
I'm using -m commonjs and then use browserify to generate a single bundle.js
However I noticed that I get the original source map references twice in the bundle, which doesn't seem to work.
Passing --debug doesn't seem to do the trick either.
I had a feeling this issue: https://github.com/substack/node-browserify/issues/325 is somewhat related, but I couldn't figure out how the issue was resolved.
Also https://github.com/substack/browser-pack was suggested, but again I don't fully understand how to use it, is it a replacement to browserify?
Bottom line, I would like to merge the 2 js files but "merge" the js to ts source maps using browserify. Is that possible?
tsify is a browserify plugin that is better and replaces e.g. typescriptifier.
npm install tsify browserify watchify
You use tsify like this:
browserify src/index.ts -p tsify --debug -o build/index.js
Notice that this supports browserify --debug switch, no extra tricks required. So you can also use it with watchify like this:
watchify src/index.ts -p tsify --debug -o build/index.js
Using the minifyify browserify plugin I believe you can use TypeScript with Browserify and retain the source maps. After compiling the TypeScript files you should be able to pass the "entry" file (the one that imports the other one via commonjs syntax) through browserify with the minifyify plugin.
var browserify = require('browserify'),
bundler = new browserify();
bundler.add('entry.js');
bundler.plugin('minifyify', {map: 'bundle.js.map'});
bundler.bundle({debug: true}, function (err, src, map) {
if (err) console.log(err);
fs.writeFileSync('bundle.js', src);
fs.writeFileSync('bundle.js.map', map);
});
Here is my working solution:
var settings = {
projectName : "test"
};
gulp.task("bundle", function() {
var mainTsFilePath = "src/main.ts";
var outputFolder = "bundle/src/";
var outputFileName = settings.projectName + ".min.js";
var pkg = require("./package.json");
var banner = [
"/**",
" * <%= pkg.name %> v.<%= pkg.version %> - <%= pkg.description %>",
" * Copyright (c) 2015 <%= pkg.author %>",
" * <%= pkg.license %>",
" */", ""
].join("\n");
var bundler = browserify({
debug: true,
standalone : settings.projectName
});
// TS compiler options are in tsconfig.json file
return bundler.add(mainTsFilePath)
.plugin(tsify)
.bundle()
.pipe(source(outputFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(header(banner, { pkg : pkg } ))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(outputFolder));
});
I created example project.
You can run it with $(npm bin)/gulp build --env=dev for development environment and source maps will be generated.
There is gulpfile.js:
'use strict';
var path = require('path'),
gulp = require('gulp'),
del = require('del'),
typescript = require('gulp-typescript'),
sourcemaps = require('gulp-sourcemaps'),
browserify = require('browserify'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer'),
uglify = require('gulp-uglify'),
gutil = require('gulp-util'),
inject = require('gulp-inject'),
babel = require('gulp-babel'),
argv = require('yargs').argv;
var devEnvironment = 'dev',
prodEnvironment = 'prod',
environment = argv.env || prodEnvironment,
isDevelopment = environment === devEnvironment;
var projectPath = __dirname,
srcDir = 'src',
srcPath = path.join(projectPath, srcDir),
buildDir = path.join('build', environment),
buildPath = path.join(projectPath, buildDir),
distDir = 'dist',
distRelativePath = path.join(buildDir, distDir),
distPath = path.join(buildPath, distDir);
var tsSrcPath = path.join(srcPath, 'typescript'),
tsGlob = path.join(tsSrcPath, '**', '*.ts'),
tsBuildPath = path.join(buildPath, 'tsc');
var indexHtmlName = 'index.html',
indexJsName = 'index.js';
var distIndexJsPath = path.join(distPath, 'index.js'),
distIndexHtmlPath = path.join(distPath, indexHtmlName);
var tsProject = typescript.createProject('tsconfig.json');
console.log('Environment: ' + environment);
gulp.task('clean', function () {
return del([buildPath]);
});
gulp.task('tsc', ['clean'], function () {
var stream = gulp.src([tsGlob]);
if (isDevelopment) {
stream = stream
.pipe(sourcemaps.init());
}
stream = stream
.pipe(typescript(tsProject))
.pipe(babel({
presets: ['es2015']
}));
if (isDevelopment) {
stream = stream.pipe(sourcemaps.write({sourceRoot: tsSrcPath}));
}
return stream.pipe(gulp.dest(tsBuildPath));
});
gulp.task('bundle', ['tsc'], function () {
var b = browserify({
entries: path.join(tsBuildPath, indexJsName),
debug: isDevelopment
});
var stream = b.bundle()
.pipe(source(indexJsName))
.pipe(buffer());
if (!isDevelopment) {
stream = stream.pipe(uglify());
}
return stream
.on('error', gutil.log)
.pipe(gulp.dest(distPath));
});
gulp.task('build', ['bundle'], function() {
return gulp.src(path.join(srcPath, indexHtmlName))
.pipe(inject(gulp.src([distIndexJsPath], {read: false}), {ignorePath: distRelativePath, addRootSlash: true}))
.pipe(gulp.dest(distPath));
});
You should pay attention to lines:
stream = stream.pipe(sourcemaps.write('', {sourceRoot: tsSrcPath})); - write inline source maps with sourceRoot pointing to your typescript sources path. Inline maps are written directly to .js files generated by tsc to build/dev/tsc.
debug: isDevelopment - in development environment make browserify generate his own source maps for resulting bundle build/dev/dist/index.js file so it will have source maps referencing .js files from build/dev/tsc which in turn have source maps referencing .ts files from src/typescript.
With this setup you will be able to see and debug .ts files in browser:
I faced similar issue when trying to debug my Angular2 app running in Chrome in Visual Studio Code (Using Debugger for Chrome extension)
I use gulp as my task runner and my setup is as follows:
Typescript files -> tsc -> intermediate es5 js -> browserify (plus uglify in production build) -> compiled bundle
My directory structure is as follows:
|- src
|- my .ts files here
|- main.ts - my entry file
|- dist
|- intermediate files go here
|- web
|- app.js - final bundle
|- app.js.map - final bundle map
|- gulpfile.js
gulpfile.js:
var gulp = require('gulp'),
tsc = require('gulp-typescript'),
browserify = require('browserify'),
uglify = require('gulp-uglify'),
sourcemaps = require('gulp-sourcemaps'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer');
gulp.task('tsc', [], () => {
return gulp.src(['src/**/*.ts'])
.pipe(sourcemaps.init())
.pipe(tsc({
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
}))
.pipe(sourcemaps.write(null, {
"sourceRoot": function(file) {
let parts = file.relative.split('\\');
let root = Array(parts.length + 1).join('../') + 'src';
return root;
}
}))
.pipe(gulp.dest('dist/'));
});
gulp.task('bundle', ['tsc'], () => {
let b = browserify({
entries: 'dist/main.js',
debug: true,
});
return b.bundle()
.pipe(source('app.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write('./', {
"sourceRoot": "../",
}))
.pipe(gulp.dest('web/'));
})
gulp.task('default', ['bundle']);
Explanation/reasoning:
For some reason browserify doesn't read and parse .js.map files linked in .js file (via special comment at the end) but it does when the source map is embedded in js file. So, by passing null instead of path to sourcemaps it will embed it at the end of generated .js file.
Next issue I noticed was that sourcemaps doesn't automatically follow directory structure (add '../' to sourceRoot when it goes to next directory level), so I made a quick function to complement this. Keep in mind that it only works on Windows - on Linux you'd have to change split character.
function(file) {
let parts = file.relative.split('\\'); // put '/' here on Linux
let root = Array(parts.length + 1).join('../') + 'src';
return root;
}
Certainly there is a way to detect correct path separator, I'm debugging only on Windows thus it's not important for my purposes.
I hope it helps someone, cause I've spent whole Sunday morning tracking down this problem.

Categories