I am loving gulpjs, but am having an issue where my gulpfile.js is just getting really, really big.
I have searched pretty extensively and am having difficulty finding resources related to this, but is it possible to split a gulpfile.js up into multiple smaller js files just for organization?
Yes, you can do it to manage your tasks. For example if you have this file organization:
gulpfile.js
-- tasks
---- test.js
---- dev.js
You have to install de require-div module:
npm install require-dir --save-dev
And, finally, you add this code to your gulpfile
var requireDir = require('require-dir');
var dir = requireDir('./tasks');
Hope it helps.
Regards.
I do it this way (I use coffeescript, but the theory is sound), similar to the above:
tasks = fs.readdirSync './gulp/tasks'
tasks.forEach (task)->
require "./tasks/#{task}" if task.indexOf('coffee') >= 0
All it does is read the task folder and require all the files in it as long as they're .coffee files (which isn't 100% kosher, but it does avoid hidden dotfiles).
Related
I am building a series of plugins for WP, and want to use gulp to manage the assets.
I have created a strict naming/directory pattern in each of the plugins, in order to make using the task management easier. Currently all the plugins sit in the basic WP structure, and my gulp file sits below root and runs fine.
I am now extracting all the plugins into composer packages. I now want to build the plugins, and leave all the assets in the plugin directories rather than dumping them to the theme. I have now put the "builder" into its own package, which I can run from my IDE.
e.g.
pluginOne
pluginTwo
pluginBuilder
I have so far created this to find the scss files build the style:
How can I tell gulp to pipe back to the directory it found? I've only managed to get it to pipe to specific dir
gulp.task('style', function() {
glob('../plugins/pluginprefix-*/assets/build/scss/pluginprefix.*.scss', {}, function (er, files) {
gulp.src(files)
.pipe(plugins.plumber())
.pipe(plugins.sass())
.pipe(plugins.autoprefixer('last 10 version'))
.pipe(plugins.minifyCss())
.pipe(gulp.dest(''));
})
});
Thanks for any help or advice =)
This should work:
var rename = require('gulp-rename');
...
.pipe(rename(function(path){
path.dirname = path.dirname;
path.basename = path.basename;
});
.pipe(gulp.dest(''));
The code
My latest commit is in a repo on GitHub.
The problem...
I am setting up a project (link above) using GruntJS. While trying to run any Grunt task, I'm getting a No "<insert-taskname>" targets found; a few examples:
No "browserSync" targets found.
Warning: Task "browserSync" failed. Use --force to continue.
No "jshint" targets found.
Warning: Task "jshint" failed. Use --force to continue.
No "sass" targets found.
Warning: Task "sass" failed. Use --force to continue.
What I'm doing
I am using external .js Grunt config files using the load-grunt-configs plugin. I have used a very similar setup in other projects without problems. I'm passing the shared Grunt variables which were initialized in the Gruntfile.js to each of the grunt-configs files using the options object that is a part of the load-grunt-configs plugin.
What I've tried so far...
I've tried checking my Grunt variables that are being used in the external config files, double checking my syntax and bracket matching, and searching through other stack overflow questions with no luck.
Any help would be greatly appreciated! Thank you.
I recommend using the idiomatic and built-in methods of breaking up your Gruntfile instead. 3rd party solutions tend to stray far from the Grunt APIs.
Create a folder named tasks/ and within that folder add files similar to what you're currently doing now.
Load all of those files in your main Gruntfile using grunt.loadTasks():
// Gruntfile.js
module.exports = function(grunt) {
// Initialize config.
grunt.initConfig({
pkg: require('./package.json'),
});
// Load per-task config from separate files.
grunt.loadTasks('tasks');
};
Each of those files are formatted like mini Gruntfiles. Here is an example for jshint:
// tasks/jshint.js
module.exports = function(grunt) {
grunt.config('jshint', {
app: {
options: {jshintrc: 'app/.jshintrc'},
src: ['app/**/*.js'],
},
});
grunt.loadNpmTasks('grunt-contrib-jshint');
};
Here is a full example of this solution from the creator of Grunt himself: https://github.com/cowboy/wesbos
your problem is inside your config tasks.
you are doing
module.exports = {
you need to do:
module.exports.tasks = {
other than that i recommend following kyle's answer, as it is much cleaner to use grunt's built in features!
I am building an npm module that will generate a specific project template for certain software projects. As such, when a developer installs my npm module and runs it, I would like the program to create files and folders in a certain way.
One such file I would like to include in the project template is a .gitignore file because the software project is going to assume it will be tracked via git. However, when I call "npm install" on my module, npm renames all my .gitignore files to .npmignore files. How can I ensure that my .gitignore files are not tampered with by npm when I distribute my module?
Currently npm doesn't allow .gitignore files to be included as part of an npm package and will instead rename it to .npmignore.
A common workaround is to rename the .gitignore to gitignore before publishing. Then as part of an init script, rename the gitignore file to .gitignore. This approach is used in Create React App
Here's how to do it in Node, code from Create React App init script
const gitignoreExists = fs.existsSync(path.join(appPath, '.gitignore'));
if (gitignoreExists) {
// Append if there's already a `.gitignore` file there
const data = fs.readFileSync(path.join(appPath, 'gitignore'));
fs.appendFileSync(path.join(appPath, '.gitignore'), data);
fs.unlinkSync(path.join(appPath, 'gitignore'));
} else {
// Rename gitignore after the fact to prevent npm from renaming it to .npmignore
// See: https://github.com/npm/npm/issues/1862
fs.moveSync(
path.join(appPath, 'gitignore'),
path.join(appPath, '.gitignore'),
[]
);
}
https://github.com/npm/npm/issues/1862
Looks like this is a known issue. The answer at the bottom seems like the recommended approach. In case the issue or link ever gets destroyed:
For us, I think a better solution is going to be clear documentation that if authors wish to use .gitignore in their generators, they will need to name their files .##gitignore##, which will be a value gitignore set to the same string gitignore.
In this way, the file that gets published as a template file to npm is called .##gitignore## and won't get caught by npm, but then later it gets replaced with the string to be .gitignore.
You can see multiple commits dealing with npm issue 1862:
this project adds a rename.json:
lib/init-template/rename.json
{
".npmignore": ".gitignore",
}
this one renames the .gitignore:
templates/default/.gitignore → templates/default/{%=gitignore%}
index.js
## -114,6 +114,10 ## generator._pkgData = function (pkg) {
+ // npm will rename .gitignore to .npmignore:
+ // [ref](https://github.com/npm/npm/issues/1862)
+ pkg.gitignore = '.gitignore';
Edit: even though this answer causes .gitignore to be included in the published package (proven by unpkg), upon running npm install the .gitignore file is simply removed! So even getting NPM to include the file is not enough.
Another solution (simpler imo):
Include both .gitignore and .npmignore in the repo. Add the following to your .npmignore file:
!.gitignore
!.npmignore
Now that .npmignore will already exist in the published package, NPM won't rename .gitignore.
I have a node project with:
.coffeescript source in src
compiled coffeescript output to lib
shell scripts in bin
How can I adjust my Makefile, shown below, to also copy .js files in src to the lib directory?
BIN = ./node_modules/.bin
SRC = $(wildcard src/*.coffee)
LIB = $(SRC:src/%.coffee=lib/%.js)
init:
npm install
clean:
#rm -r -f $(LIB)
build: $(LIB)
dist: clean init build
lib/%.js: src/%.coffee
$(call coffeetime)
define coffeetime
#mkdir -p $(#D)
$(BIN)/coffee -bcp $< > $#
endef
Also, if you have any other suggestions to improve the Makefile, please share.
Something like this might work.
Add SRCJS = $(wildcard src/*.js)
Change LIB = $(SRC:src/%.coffee=lib/%.js) to LIB = $(SRC:src/%.coffee=lib/%.js) $(SRCJS:src/%=lib/%).
Add:
lib/%.js: src/%.js
#cp $< $#
If it doesn't work (for some reason) then you may need to use a static pattern rule but I think something like the above should work.
I would suggest you to use Grunt instead.
There is a few neat task that handle Coffeescript compiling very well. Like: https://github.com/gruntjs/grunt-contrib-coffee
Also, depending on your needs, Node.js can cope with Coffeescript directly if needed.
I have some projects that use RequireJS to load individual JavaScript modules in the browser, but I haven't optimized them yet. In both development and production, the app makes a separate request for each JavaScript file, and now I would like to fix that using Grunt.
I have tried to put together a simple project structure to no avail, so I'm wondering if someone can provide a working example for me. My goals are the following:
In development mode, everything works in the browser by issuing a separate request for each required module. No grunt tasks or concatenation are required in development mode.
When I'm ready, I can run a grunt task to optimize (combine) all of the JavaScript files using r.js and test that out locally. Once I'm convinced the optimized application runs correctly, I can deploy it.
Here's a sample structure for the sake of this conversation:
grunt-requirejs-example/
grunt.js
main.js (application entry point)
index.html (references main.js)
lib/ (stuff that main.js depends on)
a.js
b.js
requirejs/
require.js
text.js
build/ (optimized app goes here)
node_modules/ (necessary grunt tasks live here)
Specifically, I'm looking for a working project structure that I can start from. My main questions are:
If this project structure is flawed, what do you recommend?
What exactly needs to be in my grunt.js file, especially to get the r.js optimizer working?
If all of this isn't worth the work and there's a way to use the grunt watch task to automatically build everything in development mode every time I save a file, then I'm all ears. I want to avoid anything that slows down the loop from making a change to seeing it in the browser.
I use the grunt-contrib-requirejs task to build project based on require.js. Install it inside your project directory with:
npm install grunt-contrib-requirejs --save-dev
BTW: --save-dev will add the package to your development dependencies in your package.json. If you're not using a package.json in your project, ignore it.
Load the task in your grunt file with:
grunt.loadNpmTasks('grunt-contrib-requirejs');
And add the configuration to your grunt.initConfig
requirejs: {
production: {
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js",
out: "path/to/optimized.js"
}
}
}
Now you're able to build your require.js stuff into a single file that will be minimized with uglifyjs by running grunt requirejs
You can bundle a set of different tasks into some sort of main task, by adding this to your grunt file
grunt.registerTask('default', ['lint', 'requirejs']);
With this, you can simply type grunt and grunt will automatically run the default task with the two 'subtasks': lint and requirejs.
If you need a special production task: define it like the above
grunt.registerTask('production', ['lint', 'requirejs', 'less', 'copy']);
and run it with
grunt production
If you need different behaviors for 'production' and 'development' inside i.e. the requirejs task, you can use so called targets. In the configuration example above it's already defined as production. You can add another target if you need (BTW, you can define a global config for all targets by adding a options object on the same level)
requirejs: {
// global config
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js"
},
production: {
// overwrites the default config above
options: {
out: "path/to/production.js"
}
},
development: {
// overwrites the default config above
options: {
out: "path/to/development.js",
optimize: none // no minification
}
}
}
Now you can run them both at the same time with grunt requirejs or individually with grunt requirejs:production, or you define them in the different tasks with:
grunt.registerTask('production', ['lint', 'requirejs:production']);
grunt.registerTask('development', ['lint', 'requirejs:development']);
Now to answer your questions:
I would definitely use a subfolder in your project. In my case I use a 'src' folder for development that is build into a 'htdocs' folder for production. The project layout I prefere is:
project/
src/
js/
libs/
jquery.js
...
appname/
a.js
b.js
...
main.js // require.js starter
index.html
...
build/
... //some tmp folder for the build process
htdocs/
... // production build
node_modules/
...
.gitignore
grunt.js
package.json
see above
You can do so, but I wouldn't recommend to add requirejs to the watch task, it's a resource hungry task and it will slow down your machine noticeable.
Last but not least: Be very cautious when playing around with r.js. Especially when you want to optimize the whole project with r.js by adding a modules directive to your config. R.js will delete the output directory without asking. If it happens that it is accidentally configured to be your system root, r.js will erase your HDD. Be warned, I erased my whole htdocs folder permanently some time ago while setting up my grunt task... Always add keepBuildDir:true to your options when playing around with the r.js config.