How to load sourcemaps with uglifyjs2 and Ionic? - google-chrome

For my Ionic app, I am using some gulp tasks to minify the Javascript code. Uglifyjs2 minifies the code:
gulp.task('uglify', () => {
gulp.src(paths.uglify)
.pipe(uglify('app.min.js', {
outSourceMap: true
}))
.pipe(gulp.dest('./www/dist/js-uglify'));
});
This generates the files
www
| dist
| | js-uglify
| | | app.min.js
| | | app.min.js.map
app.min.js thus ends with //# sourceMappingURL=app.min.js.map
In my index.html I have the following reference:
<script src="dist/js-uglify/app.min.js"></script>
When I build and run my app via ionic run the file app.min.js is loaded. However, the sourcemap is missing. Chrome seems to be set up properly (the option Enable JavaScript source maps is set).
How can I tackle this problem? Should the Network list of transmitted files contain an entry for the source map? Can I somehow manually force Chrome to load the map?

I am not familiar with uglifyjs, but a quick look at some ionic software that uses it online suggests that maybe you did not configure your flags correctly. It looks like you are meant to run
uglifyjs [input files] [options]
Using the option --source-map output.js.map.
Ok, another thing which may be relevant: according to the gruntjs GitHub, that sourceMappingURL flag no longer works.
Version 3.x introduced changes to configuring source maps
...
sourceMappingURL - This is calculated automatically now sourceMapPrefix - No longer necessary for the above reason ...
sourceMap - Only accepts a Boolean value. Generates a map with a default name for you sourceMapRoot - The location of your sources is now calculated for you when sourceMap is set to true but you can set manual source root if needed
So maybe instead of using sourceMappingURL you should just set the boolean to true? Hope this helps!

gulp-uglifyjs is deprecated. It's possible that your sourcemaps are not being created properly.
Current best practice is to use the following modules to uglify/concat/sourcemap your code:
gulp-uglify
gulp-concat
gulp-sourcemaps
Example:
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var sourcemaps = require('gulp-sourcemaps');
gulp.task('build-js', function () {
return gulp.src('app/**/*.js')
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(concat('app.min.js'))
.pipe(sourcemaps.write('.', { includeContent: false, sourceRoot: '../app' }))
.pipe(gulp.dest('dist'));
});
See this related answer for an explanation of why these gulp modules work better.
Also, in Chrome, the app.min.js.map file does not show up in the Network tab. You'll know if your sourcemaps have been loaded if they show up in the Sources tab in an orange colored folder.

Related

gulp.src is not a function

I want to use gulp to concatenate and then minimize my Javascript files.
But I can not even get the first part to run. I keep getting an error that says "gulp.src is not a function".
I have gulp installed both globally and in the directory I am working with.
And in a different directory I am using gulp to compile my Sass files just fine.
What is wrong with this task?
'use strict';
var gulp = require('gulp'),
concat = require('gulp-concat');
/* Concatenate Javascript files needed to be referenced in the header. */
gulp.task("concatHeaderJS", function() {
gulp.scr([ // what to concat, can also be strings
'inc/js/zebra_dialog.js', // order matters
'inc/js/gx-zebra_dialog.js',
'inc/js/gx-sidebar-nav.js'])
.pipe(concat("header_files_concat.js")) // where to send result
.pipe(gulp.dest("inc/js")); // folder for result to end in
});
Change gulp.scr to gulp.src. It's the typo life.

Rebuild all files if template changes

I'm using gulp to convert markdown files to HTML, and using the gulp-watch plugin (not the gulp.watch API function) to rebuild files if they change. Works great!
gulp.task('markdown', function () {
gulp.src('src/**/*.md')
.pipe(watch('src/**/*.md'))
.pipe(markdown())
.pipe(template('templates/md.tpl'))
.pipe(gulp.dest('dist'));
});
The problem is that the pipeline src is the markdown files, but within the pipeline I also reference a template file. If that template changes, all the markdown files need to be rebuilt. Is there a way to express that dependency in gulp/gulp-watch?
I tried using gulp.watch (the API function) to watch the template and run the 'markdown' task if it changes ...
gulp.watch('templates/md.tpl', ['markdown']);
... but that didn't work. Nothing happens. I assume having gulp-watch in the pipeline prevents it from doing anything.
I guess I could create a two tasks, one with gulp-watch and one without, and use the one without to force a full rebuild. I'd rather not, because then it becomes an ongoing problem to keep the two in sync.
Is there a better way?
I guess I could create a two tasks, one with gulp-watch and one without, and use the one without to force a full rebuild. I'd rather not, because then it becomes an ongoing problem to keep the two in sync.
Remember, gulp is just JavaScript.
Simply write a function that constructs the stream with or without the watch() step depending on a parameter that you pass. The gulp-if plugin let's you write something like this in a very concise way (although it's not necessary and could be done without it).
Here's how I would do it:
var gulpIf = require('gulp-if');
function processMarkdown(opts) {
gulp.src('src/**/*.md')
.pipe(gulpIf(opts.watch, watch('src/**/*.md')))
.pipe(markdown())
.pipe(template('templates/md.tpl'))
.pipe(gulp.dest('dist'));
}
gulp.task('markdown', function() {
processMarkdown({watch: true});
watch('templates/md.tpl', function() {
processMarkdown({watch: false});
});
});
You can specify gulp src as an array, too:
gulp.src(['src/**/*.md', 'templates/md.tpl'])

