Gulp - sourcemaps - strange behavior - javascript

In my gulpfile.js, I'm trying to minify and enable sourcemaps in a release task.
Based on a config variable, I'm trying to pipe further actions into the stream. The check for the condition is using gulp-if-else. My set of dependencies (only relevant ones) are below
var gulp = require('gulp');
var browserify = require('browserify');
//... elided
var through= require('through2');
var sourcemaps= require('gulp-sourcemaps');
var uglify = require('gulp-uglify');
var ifelse = require('gulp-if-else');
Here's the code that I'm having trouble with. If I keep three ifelse pipe calls individually (currently commented out), then the source is uglified and sourcemap is created as expected.
Repeating the condition didn't feel clean - so I tried replacing it with the minify function - and then the behavior is strange.
If I don't give relative path in sourcemaps.write then the js file has a inline sourcemap.
With a relative path, source is uglified, the js has a sourcemap comment pointing to app.js.map but app.js.map itself is never generated
var minify = function() {
var stream = through({objectMode:true})
stream
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write("./"));
return stream;
};
var bundledStream = through({objectMode:true});
bundledStream
// Report compile errors
.on('error', handleErrors)
.on('end', reportFinished)
// Use vinyl-source-stream to make the
// stream gulp compatible. Specifiy the
// desired output filename here.
.pipe(source(entry + '.js'))
// Specify the output destination
.pipe(buffer())
// uncommenting the following three lines works
//.pipe(ifelse(!config.debug,function() {return sourcemaps.init()}))
//.pipe(ifelse(!config.debug, uglify))
//.pipe(ifelse(!config.debug,function() {return sourcemaps.write("./")}))
// this works partially?!? but I don't know why. I'd like this version to work
.pipe(ifelse(!config.debug, minify))
.pipe(gulp.dest(config.destFolder));
I'm just picking up gulp (and node, really) and ran into this weird behavior that I can't seem to reason about. Would be a great help if someone can demystify it for me.
UPDATE: Complete gulpfile.js
UPDATE2: Added gulp-filelog. added pipe(filelog("minify")) and pipe(filelog("outer")) to the streams. filelog prints two files inside the fn but only one file outside. Why is the second file being dropped/ignored? What am I missing?
[09:43:24] [minify] [1] [E:\....\Dashboard\app.js.map]
[09:43:24] [minify] [2] [E:\....\app.js]
[09:43:24] [outer] [1] [E:\....\Dashboard\app.js]
[09:43:24] [outer] Found [1] files.
[09:43:24] [minify] Found [2] files.

Related

Gulp-Sourcemaps: Chrome DevTools incorrectly references source of compiled js

Example case:
I have 3 javascript files (Act.js, Body.js, SpriteSheets.js) that are being compiled together with gulp 4.0 and source mapped with gulp-sourcemaps 2.6.4. An error is thrown on line 43 of Body.js, but the console says line 194 of Act.js. Act.js has 151 lines, so if I click the Act.js:194 link in the Console it opens up Sources and highlights the last line (151) in Act.js.
All 3 javascript sources display correctly in the Sources tab and the console prints the correct class and function names, but the console always points to Act.js, even console logs that exist in the other files.
I don't know if this is a Chrome issue, a gulp-sourcemaps issue, or a problem with my code. Any ideas?
Gulp Compile Function:
const gulp = require('gulp');
const concat = require('gulp-concat');
const minify = require('gulp-minify');
const plumber = require('gulp-plumber');
const sourcemaps = require('gulp-sourcemaps');
....
const compileJS = (src, dest, name, include) => {
console.log(`js compile ${src}`);
let glob = [src];
if (include){
glob = include.first ? include.src.concat(glob) : glob.concat(include.src);
}
return gulp.src(glob)
.pipe(plumber())
.pipe(sourcemaps.init())
// concat all js in folder and name result as folder's name
.pipe(concat(name + '.js'))
.pipe(minify({
noSource: true,
ext: {
min: '.min.js'
}
}))
.pipe(sourcemaps.write('./', {
sourceMappingURLPrefix: src.replace('./', '').replace('src', '').replace('/**', '').replace('/*.js', '')
}))
.pipe(gulp.dest(dest));
};
I should note that SASS is also being compiled and sourced mapped and the sourcemap works correctly.
Looks like gulp-minify was the problem. It's an unsupported plug-in when it comes to using gulp-sourcemaps. Whoops! I should have read the documentation thoroughly. I switch to using gulp-uglify-es for minification.

