I just started playing with gulp, and it's very fast and easy to use but it seems to have a critical flaw: what do you do when a task needs to output more than one type of file?
For example, gulp-less says it doesn't even support the sourceMapFilename option. I don't want my source map embedded in my CSS file. Am I hooped? Should I just go back to using Grunt, or is there a way to deal with this?
This task will take multiple files, do stuff to them, and output them along with source maps.
It will include the source code within the maps files by default, so you don't have to distribute the source code files too. This can be turned off by setting the includeContent option to false. See the gulp-sourcemaps NPM page for more source map options.
gulpfile.js:
var gulp = require("gulp");
var plugins = require("gulp-load-plugins")();
gulp.task("test-multiple", function() {
return gulp.src("src/*.scss")
.pipe(plugins.sourcemaps.init())
.pipe(plugins.sass())
.pipe(plugins.autoprefixer())
.pipe(plugins.sourcemaps.write("./"))
.pipe(gulp.dest("result"));
});
package.json
"gulp": "~3.8.6",
"gulp-load-plugins": "~0.5.3",
"gulp-sass": "~0.7.2",
"gulp-autoprefixer": "~0.0.8",
"gulp-sourcemaps": "~1.1.0"
The src directory:
first.scss
second.scss
The result directory after running the test-multiple task:
first.css
first.css.map // includes first.scss
second.css
second.css.map // includes second.scss
Gulp supports multiple output files fine. Please read the docs.
Example:
gulp.task('scripts', function () {
return gulp.src('app/*js')
.pipe(uglify())
.pipe(gulp.dest('dist'));
});
This will read in a bunch of JS files, minify them and output them to the dist folder.
As for the gulp-less issue. You could comment on the relevant ticket.
In the docs it shows you how to have multiple output files:
gulp.src('./client/templates/*.jade')
.pipe(jade())
.pipe(gulp.dest('./build/templates'))
.pipe(minify())`
.pipe(gulp.dest('./build/minified_templates'));
Related
I'm trying to come up with a gulp task that generates new source maps whenever its corresponding .js file has changed, this is what I have so far:
gulp.task('maps', [ 'compile:ts' ], function () {
return gulp.src([
'app/**/*.js'
])
.pipe(newer({ dest: 'app', ext: '.js.map' }))
.pipe(print(function (filepath) {
return 'Creating source map for ' + filepath + '...';
}))
.pipe(sourcemaps.init())
.pipe(sourcemaps.write('./'))
.pipe(print(function (filepath) {
return 'Writing source map for ' + filepath + '...';
}))
.pipe(checkout())
.pipe(gulp.dest('app'))
;
});
Now two weird things happen:
gulp-newer returns all .js files, it doesn't matter if they were changed or not (regarding the timestamps of the .map.js files).
gulp-sourcemaps emits both, the .js and the .js.map file.
Can anyone provide a hint what I'm missing here?
gulp-sourcemaps emits both, the .js and the .js.map file.
That's to be expected, because that's how source maps work. Each .js file contains a sourceMappingURL comment that points to the .js.map file so your browser knows where to find it.
You can leave this out by using the addComment option:
.pipe(sourcemaps.write('./'), {addComment:false})
Of course, that means your HTTP server has to send a X-SourceMap header for each .js file.
gulp-newer returns all .js files, it doesn't matter if they were changed or not (regarding the timestamps of the .map.js files).
This might be caused by gulp-sourcemaps emitting both a .js and a .js.map file, effectively overwriting your existing .js file. Using the same source and destination directories is generally a bad idea, so using a different dest directory would solve this problem.
(It might also be caused by the checkout() pipe, but you didn't describe what that does. I'd try removing this and see if it works.)
However I don't think any of the above really matters, since your general approach and the way you're using gulp-sourcemaps is likely to be completely wrong. I assume you want sourcemaps from your original .ts files to your compiled .js files. In that case you need to use it in your compile:ts task. The way you're using it now will just produce an empty source map file.
I see the console log statement that js task run twice once I change any of the javascript files. I wonder why it run two times for each change?
var gulp = require('gulp');
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
gulp.task('default', function() {
gulp.watch("public/js/**/*.*", ["js"]);
});
gulp.task("js", function(){
var js = [
"public/js/**/*.js",
"!public/js/api/**/*.js"
];
gulp.src(js)
.pipe(concat("app.min.js"))
.pipe(uglify())
.pipe(gulp.dest("public/js"));
});
Console
[13:02:27] Starting 'js'...
[13:02:27] Finished 'js' after 1.6 ms
[13:02:27] Starting 'js'...
[13:02:27] Finished 'js' after 5.1 ms
The problem is that you are watching the same directory which is used as the destination directory in the task you run when the change is detected. Currently, your build flow looks like this:
Imagine you're modifying a file public/js/script.js.
The watch task detects the change and starts your custom js task. As the result, the public/js/app.min.js file is created.
Since the app.min.js is inside the watched directory, the watch task detects another change, hence the js task is executed once more. You actually should run into a loop, but Gulp seems to be smart enough do detect such a cycle.
The best solution for this issue is to separate source files from the output. In your task pipe, set the destination folder to something outside the source directory, for example:
.pipe(gulp.dest("dist/js"));
After that, your project should has the following structure:
public
js
script.js
dist
js
app.min.js
grunfile.js
...
Where the public directory is used to keep the source files that are watched and the dist directory holds the output of the build. If I were you, I would reconsider renaming the public directory to something more descriptive like src, but that is up to you :)
All:
I am pretty to new to Gulp and Browserify, what I did is transpile some jsx code and browserify them into a bundle.js file.
var gulp = require("gulp");
var browserify = require("browserify");
var source = require("vinyl-source-stream");
var reactify = require("reactify");
gulp.task("default", function(){
browserify({
entries: ["js/app.js"],
debug: true
})
.transform(reactify)
.bundle()
.pipe(source("bundle.js"))
.pipe(gulp.dest("dist/js/"));
});
In app.js, I specify a few require dependencies(each one may require some other file), and I thought browserify will parse them and compile into a single bundle.js file, but when I run it, even I only include bundle.js in index.html page, it still includes all those dependency files when I check in Chrome source tab, I wonder if this is just Chrome's feature to parse bundle file which gives me a list of dependency file list or it actually download those dependency files as well( My confuse is I actually can click and open those dependency files, so I guess Chrome download them all with bundle.js, but I am not sure about that)?
Thanks
If I understand you correctly, you are describing what debug: true in browserify gives you, aka source maps.
--debug -d Enable source maps that allow you to debug your files separately.
and
When opts.debug is true, add a source map inline to the end of the
bundle. This makes debugging easier because you can see all the
original files if you are in a modern enough browser.
I have following directory structure:
common
-services
--service1.js
--service2.js
-app
--gulpfile.js
--src
---services
----service1.js
----service3.js
I want to made gulp task that will take all files from common directory, take files from app directory and replace all files with same filenames in original stream. After that I will concat it and write to other directory.
I tried this:
var gulp = require('gulp'),
merge = require('gulp-merge'),
concat = require('gulp-concat');
gulp.task('templates', function () {
return merge(
gulp.src(['../common/**/*.js']),
gulp.src(['src/**/*.js'])
)
.pipe(concat('app.js'))
.pipe(gulp.dest('build/js'));
});
I expected to got content of common/services/service2.js, app/src/services/service1.js, app/src/services/service3.js in dest/app.js.
But instead I've got content of all files.
I tried to change cwd or base of gulp.src, but it has no effect.
I know that I can write this stream to tmp directory, and after that get files from it, but it seems not really like gulp-style solution. So how can I overwrite files with same file names in streams?
Ok, i can't find any existing solution for that, so I write my own gulp plugin: gulp-unique-files.
I'm trying to make a Gulp task that takes JS files, runs uglify on them, adds a .min suffix to the filename and then saves them in a destination folder that is different than the source folder. The tricky part is to keep source maps working...
gulp.task('uglify-js', function () {
// Fetch CSS files
return gulp.src(['assets/js/*.js', '!assets/js/*.min.js'])
// Start source map
.pipe(sourcemaps.init({loadMaps: true}))
// Uglify JS
.pipe(uglify())
// Add file suffix
.pipe(rename({suffix: '.min'}))
// Save source map
.pipe(sourcemaps.write())
// Save output to destination folder
.pipe(gulp.dest('public/js/'));
});
I tried many different options, but the source maps don't seem to work...
Does anyone know the right way to do this?
My packages:
"devDependencies": {
"gulp": "^3.8.10",
"gulp-rename": "^1.2.0",
"gulp-sourcemaps": "^1.3.0",
"gulp-uglify": "^1.0.2"
}
Thanks a bunch! :)
The problem is gulp-rename doesn't currently support gulp-sourcemaps, as mentioned in their latest issue.
One alternative is to use a different lib that supports sourcemaps, for example gulp-concat, which supports renaming the files. If you don't want to concat your files, however, you could always open a pull request against gulp-rename to add sourcemaps support, as documented here.
Update: As of 2015-03-14 gulp-rename now supports sourcemaps