I'm trying to create a gulpfile that lint my personal javascript files (.js) but ignore any vendor/third party libaries.
My gulp file is listed below:
var gulp = require("gulp"),
uglify = require("gulp-uglify"),
jshint = require("gulp-jshint"),
jasmine = require("gulp-jasmine"),
nodemon = require("gulp-nodemon");
// lint JS files for bad habbits
gulp.task("lint", function () {
gulp.src(["**/*.js", "node_modules/*"])
.pipe(jshint())
.pipe(jshint.reporter("default"));
});
gulp.task("nodemon", function () {
nodemon({
script: "server.js",
ext: "html css jade js",
ignore: ["node_modules/*"]
})
.on("change", ["lint"])
.on("restart", function () {
console.log("Change detected, restarting server ...");
});
});
gulp.task("default",["nodemon"]);
When I run the "gulp default" command in my terminal it still lint the javascript files in the node_modules. I've tried variations of the glob syntax but I can't seem to achieve the desired behaviour.
Any idea where I've gone wrong?
Thanks.
The glob pattern you've set, node_modules/* only matches the files in the root of the node_modules directory, but not all the children with an highter depth.
You need to set is as node_modules/**/*, this will match everything. I advice you however to only match js files, with node_modules/**/*.js.
You also need to negate the pattern with !, gulp does not know that you want to do that, so it will look like:
gulp.src(['**/*.js', '!node_modules/**/*.js'])
For nodemon, following the same thing you can use the node_modules/**/* pattern.
The library used by gulp for globbing is minimatch.
use this ignore: ["node_modules/"] without '*' and it will work
Related
So I'm having a slight problem with producing production ready scripts for my project. I'm using gulp to concatenate and minify my css and js, and while the css is working fine the gulp js function isn't generating my final file. Please refer to my code below:
gulp.task('js', function() {
return gulp.src([source + 'js/app/**/*.js'])
.pipe(concat('development.js'))
.pipe(gulp.dest(source + 'js'))
.pipe(rename({
basename: 'production',
suffix: '-min',
}))
.pipe(uglify())
.pipe(gulp.dest(source + 'js/'))
.pipe(notify({ message: 'Scripts task complete', onLast: true }));
});
If anyone has encountered a similar problem or has any tips it would be much appreciated :)
There is nothing wrong with your gulpfile. I tested it and it works perfectly.
The only thing I can guess is that your source is not set correctly. Did you forget the trailing slash '/' ?
I would suggest 2 things to figure it out. Include node path library to check where source is actually pointing to like this:
var path = require('path');
// in gulp task ...
path.resolve(path.resolve(source + 'js/app'));
Make sure it points where you think it does.
Secondly, you could use gulp-debug to establish that any files are found:
npm install gulp-debug
Then
var debug = require('gulp-debug');
// in gulp task ...
return gulp.src([source + 'js/app/**/*.js'])
.pipe(concat('development.js'))
.pipe(debug())
.pipe(gulp.dest(source + 'js'))
.pipe(debug())
// etc.
Good luck!
Based on additional infomation in the comments I realise you are generating JS files in a separate process ...
gulp is asynchronous by default. What this boils down to is that all functions try to run at the same time - if you want a specific order it must be by design. This is great because it's very fast but can be a headache to work with.
Problem
Here is what's basically happening:
// SOME TASK THAT SHOULD BE RUN FIRST
gulp.task('copy-vendor-files-to-tempfolder', function (done) {
// copy files to vendor folder
done()
})
// SOME TASKS THAT DEPEND ON FIRST TASK
gulp.task('complile-styles', function () { /* independent task */ })
gulp.task('concat-vendor-files', function () { /* concat files in vendor folder. depends on vendor files existing */ })
// GENERAL TASK WHICH STARTS OTHERS
gulp.task('ready', ['copy-vendor-files-to-tempfolder', 'compile-styles', 'concat-vendor-files])
When you try to run:
$ gulp ready
GULP TASK WILL FAIL! Folder is being created at the same time!!
NOWHERE TO COPY FILES!
Solution
There are many solutions but the following module has come in handy for me again and again:
npm install run-sequence
Then in your gulpfile.js:
var runSequence = require('run-sequence')
gulp.task('ready', function (done) {
runSequence(
'create-folders', // do this first,
[
'copy-css-files',
'copy-html-files'
], // do these AFTER but in parallel
done // callback when ready
)
})
This will guarantee the folder exists when you try to run the other functions.
In your specific case, you should make sure the task that concatenates the JS files is run after the task that copies them out of vendor.
Note: I'm leaving other answer because it contains useful help for debugging similar issues.
HTH!
I try to write these code
gulp.task('script', function() {
'use strict'
return gulp.src(['app.js', 'components/**/*.jsx'])
.pipe(babel())
.pipe(browserify())
.pipe(gulp.dest("dist"));
});
but it shows some error:
SyntaxError:
/Users/Zizy/Programming/learn-react-js/components/CommentBox.jsx:58
<div className="commentBox">
^
ParseError: Unexpected token
at wrapWithPluginError (/Users/Zizy/Programming/learn-react-js/node_modules/gulp-browserify/index.js:44:10)
It seems that before .pipe(browserify()) the gulp did't transform the jsx code. But if I just remove .pipe(browserify()) I find that did transform, just cannot let babel and browserify work together.
I know maybe I can use like babelify or browserify plugin for babel though, I just want figure out the reason.
gulp-browserify doesn't quite work like that. You don't give it a bunch of buffers to collect and bundle.
You give it one file—the entry file—which it passes into Browserify. Browserify checks to see what other files the entry file references, then loads those files directly from the file system, meaning that you can't modify them with gulp plugins beforehand.
So, really, if we pretend you don't want to use Babel on your source files, your gulpfile should look like this, only passing in the entry file:
gulp.task('script', function() {
'use strict'
return gulp.src('app.js')
.pipe(browserify())
.pipe(gulp.dest("dist"));
});
However, note that gulp-browserify is no longer maintained, and this is exactly why. gulp plugins aren't supposed to read directly from the file system. That's why you're supposed to use Browserify (or, in your case, Babelify) directly with vinyl-source-stream as recommended in the gulp recipes. It's more idiomatic and less confusing.
That wraps up my answer to your question, but I'd like to add: if you're using the ES2015 module syntax (and you probably should be), there's a better way to do this. Browserify wraps all your modules separately in a bunch of code to make the programmatic CommonJS API work properly, but ES2015 modules have a declarative syntax, which makes it much easier for tools to operate on them statically. There's a tool called Rollup that takes advantage of this, allowing it to produce bundles that are smaller, faster, and more minfication-friendly than Browserify's.
Here's how you might use it with gulp:
var gulp = require('gulp'),
rollup = require('rollup-stream'),
babel = require('gulp-babel'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer');
gulp.task('script', function() {
return rollup({entry: 'app.js'})
.pipe(source('app.js'))
.pipe(buffer())
.pipe(babel())
.pipe(gulp.dest('dist'));
});
Starting from Babel 6 you need to declare the presets manually, check this.
Basically, in the root of your project you need a .babelrc with the following content:
{
"presets": [ "es2015", "react" ]
}
And the corresponding npm modules in package.json:
// package.json
{
"devDependencies": {
...
"babel-preset-es2015": "^6.1.18",
"babel-preset-react": "^6.1.18",
...
}
}
Here is a sample repository with gulp, babel and browserify
Following is the code snippet
gulp.task("js", (done) => {
const bundler = browserify({ entries: paths.js.source }, { debug: true }).transform(babel);
bundler.bundle()
.on("error", function (err) { console.error(err); this.emit("end"); })
.pipe(source(paths.build.destMinJSFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(sourcemaps.write(paths.js.destMapFolder))
.pipe(gulp.dest(paths.build.destBuildFolder));
done();
});
I'm using gulp with browserify and tsify in a TypeScript project. The following is an extract from my gulpfile.js:
var browserified = function (filename, debug) {
var b = browserify({
entries: filename,
debug: debug || false
});
b.plugin('tsify', {
noImplicitAny: true,
target: 'ES5'
});
b.transform('debowerify');
return b.bundle();
};
gulp.task('rebuild', ['lint', 'less'], function() {
var b = browserified ('./src/ts/main.ts', true);
return buildSourceMaps (b);
});
This works so far. I want to extend this so I can require React JSX files. First I tried (from one of my TypeScript files):
import Test = require ('../jsx/Test.jsx');
This doesn't work, though, because tsify would complain as it looks for a TypeScript file ../jsx/Test.jsx.ts. So I use the following hack:
declare var require: any;
var Test = require ('../jsx/Test.jsx');
If Test.jsx is plain vanilla JavaScript, this works. If Test.jsx contains TypeScript, it would fail, which is what I expect. So far, so clear.
Now I want to add reactify to my gulp tasks so I can use JSX in these files. Here I am stuck! I tried adding the following to the function browserified in my gulpfile.js:
b.plugin ('reactify', {
extension: 'jsx'
});
I still get the following error when I call gulp rebuild when Test.jsx contains actual JSX:
Unexpected token <
Obviously, gulp chokes on the first JSX-specific term. I think gulp is trying to pass the JSX through the TypeScript compiler. Which isn't a surprise, since I can't think of a way how to tell tsify to ignore my .jsx files. I'm new to gulp, so I am a bit at a loss. Any ideas how to set up gulp to allow for TypeScript with all .ts files and JSX with all .jsx files?
This is the gulp task I use for development. It uses watchify along with browserify and reactify to build your code, provide source mapping, and rebundle any changes you make on the fly. The path.ENTRY_POINT variable is the main component for your react app (often app.js or main.js).
gulp.task('watch', function() {
gulp.watch(path.HTML, ['copy']);
var watcher = watchify(browserify({
entries: [path.ENTRY_POINT],
transform: [reactify],
debug: true,
cache: {}, packageCache: {}, fullPaths: true
}));
return watcher.on('update', function () {
watcher.bundle()
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC))
console.log('Updated');
})
.bundle()
.pipe(source(path.OUT))
.pipe(gulp.dest(path.DEST_SRC));
});
I used this tutorial to set up my gulpfile.js and it provides a good explanation for every gulp task:
http://tylermcginnis.com/reactjs-tutorial-pt-2-building-react-applications-with-gulp-and-browserify/
I have a gulp starter kit for my project, however, I want to use gulp-load-plugins to for devDependencies of package.json file. My file structure is
ProjectName
Gulp
-Tasks
-broswerify.js
-browserSync.js
-jade.js
-lint.js
Gulpfile.js
config.json
package.json
Gulpfile.js
var requireDir = require('require-dir');
var dir = requireDir('./gulp/tasks', {recurse: true});
jade.js (Which is working as expected using gulp-load-plugins)
var gulp = require('gulp');
var config = require('../../config.json');
var plugins = require('gulp-load-plugins')();
gulp.task('jade', function(){
return gulp.src(config.jade.src)
.pipe(plugins.jade())
.pipe(gulp.dest(config.jade.build))
});
browsersync.js (which is not working using gulp-load-plugins)
var gulp = require('gulp');
var config = require('../../config.json').browsersync;
var plugins = require('browsersync'); // works
//var plugins = require('gulp-load-plugins')(); // it doesn't works.
gulp.task('browsersync', function () {
plugins.browserSync.init(config); // (browsersync required)
//plugins.browserSync.init(config) it doesn't work. (gulp-load-plugins required)
});
I would like to know that if there is a better way to do that?
Why would you wan't to use gulp-load-plugins if you have a seperate file for each plugin?
This is how i load gulp-load-plugins :
$ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'gulp.*'],
replaceString: /\bgulp[\-.]/,
lazy: true,
camelize: true
}),
Here is an example of a revision plugin:
// revision styles
gulp.task('rev-styles', function () {
return gulp.src(dev.css)
.pipe($.rev())
.pipe($.cssmin())
.pipe(gulp.dest(dist.css))
.pipe($.filesize())
.pipe($.rev.manifest({merge: true}))
.pipe(gulp.dest('./'))
//rev replace
.on('end', function() {
return gulp.src(['./rev-manifest.json', 'dist/*.html'])
.pipe($.revCollector({
replaceReved: true,
dirReplacements: {
'css': 'css'
}
}))
.pipe(gulp.dest(dist.dist))
});
});
As you can see all my pipes are called .pipe($.pluginName()) meaning $ stands for gulp- . If you have a plugin named gulp-name-secondname you call it like this: .pipe($.nameSecondname()) . Top were i require gulp-load-plugins i have camelize set to true . Lazy loading loads only the plugins you use not all of them .
As a side note i strongly recommend not separating plugins in diffrent files but you can modulate them, meaning separating important tasks in separate files like compilation file , optimization file , build file, etc .
This might help you understand gulp file separation better http://macr.ae/article/splitting-gulpfile-multiple-files.html
Careful with gulp-load-plugins because it slows your tasks , for example i run gulp-webserver , when i use it with gulp-load-plugins the task finishes after 200ms versus 20ms if i use it normally. So don't use with everything, play with it see how much performance you lose on each task and prioritize.
I have used gulp-load-plugins but found that it mainly adds complexity and obscures my code. At also makes it harder to understand for people less familiar with Gulp. It looks cleaner and easier to understand to have all modules explicitly declared at the top.
I've split out my grunt plugins into their own files and I'm using the load-grunt-config (https://github.com/firstandthird/load-grunt-config) to call them:
module.exports = function (grunt) {
'use strict';
require('load-grunt-config')(grunt);
};
I've got sass, autoprefixer, cssmin and watch tasks working but I'm also using Browsersync and px-to-rem these two plugins return:
Warning: Task "remify" not found. Use --force to continue.
and
Warning: Task "browsersync" not found. Use --force to continue.
when called individually or as part of a bigger task.
I've followed the syntax for the separate.js files for these two plugin so I'm at a loss. For example the remify.js file which is called when running grunt is written like this
module.exports = {
dist: {
options: {
base: 16,
fallback: true,
fallback_existing_rem: true,
ignore: []
},
files: {
'css/style.css': 'css/style.css'
}
}
};
Any ideas where this is going wrong?
I've also set up a gist of the example code, include package.json and a aliases.yml
https://gist.github.com/sturobson/f88258fd010e901e24d9
You have to call the grunt plugin exactly what it is. So where I've got remify I should be using px_to_rem and where I've got browsersync and I should have browserSync.
Silly me.
you can pass a second argument to load-grunt-config to provide some options where you could also define some pattern which can be used by load-grunt-tasks which is used internally.
if you don't pass a second argument, it uses the default-pattern of load-grunt-tasks which is grunt-*.
so if you want to load all devDependencies without defining them seperatly, do it like this:
require('load-grunt-config')(grunt, {
loadGruntTasks: {
pattern: '*',
scope: 'devDependencies'
}
});