I want to minify some JS files with Gulp, but can't seem to get control over the process. I want only the minified version in the destination, and am currently getting copies of the originals as well.
I'm thinking I may need the rename package, but am not sure how to use it for this task - I would presumably need some kind of variable to hold the current file name for each script.
Any help much appreciated. The code is below:
var gulp = require( 'gulp' );
var minify = require( 'gulp-minify' );
var rename = require( 'gulp-rename' );
//script paths
var jsFiles = 'js/**/*.js',
jsDest = 'js/dist/';
gulp.task('scripts', function() {
return gulp.src(jsFiles)
.pipe(minify())
.pipe(gulp.dest(jsDest));
});
Set the noSource config like the following
.pipe(minify({noSource: true})
Related
I'm working on a project that uses Node and Gulp, and I want to add a new Javascript library for some new features in the site.
I found this library that does what I need: http://imakewebthings.com/waypoints/
It says in the library website that I need to run npm install waypoints, so I did just that, and a new waypoints directory was created in my node_modules directory. Then I'm said to include the new library in my project like this:
<script src="/path/to/noframework.waypoints.min.js"></script>
But, the library is one level above the document root of my project, so I can't just do src="/node_modules/waypoints/src/waypoint.js" because that folder is not reachable from the web browser.
I tried to add the new module to the gulpfile.js file of my project but it still doesn't work.
var waypoints = require('waypoints'),
I still get a "Uncaught ReferenceError: Waypoint is not defined" error.
What am I missing? How do I get node and/or gulp to load this new library?
EDIT
This is what I have in my gulpfile.js where I "think" it's including the libraries for use in the client side:
var customJSScripts = ['src/js/custom/**/*.js'];
var libsJSscripts = ['src/js/libs/**/*.js'];
var allJSScripts = ['src/js/**/*.js'];
var outputFileName = 'custom.min.js';
var outputFolder = './dist/js/'
gulp.task('jshint', function() {
return gulp.src(customJSScripts)
.pipe(jshint({'esversion': 6}))
.pipe(jshint.reporter('jshint-stylish'));
});
gulp.task('concat-scripts', function() {
if (envVars.minifyJS) {
gulp.src(customJSScripts)
.pipe(sourcemaps.init())
.pipe(concat(outputFileName))
.pipe(uglify())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(outputFolder));
} else {
gulp.src(customJSScripts)
.pipe(sourcemaps.init())
.pipe(concat(outputFileName))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(outputFolder));
}
gulp.src(libsJSscripts)
.pipe(sourcemaps.init())
.pipe(concat('libs.min.js'))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(outputFolder))
});
You don't need to require() waypoints, since you are not using it on the server. What you should do is add another task and make it a dependency for concat-scripts like below:
gulp.task('move-waypoint', function() {
var required_files = [
'../node_modules/waypoints/waypoints.min.js' //make sure this is the right path
];
return gulp.src(required_files, {base: '../node_modules/waypoints/'})
.pipe(gulp.dest(outputFolder));
});
gulp.task('concat-scripts', ['move-waypoint'],function() { //will execute the move-waypoint task first
//your usual code here...
});
You can then look at the path of waypoint in the output folder to determine the script path to include in your html page.
So far I have this code, which I got from here:
var gulp = require('gulp');
var webpack = require('webpack-stream');
var named = require('vinyl-named');
gulp.task('default', function() {
return gulp.src('*/lib/app.js', { base: '.' })
.pipe(named())
.pipe(webpack())
.pipe(gulp.dest('.'));
});
My folder structure is like:
site1/lib/app.js
site2/lib/app.js
I want to create the output files like the following, with each file containing only their respective lib/app.js file's code (and any require()s made in them):
site1/app.js
site2/app.js
However, the code I have now just outputs to the project's root directory. I've tried several combinations, such as removing the { base: '.' }, but nothing works. If I remove the named() and webpack() pipes, though, then the current code actually outputs to the correct directory. So, in the process, it seems like perhaps Webpack loses the originating directory information?
Also, it possible to get a solution that also works with Webpack's "watch: true" option, so that compiling modified files is quick, rather than using Gulp to always iterate through every single file on every file change?
I assume you want to create a app.js for each site that packs only the code for that site (and not the others).
In that case you can use gulp-foreach to effectively iterate over all your app.js files and send each one down its own stream. Then you can use the node.js built-in path module to figure out where the parent directory for each app.js file is and write it there with gulp.dest().
var gulp = require('gulp');
var webpack = require('webpack-stream');
var named = require('vinyl-named');
var foreach = require('gulp-foreach');
var path = require('path');
gulp.task('default', function() {
return gulp.src('*/lib/app.js')
.pipe(foreach(function(stream, file) {
var parentDir = path.dirname(path.dirname(file.path));
return stream
.pipe(named())
.pipe(webpack())
.pipe(gulp.dest(parentDir));
}));
});
If you want to use webpack({watch:true}) you'll have to use a different approach. The following uses glob to iterate over all the app.js files. Each app.js file is again send down its own stream, however this time all the streams are merged before being returned.
var gulp = require('gulp');
var webpack = require('webpack-stream');
var named = require('vinyl-named');
var path = require('path');
var merge = require('merge-stream');
var glob = require('glob');
gulp.task('default', function() {
return merge.apply(null, glob.sync('*/lib/app.js').map(function(file) {
var parentDir = path.dirname(path.dirname(file));
return gulp.src(file)
.pipe(named())
.pipe(webpack({watch:true}))
.pipe(gulp.dest(parentDir));
}));
});
I need to run some gulp task on two different folder only.
Example of my project folder structure:
- Project
- componentA
- componentB
- componentC
- componentD
I need to perform tasks in componentA and componentB and not in C/D.
At the moment I am using the following script.
Could you please tell me how to add the task for B?
Do you know any alternative/better approach?
// include gulp
var gulp = require('gulp');
// include plug-ins
var jshint = require('gulp-jshint');
// JS hint task
gulp.task('jshint', function () {
gulp.src('./componentA/**/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
The below uses a match to exclude C and D directly
(note I'm using concat for testing)
var gulp = require('gulp');
var concat = require('gulp-concat');
var files = './component!(C|D)/*.txt';
gulp.task('test', function(){
gulp.src(files)
.pipe(concat('all.txt'))
.pipe(gulp.dest('./'));
});
Which for you would be
'./component!(C|D)/**/*.js'
I was able to solve this issue using the following code.
Any better way or alternative approaches are welcome.
// include plug-ins
var jshint = require('gulp-jshint');
var folders = [
'./componentA/**/*.js',
'./componentB/**/*.js'
];
// JS hint task
gulp.task('jshint', function () {
gulp.src(folders)
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
I have an app built with Node-Gulp-Webpack.
I have an external JavaScript file external.js that is not local to my app, but I want to be able to require it in my app. This file is on a path for which there is an environment variable named MY_PATH.
How can I include this external.js as-is in my build without making a Node module out of it?
So far, this does not work and doesn't return a useful error message:
var external = require(process.env.MY_PATH + '/external.js');
Use gulp-remote-src, the example:
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var remoteSrc = require('gulp-remote-src');
gulp.task('remote', function() {
remoteSrc(['app.js', 'jquery.js'], {
base: 'http://myapps.com/assets/',
})
.pipe(uglify())
.pipe(gulp.dest('./dist/'));
})
I have multiple sets of js modules that I would like to concat into separate files. I don't want to have to create a seperate concat task for each file. It would make more sense to be able to pass arguments into the gulp task "concat". Unfortunately gulp doesn't allow arguments to be passed into tasks(I'm sure for good reason).
Any ideas of how I can accomplish this?
Use Case
A specific scenario would be website that has a global.js file for all pages as well as page specific js files.
Creating a task for each page specific js file will quickly make the gulpfile.js hard to manage as the site grows.
My dev invironment:
I have a dev/js/ directory which has multiple sub-directories. Each sub-directory contains modules for a specific js file. So each sub-directory needs to be concatenated into it's own file within lib/js/.
Perhaps requirejs?
Maybe I should just look into using a module loader like requirejs.
I needed to take modules from my source sub-directory (src/modules/), concatenate a specific file to each individually (src/distribution), then pipe the result to a sub-directory in my distribution folder (dist/js/modules/).
I wasn't sure how many modules would end up being written for this project so I wanted to do it dynamically and found this to be the best (simplest) solution:
gulp.task("modules:js", () => {
let modules = fs.readdirSync("src/modules");
let concatModule = (module) => {
return gulp.src([
'src/distribution',
module
])
.pipe(concat(module))
.pipe(gulp.dest("build/js/modules"));
}
for (let module of modules) {
concatModule(module);
};
});
You could make concatJS a higher-order function:
var concatJS = function (src, filename, dest) {
return function() {
gulp.src(src)
.pipe(concat(filename))
.pipe(gulp.dest(dest));
};
};
gulp.task('concat-1', concatJS('src/module-1', 'module-1.js', 'build/module-1'));
gulp.task('concat-2', concatJS('src/module-2', 'module-2.js', 'build/module-2'));
//etc...
Note: You'd probably be better off using a bundler like browserify or webpack. Since asking this question I have switched to browserify rather than trying to roll my own solution.
Improved Solution:
var fs = require("fs");
/* other requires omitted */
/* Set JS dev directory in one place */
var jsSrc = "dev/js/";
var jsDest = "lib/js/";
var concat = function (path) {
path = path.replace(/\\/g, "/");
var src = path.replace(/(\/[^\/]+?\.js$)|(\/$)/, "/*.js";
var filename = src.match(/\/([^\/]+?)(\/[^\/]+?\.js$)/)[1] + ".js";
gulp.src(src)
.pipe(concat(filename)
.pipe(gulp.dest(jsDest));
});
/* The concat task just runs the concat function for
* each directory in the javascript development directory.
* It will take a performance hit, but allows concat to be
* run as a dependency in a pinch.
*/
gulp.task("concat", function () {
var dirArr = fs.readdirSync(jsDev);
for (var d in dirArr) {
var path = jsDev+dirArr[d]+"/";
concat(path);
}
});
/* Run "concat" as a dependency of the default task */
gulp.taks("default", ["concat"], function () {
var JSWatcher = gulp.watch([jsSrc+"**/*.js"]);
JSWatcher.on("change", function (event) {
concat(event.path);
});
});
Alright, I think this works. It's a little bit of a hack though, and doesn't work for all use cases.
... removed previous example to save space ...