Using Gulp and minified CSS/JS

I recently started using Gulp to autoprefix, minifycss and minify my JS. Right now, all the files that get autoprefixed, minified are sitting in a dist folder. Is there a way I can point my html file to these minified versions without manually retyping the following :
<script src="js/custom.js"></script>
to :
<script src="dist/custom.min.js"></script>
back and forth?
Right now, when I develop, I edit about 5 to 10 css and JS files but when I edit them, it's obviously in the unminified, unautoprefixed version. I'm sure that's not how developers do it so I'm guessing there's a step that I'm missing...
You should look at using source maps. From that article:
Basically it's a way to map a combined/minified file back to an unbuilt state. When you build for production, along with minifying and combining your JavaScript files, you generate a source map which holds information about your original files. When you query a certain line and column number in your generated JavaScript you can do a lookup in the source map which returns the original location. Developer tools (currently WebKit nightly builds, Google Chrome, or Firefox 23+) can parse the source map automatically and make it appear as though you're running unminified and uncombined files.
gulp-sourcemaps is what you will need to use. You don't mention which gulp plugins you are using, but there's a good chance that they have support for source maps.
Here's a simple example of how you would use it:
var gulp = require('gulp');
var minify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
gulp.task('minify', function() {
gulp.src('src/*.js')
.pipe(sourcemaps.init()) // Initialize the source maps.
.pipe(minify()) // Do your minification, concatenation, etc.
.pipe(sourcemaps.write()) // Write the source maps.
.pipe(gulp.dest('dist')); // Write the minified files.
});
Just make sure that the original unminified files are also being server by your web server so that the browser can download them.
This also has the added advantage that when you are testing your webpage at development time, you're actually running the minified code that you will end up deploying.
You can try the gulp-replace plugin, write a task, something like this:
var replace = require('gulp-replace')
gulp.task('adoptDist', function() {
return gulp.src(paths.dest + '/www/**/*.html', { base: paths.dest })
.pipe(replace(/src="js\/(.+?)\.js"/g, function(match, $1) {
return 'src="dist/' + $1 + '.min.js"'
}))
.pipe(gulp.dest(paths.dest))
});

issue with piping gulp-watch into gulp-ruby-sass

Maybe I'm an idiot, but I cannot get the combination of gulp-watch and gulp-ruby-sass to work. Any suggestions are hugely welcome. For all the following, the require() calls in my gulpfile.js look like this:
var gulp = require('gulp');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var sass = require('gulp-ruby-sass');
The next bit is what I can't get working. When I change a file I see the output from gulp-watch stating the file was changed, but no output from gulp-ruby-sass and the file isn't written to the dist/ directory.
gulp.task('test-watch', function() {
return watch('./**/*.scss')
.pipe(plumber())
.pipe(sass())
.pipe(gulp.dest('dist/'));
});
Yet I know both gulp-watch and gulp-ruby-sass are setup correctly individually because they work fine on their own:
// writes updated files to dist/ successfully
gulp.task('test-watch', function() {
return watch('./**/*.scss')
.pipe(plumber())
.pipe(gulp.dest('dist/'));
});
// compiles into css and writes to dist/ directory successfully
gulp.src('./**/*.scss')
.pipe(sass())
.pipe(gulp.dest('dist/'));
So what's my problem? Even more vexing, the example above that does not work actually comes from the gulp-watch readme, so should be something that's supported. Any advice is very welcome!
It seems the "solution" is to use gulp-sass for this instead of gulp-ruby-sass.
I still do not know why gulp-ruby-sass doesn't support this since piping the results of gulp.src() into and out of gulp-ruby-sass works like a champ, but it doesn't. I wonder if gulp-watch returns a different file format than gulp.src that gulp-ruby-sass can't handle but gulp-sass can.
If anyone knows how to make this work for gulp-ruby-sass since that's supposedly more fully-featured, please do share.

Gulp + gulp-compass compile, unchanged files being reinjected to BrowserSync

I've got a Gulp task setup to compile .scss files with compass, and also another task running which injects changed CSS into the browser via BrowserSync.
gulp.task('browser-sync', function () {
var options = {
files: './public/css/**/*.css',
proxy: ecs_domain,
port: 3000
};
browserSync(options);
});
gulp.task('compass', function () {
gulp.src('./scss/**/*.scss')
.pipe(compass({
css: cssOutput,
sass: 'scss'
}))
.pipe(gulp.dest(cssOutput))
.pipe(reload({stream: true}));
});
The problem I'm finding is that when compass is run, I get output like in the following snippet:
identical public/css/main.css
[BS] File changed: public/css/main.css
Even though the file main.css hasn't changed, compass somehow touches it, making BrowserSync think it has changed, meaning that even if only one file changes, the entire set of CSS files are re-injected to the browser.
Is there a way to leave the identical/unchanged *.css files un-touch-ed so BrowserSync can only load the files that actually changed?
We have quite a few files and makes the whole process quite slow.
I've found a partial solution. I installed gulp-changed and redirected output from compass to a temporary .out folder. Then created a watch to run gulp-changed when files differ from public/css and .out version using the following task:
gulp.task('copy-changed-css', function () {
gulp.src('.out/**/*.css')
.pipe(changed('public/css', {hasChanged: changed.compareSha1Digest}))
.pipe(gulp.dest('public/css'))
});