Gulp watch logging that it ran, but my files aren't changing

Edit: Solved below
Here is my gulpfile
var gulp = require('gulp');
var sass = require('gulp-sass');
var minify = require('gulp-minify');
var concat = require('gulp-concat');
var sourcemaps = require('gulp-sourcemaps');
var allSassFiles = 'scss/**/*.scss';
var sassFile = gulp.src('./scss/style.scss');
var cssDest = '../wp-content/themes/Jupiter-child/uwkc_assets/css');
var sassify = function() {
return sassFile.pipe(sourcemaps.init())
.pipe(sass({outputStyle: 'compressed', onError: sass.logError}))
.pipe(gulp.dest(cssDest + '/prod'))
.pipe(sourcemaps.write())
.pipe(gulp.dest(cssDest));
};
gulp.task('doSass', sassify);
gulp.task('watchSass', function(){
return gulp.watch(allSassFiles, ['doSass']);
});
The sass glob is the variable "allSassFiles".
s
When I run the task "doSass" everything compiles fine. My css changes are represented in the browser.
However when I run the "watchSass" task things only change once, and then further changes are not reflected in the browser. It is like running only one occurrence of "doSass".
What is weird is that in my console I see the start and complete logs for doSass as if everything is running fine. However I don't see any changes being made to my css destination files.
I've tried many things, mixing up what I am returning, changing the glob syntax. Lots of things. For some reason I just can't get the darned thing to work.
Anyone see anything I might be missing? I have a feeling it has to do with what is returned with gulp-sass or sourcemaps, but I don't know enough about those to figure out the answer.
Thanks everyone!
This is what I figured out:
I needed to create a new gulp.src() object every time I ran sassify in the watch runtime apparently. Also I hope I am using those terms right.
I re-wrote:
return sassFile.pipe(sourcemaps.init())
in the sassify function to:
return gulp.src('./scss/style.scss').pipe(sourcemaps.init())
This did the trick. It makes sense to me that watch would re-use the same src object referenced in the variable sassFile that didn't represent a changed scss file.

How to set up gulp to bundle several files into one?

This seems like a very simple question, but spent the last 3 hours researching it, discovering it can be slow on every save on a new file if not using watchify.
This is my directory tree:
gulpfile.js
package.json
www/
default.htm
<script src="toBundleJsHere/file123.js"></script>
toBundletheseJs/
componentX/
file1.js
componentY/
file2.js
componentZ/
file3.js
toPutBundledJsHere/
file123.js
Requirements.
On every creation or save of a file within the folder toBundleTheseJs/ I want this file to be rebundled into toBundleJsHere/
What do I need to include in my package.json file?
And whats the minimum I need to write into my gulp file?
This should be as fast as possible so think I should be using browserify and watchify. I want to understand the minimum steps so using package manager like jspm is overkill a this point.
thanks
First you should listen to changes in the desired dir:
watch(['toBundletheseJs/**/*.js'], function () {
gulp.run('bundle-js');
});
Then the bundle-js task should bundle your files. A recommended way is gulp-concat:
var concat = require('gulp-concat');
var gulp = require('gulp');
gulp.task('bundle-js', function() {
return gulp.src('toBundletheseJs/**/*.js')
.pipe(concat('file123.js'))
.pipe(gulp.dest('./toPutBundledJsHere/'));
});
The right answer is: there is no legit need for concatenating JS files using gulp. Therefore you should never do that.
Instead, look into proper JS bundlers that will properly concatenate your files organizing them according to some established format, like commonsjs, amd, umd, etc.
Here's a list of more appropriate tools:
Webpack
Rollup
Parcel
Note that my answer is around end of 2020, so if you're reading this in a somewhat distant future keep in mind the javascript community travels fast so that new and better tools may be around.
var gulp = require('gulp');
var concat = require('gulp-concat');
gulp.task('js', function (done) {
// array of all the js paths you want to bundle.
var scriptSources = ['./node_modules/idb/lib/idb.js', 'js/**/*.js'];
gulp.src(scriptSources)
// name of the new file all your js files are to be bundled to.
.pipe(concat('all.js'))
// the destination where the new bundled file is going to be saved to.
.pipe(gulp.dest('dist/js'));
done();
});
Use this code to bundle several files into one.
gulp.task('scripts', function() {
return gulp.src(['./lib/file3.js', './lib/file1.js', './lib/file2.js']) //files separated by comma
.pipe(concat('script.js')) //resultant file name
.pipe(gulp.dest('./dist/')); //Destination where file to be exported
});

