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.
Related
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.
Im trying to use gulp and jscs to prevent code smell. I also want to use watch so that this happens when ever a change is made. The problem I'm running into is jscs is modify the source file that is being watched. This causes gulp to go into an infinite loop of jscs modifying the file and then watch seeing the change and firing off jscs again and again and again ...
const gulp = require('gulp');
gulp.task('lint', function() {
return gulp.src('/src/**/*.js')
.pipe(jscs({
fix: true
}))
.pipe(jscs.reporter())
.pipe(gulp.dest('/src'));
});
gulp.task('watch', function() {
gulp.watch('/src/**/*.js', ['lint']);
});
It's generally a bad idea to override source files from a gulp task. Any Editors/IDEs where those files are open might or might not handle that gracefully. It's generally better to write the files into a separate dist folder.
That being said here's two possible solutions:
Solution 1
You need to stop the gulp-jscs plugin from running a second time and writing the files again, thus preventing the infinite loop you're running into. To achieve this all you have to do is add gulp-cached to your lint task:
var cache = require('gulp-cached');
gulp.task('lint', function() {
return gulp.src('/src/**/*.js')
.pipe(cache('lint'))
.pipe(jscs({
fix: true
}))
.pipe(cache('lint'))
.pipe(jscs.reporter())
.pipe(gulp.dest('/src'));
});
The first cache() makes sure that only files on disk that have changed since the last invocation of lint are passed through. The second cache() makes sure that only files that have actually been fixed by jscs() are written to disk in the first place.
The downside of this solution is that the lint task is still being executed twice. This isn't a big deal since during the second run the files aren't actually being linted. gulp-cache prevents that from happening. But if you absolutely want to make sure that lint is run only once there's another way.
Solution 2
First you should use the gulp-watch plugin instead of the built-in gulp.watch() (that's because it uses the superior chokidar library instead of gaze).
Then you can write yourself a simple pausableWatch() function and use that in your watch task:
var watch = require('gulp-watch');
function pausableWatch(watchedFiles, tasks) {
var watcher = watch(watchedFiles, function() {
watcher.close();
gulp.start(tasks, function() {
pausableWatch(watchedFiles, tasks);
});
});
}
gulp.task('watch', function() {
pausableWatch('/src/**/*.js', ['lint']);
});
In the above the watcher is stopped before the lint task starts. Any .js files written during the lint task will therefore not trigger the watcher. After the lint task has finished, the watcher is started up again.
The downside of this solution is that if you save a .js file while the lint task is being executed that change will not be picked up by the watcher (since it has been stopped). You have to save the .js file after the lint task has finished (when the watcher has been started again).
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))
});
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.
I have the following code fragment in my gulpfile.
gulp.task('static', function() {
return gulp.src(['./src/**', '!./src/js/**', '!./src/js/', '!./src/scss/', '!./src/scss/**'])
.pipe(gulp.dest(outputDir + '/'))
});
gulp.task('watch', function() {
gulp.watch(['./src/**', '!./src/js/**', '!./src/js/', '!./src/scss/', '!./src/scss/**'], ['static']);
});
gulp.task('dev', ['static']);
gulp.task('default', ['watch', 'dev']);
If I run gulp dev, gulp watch or gulp static, everything works fine. However, if I run just gulp (default), it does the static task 5 times. Can anyone help me out with why this is happening?
P.S. The paths passed to watch are such because if I don't disclude the directories as separate paths, it seems to be copying the empty directories js and scss for some reason.
Probably because you're not returning the tasks, and you need them to be asyc.
See this: Gulp.js task, return on src?
and the docs (also linked in SO post above) https://github.com/gulpjs/gulp/blob/master/docs/API.md#async-task-support
Also, the dev task looks redundant in its current form - you may as well use the task static directly, unless you plan to bundle in more tasks with dev