Uncaught ReferenceError: {Class} is not defined - javascript

Sorry if this question has already been answered, but there are so many post with this error name and a different context, that I could find the answer to this particular case.
I am using Javascript ES6 modules, and I am trying to 'compile' all my javascript files into one minified file. I am using Gulp for that. I have 3 js files (gulpfiles, an index file that require ma class, and the class file). I also have an HTML file to test the minified js file. Here is what my project looks like :
// File : gulpfile.js
const { src, dest, task, watch, series, parallel } = require('gulp');
var uglify = require('gulp-uglify')
var babelify = require('babelify')
var browserify = require('browserify')
var source = require('vinyl-source-stream')
var buffer = require('vinyl-buffer')
var rename = require('gulp-rename')
const jsSRC = './classes/'
const jsDEST = './output/'
const jsFILES = ['index.js']
function js(done) {
jsFILES.map( function (entry) {
return browserify({
entries: [jsSRC + entry]
})
.transform( babelify, { presets: ['#babel/preset-env'] } )
.bundle()
.pipe( source( entry) )
.pipe( rename({ extname: '.min.js'}) )
.pipe( buffer() )
.pipe( uglify() )
.pipe( dest( jsDEST ))
})
done()
}
task('js',js)
task('default', parallel(js))
// File : classes/Logger.js
class Logger{
constructor(msg){
console.log(msg)
}
}
export default Logger ;
// File : classes/index.js
import Logger from './Logger.js'
exports = { Logger }
var l = new Logger('Hello') // This should log 'Hello' in the console
// File : demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Demo</title>
</head>
<body>
<script src="./output/index.min.js"></script>
</body>
</html>
(I used the command npm install #babel/core #babel/preset-env babelify browserify gulp gulp-cli gulp-rename gulp-uglify vinyl-buffer vinyl-source-stream to install all the dependecies)
So, here is the problem. When I open the HTML file in a browser, I get the 'Hello' displayed in the console, because it is triggered by the var l = new Logger('Hello') line in the index.js file. But if I type the exact same thing in the console, I get this error Uncaught ReferenceError: Logger is not defined
This is probably a noob mistake. Do someone knows why I cannot use the Logger class from my page with the minified js ? And what can I do to make my class usable from the minified js file ?
Thank you !
(If there is a problem with the question, duplicated question or whatever, just tell me and I will close/delete it)

Related

Trouble with splitting gulpfile.js into multiple files in Gulp 4

I am a beginner to Javascript and Gulp. Am learning this based on a udemy course in which Gulp 3 is being used, and I've been looking at docs to convert the code to Gulp 4. It's been fun so far since I am learning more when I am doing the conversions myself, but am stuck on this one. Wonder if you guys can offer some advice.
Issue: When I split the gulpfile.js into separate files to organise my files better, it starts throwing errors. Code below.
styles.js
var gulp = require('gulp'),
postcss = require('gulp-postcss'),
autoprefixer = require('autoprefixer'),
cssvars = require('postcss-simple-vars'),
nested = require('postcss-nested'),
cssImport = require('postcss-import');
function styles(cb) {
return gulp.src('./app/assets/styles/styles.css')
.pipe(postcss([cssImport, cssvars, nested, autoprefixer]))
.pipe(gulp.dest('./app/temp/styles'));
cb();
}
exports.styles = styles;
watch.js
var gulp = require('gulp'),
browserSync = require('browser-sync').create();
function cssInject(cb) {
return gulp.src('./app/temp/styles/styles.css')
.pipe(browserSync.stream());
cb();
}
function browserSyncReload(cb) {
browserSync.reload();
cb();
}
function watch(cb) {
browserSync.init({
notify: false,
server: {
baseDir: "app"
}
});
watch('./app/index.html', browserSyncReload);
watch('./app/assets/styles/styles.css', gulp.series(cssInject, styles));
cb();
}
exports.browserSyncReload = browserSyncReload;
exports.watch = watch;
gulpfile.js
var stylesTasks = require('./gulp/tasks/styles.js'),
watchTasks = require('./gulp/tasks/watch.js');
exports.watch = watchTasks.watch;
exports.styles = stylesTasks.styles;
exports.browserSyncReload = watchTasks.browserSyncReload;
When I run "gulp watch", this is what I get.
error
$ gulp watch
[21:14:28] Using gulpfile ~/Projects/travel-site/gulpfile.js
[21:14:28] Starting 'watch'...
internal/async_hooks.js:195
function emitInitNative(asyncId, type, triggerAsyncId, resource) { ^
RangeError: Maximum call stack size exceeded
(Use `node --trace-uncaught ...` to show where the exception was thrown)
I found another post with almost identical code, but with a different error - which happened to be one of the errors i was getting earlier as well, and have followed the solution mentioned in that post - and that's when I get this error. Here's the link to the post.
Any help is much appreciated. Thanks for your time.
I have a full article that shows many how to regarding going from gulp3 to gulp4, I think you are going to find everything you need there
But basically, I think you need to take a look at these modules :
gulp-task-loader-recursive
gulp4-run-sequence
require-dir
Then, from a gulp.js perspective, you can end up with something like this :
// gulpfile.js
global.config = require('./gulp/config/config.json');
require('events').EventEmitter.prototype._maxListeners = 1000;
require('require-dir')('./gulp/tasks/styles');
require('require-dir')('./gulp/tasks/watch');
//... etc ...
So you would be able to then create your styles task and export it :
var gulp = require('gulp'),
postcss = require('gulp-postcss'),
autoprefixer = require('autoprefixer'),
cssvars = require('postcss-simple-vars'),
nested = require('postcss-nested'),
cssImport = require('postcss-import');
function styles(cb) {
return gulp.src('./app/assets/styles/styles.css')
.pipe(postcss([cssImport, cssvars, nested, autoprefixer]))
.pipe(gulp.dest('./app/temp/styles'));
cb();
}
const stylesTask = task('styles', styles);
exports.stylesTask = stylesTask;
You can then validate its recognized by gulp :
gulp --tasks
If you correctly see your styles tasks, you should now be able to run your task by running :
gulp styles
Repeat those steps for the watch task.
Answering my own question feels wierd, but I found the solution after playing with it for couple of days. See below.
I needed to import styles into watch.js, and not gulpfile.js. That was my first mistake. To do this, I added the below line to watch.js
var styles = require('./styles').styles;
Then my gulpfile.js only needed two lines
gulpfile.js
var watchTask = require('./gulp/tasks/watch').watch;
exports.default = watchTask;
I also removed the variable gulp, instead created variables for src and dest. So, the rest of the code looked like below.
styles.js
var {src, dest} = require('gulp'),
postcss = require('gulp-postcss'),
autoprefixer = require('autoprefixer'),
cssvars = require('postcss-simple-vars'),
nested = require('postcss-nested'),
cssImport = require('postcss-import');
const styles = function (cb) {
return src('./app/assets/styles/styles.css')
.pipe(postcss([cssImport, cssvars, nested, autoprefixer]))
.pipe(dest('./app/temp/styles'));
cb();
}
exports.styles = styles;
watch.js
var styles = require('./styles').styles;
var {src, series, watch} = require('gulp'),
browserSync = require('browser-sync').create();
const cssInject = function (cb) {
return src('./app/temp/styles/styles.css')
.pipe(browserSync.stream());
cb();
}
const reload = function (cb) {
browserSync.reload();
cb();
}
const watchTask = function (cb) {
browserSync.init({
notify: false,
server: {
baseDir: "app"
}
});
watch('./app/index.html', reload);
watch('./app/assets/styles/styles.css', series(cssInject, styles));
cb();
}
exports.watch = watchTask;
Hence resolved! hope this helps someone else.

gulp-load-plugins.sourcemaps.init() TypeError: Cannot read property 'init' of undefined

I'm trying to adapt a gulp file to my purposes and I'm running into issues. I only care about one task:
gulp.task('js:browser', function () {
return mergeStream.apply(null,
Object.keys(jsBundles).map(function(key) {
return bundle(jsBundles[key], key);
})
);
});
It is using browserify to condense my bundle into a usable single file. It uses these two methods and this object:
function createBundle(src) {
//if the source is not an array, make it one
if (!src.push) {
src = [src];
}
var customOpts = {
entries: src,
debug: true
};
var opts = assign({}, watchify.args, customOpts);
var b = watchify(browserify(opts));
b.transform(babelify.configure({
stage: 1
}));
b.transform(hbsfy);
b.on('log', plugins.util.log);
return b;
}
function bundle(b, outputPath) {
var splitPath = outputPath.split('/');
var outputFile = splitPath[splitPath.length - 1];
var outputDir = splitPath.slice(0, -1).join('/');
console.log(outputFile);
console.log(plugins);
return b.bundle()
// log errors if they happen
.on('error', plugins.util.log.bind(plugins.util, 'Browserify Error'))
.pipe(source(outputFile))
// optional, remove if you don't need to buffer file contents
.pipe(buffer())
// optional, remove if you dont want sourcemaps
.pipe(plugins.sourcemaps.init({loadMaps: true})) // loads map from browserify file
// Add transformation tasks to the pipeline here.
.pipe(plugins.sourcemaps.write('./')) // writes .map file
.pipe(gulp.dest('build/public/' + outputDir));
}
var jsBundles = {
'js/polyfills/promise.js': createBundle('./public/js/polyfills/promise.js'),
'js/polyfills/url.js': createBundle('./public/js/polyfills/url.js'),
'js/settings.js': createBundle('./public/js/settings/index.js'),
'js/main.js': createBundle('./public/js/main/index.js'),
'js/remote-executor.js': createBundle('./public/js/remote-executor/index.js'),
'js/idb-test.js': createBundle('./public/js/idb-test/index.js'),
'sw.js': createBundle(['./public/js/sw/index.js', './public/js/sw/preroll/index.js'])
};
When I run the gulp task js:bower I get the following error coming from the the .pipe(plugins.sourcemaps.init({loadMaps: true})) expression:
TypeError: Cannot read property 'init' of undefined
I know that the lines are optional and I can just comment them out, but I do want them. When I run the code in the example file it works properly, when I run it in my gulp file it gives me the error. Any suggestions on what I might be missing? Thanks!
gulp-load-plugins analyzes the contents of your package.json file to find out which Gulp plugins you have installed. Make sure that gulp-sourcemaps is among the "devDependencies" defined there. If not run
npm install --save-dev gulp-sourcemaps
There's a small chance that your problem is related to lazy loading the sourcemaps plugin. If the above doesn't help try requiring gulp-load-plugins like this:
var plugins = require('gulp-load-plugins')({lazy:false});

gulp-jscs seems to be unable to detect the config (.jscsrc) file, but normal jscs can from the command line

When I run "gulp style" from the command line, Gulp runs, and, subsequently, gulp-jscs runs, but the latter seems to be unable to detect the rules defined in the jscs config file (.jscsrc). But, if I run jscs from the command line, then jscs does detect the config file's rules. Any idea what the deal could be?
Here's my gulp file:
(function() {
"use strict";
var gulp = require("gulp");
var jshint = require("gulp-jshint");
var jscs = require("gulp-jscs");
var jsFiles = ["*.js", "src/**/*.js"];
gulp.task("style", function () {
console.log("Running the style task.");
return gulp.src(jsFiles)
.pipe(jshint())
.pipe(jshint.reporter("jshint-stylish", {
verbose: true
}))
.pipe(jscs({configPath: "./.jscsrc"}));
});
})();
You need a reporter (just like jshint has one):
var gulp = require("gulp");
var jshint = require("gulp-jshint");
var jscs = require("gulp-jscs");
var jsFiles = ["*.js", "src/**/*.js"];
gulp.task("style", function () {
console.log("Running the style task.");
return gulp.src(jsFiles)
.pipe(jshint())
.pipe(jshint.reporter("jshint-stylish", {
verbose: true
}))
.pipe(jscs({configPath: "./.jscsrc"}))
.pipe(jscs.reporter()); // << this line here
});
Other notes, (if you are running from cmd), Gulpfile.js you don't need to wrap it into anonymous function or use 'use strict'.
Example output:
[13:53:30] Using gulpfile C:\del\so\gulpjscs\Gulpfile.js
[13:53:30] Starting 'style'...
Running the style task.
[13:53:31] gulp-debug: Gulpfile.js
[13:53:31] gulp-debug: index.js
[13:53:31] gulp-debug: 2 items
Comments must start with a lowercase letter at C:\del\so\gulpjscs\index.js :
1 |// Invalid
--------^
2 |// valid
3 |
1 code style error found.
[13:53:31] Finished 'style' after 187 ms
If you're not sure how will current path ./ be taken into account you can always use path module to resolve, for example:
var path = require('path');
var configPath = path.resolve(path.join(__dirname, '.jscsrc'))

How do you use browserify in a Gulp task?

I'm pretty new to Gulp, but by following this tutorial I set up a Gulp task that is meant to browserify javascript files in a particular directory and pipe them to a different directory - pretty simple. I've looked a few other tutorials, but this method seemed to be the most concise. Here is my code:
var gulp = require('gulp');
var browserify = require('browserify');
var transform = require('vinyl-transform');
gulp.task('js', function() {
var browserified = transform(function(filename) {
return browserify(filename).bundle();
});
return gulp.src(['./public/js/src/**/*.js'])
.pipe(browserified)
.pipe(gulp.dest('./public/js/dist'));
});
The above code is very similar to many other implementations of this sort I've seen, but when I try running it with gulp js, it produces the following error:
[15:47:13] Using gulp file
~/development/launchpad/workshop/gulpfile.js
[15:47:13] Starting 'js'...
_stream_readable.js:540
var ret = dest.write(chunk);
^
TypeError: undefined is not a function
at Producer.ondata (_stream_readable.js:540:20)
at Producer.emit (events.js:107:17)
at Producer.Readable.read (_stream_readable.js:373:10)
at flow (_stream_readable.js:750:26)
at resume_ (_stream_readable.js:730:3)
at _stream_readable.js:717:7
at process._tickCallback (node.js:355:11)
Does anyone know what might cause this error?
(As a side note, I'd like to look at the files from the stack trace to try to figure out what is going on here, but searching for _stream_readable.js in Spotlight yields about 20 files of that name, all seemingly Node modules. Is there a way to determine the full path of a file in a stack trace?)
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
gulp.task('browserify', function() {
return browserify('lib/front/app.js')
.bundle()
//Pass desired output filename to vinyl-source-stream
.pipe(source('bundle.js'))
// Start piping stream to tasks!
.pipe(gulp.dest('public/build/'));
});
If you want browserify to work with gulp. dest and create a file where we specify it via .pipe (gulp.dest ('src/js')),
then you need to download vinyl-source-stream and throw it in .pipe(source('bundle.js')),
but actually in browserify, namely the bundle method accepts callback and neither dest nor source is needed
browserify({
entries: jsFile,
basedir: "src/js/dev",
debug: true,
})
.transform(babelify, {
presets: ['#babel/preset-env'],
})
.bundle((err, buffer) => {
let event = new EventEmitter();
if (err) {
event.emit('error',err)
}
else {
let data = minify(buffer.toString(), {}).code;
fs.createWriteStream('./src/js/bundle.js').write(data)
console.dir(222);
bs.reload()
}
})
Unfortunately, this is an issue with browserify/gulp, and there's nothing that vinyl-transform can do. The solution is to use vinyl-source-stream and vinyl-buffer:
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var glob = require('node-glob');
gulp.task('browserify', function (cb) {
glob('./src/**/*.js', {}, function (err, files) {
var b = browserify();
files.forEach(function (file) {
b.add(file);
});
b.bundle().
.pipe(source('output.js'))
.pipe(gulp.dest('./dist'));
cb();
})
});
More information here.

How to perform a transform on npm module using browserify

By default, browserify does not perform transforms on modules included from node_modules, i.e. with no path.
I made a quick github repo that illustrates it here. The index.js file that gets browserified looks like this:
var fs = require('fs');
var testmodule = require('testmodule');
var trg1 = document.getElementById("target1");
var trg2 = document.getElementById("target2");
trg1.innerHTML = fs.readFileSync(__dirname+"/something.txt");
trg2.innerHTML = testmodule();
testmodule looks like this:
var fs = require('fs');
exports = module.exports = function() {
return fs.readFileSync(__dirname+'/data.txt');
}
Using the brfs transform module, I want to be able to inline both calls to fs.readFileSync, but when I run browserify index.js -t brfs -o bundle.js, only the call in my main project gets inlined. Here is the bundle.js result:
;(function(e,t,n){function r(n,i){if(!t[n]){if(!e[n]){var s=typeof require=="function"&&require;if(!i&&s)return s(n,!0);throw new Error("Cannot find module '"+n+"'")}var o=t[n]={exports:{}};e[n][0](function(t){var i=e[n][1][t];return r(i?i:t)},o,o.exports)}return t[n].exports}for(var i=0;i<n.length;i++)r(n[i]);return r})({1:[function(require,module,exports){
// nothing to see here... no file methods for the browser
},{}],2:[function(require,module,exports){
var fs = require('fs');
var testmodule = require('testmodule');
var trg1 = document.getElementById("target1");
var trg2 = document.getElementById("target2");
trg1.innerHTML = "This is data from a file in the main project folder"; // TRANSFORMED
trg2.innerHTML = testmodule();
},{"fs":1,"testmodule":3}],3:[function(require,module,exports){
(function(__dirname){var fs = require('fs');
exports = module.exports = function() {
return fs.readFileSync(__dirname+'/data.txt'); // NO TRANSFORM
}
})("/node_modules/testmodule")
},{"fs":1}]},{},[2])
;
Got some help from substack (author of browserify) on this one. To specify if a module outside of a project requires transformations, you need to specify a browserify.transform array in your package.json. So for the example I gave above, the package.json file in the testmodule directory looks like this:
{
"name":"testmodule",
"version":"0.0.0",
"browserify": {
"transform": ["brfs"]
},
"main": "index.js"
}
You can also use browserify -g brfs instead of browserify -t brfs. g is a global transform (which applies to dependencies)

Categories

Resources