gulp reference to original source after minification

Once magnification is done, and let's say I had some bug,
and I want the console of browser to point me to original source so I could see the problem clearly instead of minified lines of code.
Script.js + many more files (concatenation plus minification)
var somevar = 4
console.log(someVar) //misspelled var name
console will take me to this file
script.min.js
var somevar=4;console.log(someVar)
I've seen some .map files with some js libraries, don't know how they work.
Can someone advise how can the console of a browser can refer to original source in case of an error /problem in a minified file.
gulp.task("app", function() {
var app = [
"js/libs/abc.js",
"js/file1.js",
"js/file2.js"
];
gulp.src(app)
.pipe(concat("app.min.js"))
.pipe(uglify())
.pipe(gulp.dest("js"))
});
Install this to your dev dependencies
https://www.npmjs.com/package/gulp-sourcemaps
gulp.src(app)
.pipe(concat("app.min.js"))
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write("./"))
.pipe(gulp.dest("js"))
Make sure the generated JavaScript file, example.js, has the source mapping url at the end as follows:
//# sourceMappingURL=example.js.map

Removing gulp.src files after gulp.dest?

I have a scenario where a client of mine wants to drop LESS files into a src directory (via FTP), and for them to be automatically outputted as CSS to a build directory. For each LESS file, once its resultant CSS file is created, it should be removed from the src directory. How can I do this with Gulp?
My current gulpfile.js is:
var gulp = require("gulp");
var watch = require("gulp-watch");
var less = require("gulp-less");
watch({ glob: "./src/**/*.less" })
.pipe(less())
.pipe(gulp.dest("./build"));
This successfully detects new LESS files being dropped into the src directory and outputs CSS files into build. But it doesn't clean up the LESS files afterwards. :(
Use gulp-clean.
It will clean your src directory once you piped it. Of course, test it on a backup with different settings, and if you can't manage to make it work properly, don't hesitate to make a second task and use some task dependency to run the clean after your less task is completed.
If I'm right, when I tried to pipe gulp-clean after the gulp.dest, something went wrong, so I got another way to do this, here's an example with task dependency.
var gulp = require('gulp'),
less = require('gulp-less'),
clean = require('gulp-clean');
gulp.task('compile-less-cfg', function() {
return gulp.src('your/less/directory/*.less')
.pipe(less())
.pipe('your/build/directory'));
});
gulp.task('remove-less', ['less'], function(){
return gulp.src('your/less/directory)
.pipe(clean());
});
That's for the not-watching task. Then, you should use a watch on the *.less files, but you should get task remove-less running instead of less. Why ? Because of task dependency.
When you'll call the remove-less task, it will only start once the less task is complete. That way, the files will only be deleted once your less compilation is over, and not in the middle of it throwing errors.
It may not be the perfect method to get this working as I'm not an expert, but it's a safe and working solution for you to use. Also it's pretty clear to understand IMO.
gulp-clean is deprecated. Use the npm module del.
npm install --save-dev del
Here is how you should use it.
var gulp = require('gulp');
var del = require('del');
gulp.task('clean:mobile', function () {
return del([
'dist/report.csv',
// here we use a globbing pattern to match everything inside the `mobile` folder
'dist/mobile/**/*',
// we don't want to clean this file though so we negate the pattern
'!dist/mobile/deploy.json'
]);
});
gulp.task('default', ['clean:mobile']);

Categories