I used yeoman yeogurt generator to kickstart my project.
The grunt file generated uses (to the best of my knowledge) include-all and grunt-jit to load the modules.
What I would like to do, is add the building of jekyll to this file. To do this I installed grunt-jekyll. Afterwards I created a simple config file in grunt/config/compile/ and added the following:
// Configuration for jekyll task(s)
// Compiles the blog
'use strict';
var taskConfig = function(grunt) {
grunt.config.set('jekyll', {
options: { // Universal options
bundleExec: true,
src : '<%= jekyll %>'
},
dist: { // Target
options: { // Target options
dest: '<%= dist %>/blog',
config: '_config.yml,_config.build.yml'
}
}
});
};
module.exports = taskConfig;
After creating this file, I tested if grunt was still working by running "grunt build" and as it turns out, it didn't. I get the following error:
Running "useminPrepare:html" (useminPrepare) task
Going through dist/index.html to update the config
Looking for build script HTML comment blocks
Fatal error: Maximum call stack size exceeded
I have no idea why I get this error, as I did not tell grunt to do anything with jekyll (except load it), so I would not expect anything to have changed. Removing the file makes my grunt setup function without error.
Adding jekyll:dist to grunt/tasks/build.js results in a similar error but in the correct module:
Running "jekyll:dist" (jekyll) task
Warning: Maximum call stack size exceeded Use --force to continue.
I don't know if it helps, but here is some extra info about my setup:
node v0.12.2
grunt: v0.4.5
grunt-cli: v0.1.13
using: jade, sass, dashboard
gruntfile: https://gist.github.com/Boelensman1/95bb3ec7298377c8c4c9
package.json: https://gist.github.com/Boelensman1/1f0c97a7d7720f9e2be4
.yo-rc.json: https://gist.github.com/Boelensman1/cef88cb2cb925faa355d
build.js: https://gist.github.com/Boelensman1/5f55c251648b881e3f2d
I think I made an error in my jekyll config file, but I don't see where. If someone could help me it would be greatly appreciated.
I don't know why this results in a stack overflow, but the problem is that <%= dist %> and <%= jekyll %> are wrong. It should be <%= yeogurt.jekyll %> and <%= yeogurt.dist %>. This is because yeogurt is the configuration object, see line #20 of your gruntfile.
Related
I am trying to install Modernizr with Yarn in Rails. I do 'yarn add Modernizr' and it gets added to the .node-modules directory. However, I can't figure out how to reference it properly from Rails.
I have added //= require modernizr/src/Modernizr to application.js. But I'm not sure that's the right reference because I get the following error:
Uncaught ReferenceError: define is not defined
Do I need to somehow build the Modernizr library. Does yarn not do that? I'm somewhat new to this and struggling to understand the relationship between webpacker, yarn, and rails and how to properly build and add libraries to rails with yarn. The tutorials all make it seem as though it's as simple as 'yarn add xxx' but I seem to be missing something. Thank you.
What you're looking for is the webpacker gem, which ships by default with Rails 5.1+ but can be used with Rails 4.2+. Get that set up, then follow these steps to get a custom Modernizr build running in your Rails app:
Loader
Install the loader for modernizr:
$ yarn install webpack-modernizr-loader
Modernizr Configuration
Download your desired modernizr config from the modernizr site. Visit a link like this:
https://modernizr.com/download?-appearance-backgroundblendmode-backgroundcliptext-backgroundsize-bgpositionxy-borderradius-boxshadow-boxsizing-canvas-canvastext-cssgradients-csspointerevents-fontface-generatedcontent-inputtypes-lastchild-mediaqueries-multiplebgs-opacity-svg-touchevents-setclasses-dontmin-cssclassprefix:mod_
Then configure your build, click "Build" in the upper right-hand corner, and download "Command Line Config".
Then convert it from JSON to a module and save it as config/webpack/.modernizrrc.js (note the leading period in the filename), like so:
"use strict";
module.exports = {
minify: false,
options: [
"setClasses"
],
"feature-detects": [
"test/canvas",
"test/canvastext",
"test/inputtypes",
"test/svg",
"test/touchevents",
"test/css/appearance",
"test/css/backgroundblendmode",
"test/css/backgroundcliptext",
"test/css/backgroundposition-xy",
"test/css/backgroundsize",
"test/css/borderradius",
"test/css/boxshadow",
"test/css/boxsizing",
"test/css/fontface",
"test/css/generatedcontent",
"test/css/gradients",
"test/css/lastchild",
"test/css/mediaqueries",
"test/css/multiplebgs",
"test/css/opacity",
"test/css/pointerevents"
]
};
Custom Configuration
Next, create a custom webpack config file as config/webpack/custom.js:
const path = require("path");
module.exports = {
module: {
rules: [
{
loader: "webpack-modernizr-loader",
test: /\.modernizrrc\.js$/
}
]
},
resolve: {
alias: {
modernizr$: path.resolve(__dirname, "./.modernizrrc.js")
}
}
};
Expose Configuration
Make your config/webpack/environment.js look like this:
const { environment } = require("#rails/webpacker");
const customConfig = require('./custom');
environment.config.merge(customConfig);
module.exports = environment;
Import Modernizr
Add the following line to app/javascript/packs/application.js:
import modernizr from 'modernizr';
Load Your Pack
Add this to your layout:
<%= javascript_pack_tag "application", defer: true %>
Voila
Load up your site in a browser, inspect, and confirm that (a) modernizr CSS classes have been added to the DOM, and (b) you aren't seeing any webpack compilation errors in the console.
Further Reading
I came upon this question when I was looking to set up modernizr using webpacker in a Rails 5 app, saw the question was unanswered, and figured it out myself. If you want to know how all of this works, I suggest reading the docs for webpacker and webpack-modernizr-loader.
Gruntfile.js is located at project root/Gruntfile.js
asset_compress.ini is located at project root/app/Config/asset_compress.ini
Tests are written using Jasmine, and the specs all locate in project root/tests/**/*
The following is a stripped-down Gruntfile. If you need more, feel free to ask:
module.exports = function(grunt) {
'use strict';
grunt.initConfig({
jasmine: {
test: {
src: [
'node_modules/jasmine-expect/dist/jasmine-matchers.js',
'app/webroot/js/libraries/jquery-2.0.js',
'app/webroot/js/api/ClassUtility.js',
'app/webroot/js/api/**/*.js'
],
options: {
log: true,
specs: [
'tests/app/webroot/js/api/ClassUtility.spec.js',
'tests/**/*.spec.js'
]
}
}
}
});
};
ClassUtility (and its specification) need to be loaded before any other part of the API, because it contains everything all other "classes" rely on. This is why it's declared specifically above all other api classes.
However, I have many(!) dependencies and many other files that I need, and they're all present in a (rather large) asset_compress.ini. Ideally, I would want to keep that single ini file as the only list and have my Gruntfile read from that list to know what source files it should load.
TLDR:
How would I configure my Gruntfile with the content of my ini file?
As bfred.it suggested, there were plenty of node packages that can parse .ini files. However, none of them worked the way I wanted them to work so I decided to create my own.
The source code, documentation, instructions and anything else you may desire can be found here: https://bitbucket.org/skelware/node-file-parser/
Feel free to request features on its issue tracker!
The easy way to load and parse an ini file in node:
First install on command line:
npm install parse-ini
Then in the code:
var iniParser = require('parse-ini');
var parsedIni = iniParser.parse('yourfile.ini');
// job done, you can use results in parsedIni:
console.log(parsedIni.sectionName.variableName);
console.log(parsedIni.variableWithoutSectionName);
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 have a Javascript project with multiple subdirectories, each its own individual project. I could just use one massive Gruntfile with different tasks for each project, but I'd rather have a Gruntfile in each subfolder. A typical file structure would be this
main_folder/
project_1
src
js/
dist/
doc/
Gruntfile.js
package.json
package.json
node_modules/
And then repeat the file structure for each project
Here is my Gruntfile inside project_1
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
};
It has fewer tasks than I will use, but the errors are still there. Whenever I try to run grunt, I get the error message Local Npm module "grunt-contrib-uglify" not found. Is it installed?, even though I have it installed in node_modules.
How can I specify the location of node_modules, or do I have to reinstall node_modules inside each folder?
I think you can still keep everything in the same place if you tell Grunt more explicitly where to find your plugins. For example, here's a bit from one of my Gruntfiles:
grunt.loadTasks tasks for tasks in grunt.file.expand '../node_modules/grunt-*/tasks'
As a side note: I faced exactly the same choice you did, but made the opposite choice: a single Gruntfile for the whole project and created a symlink to it from each project sub-directory. It's turned out to be a very easy way to keep things together in one place, and side-steps a lot of confusing issues like the one you're facing.
Another good way to solve this might be the use of subgrunt. It let's you configure various targets for your subprojects and has the option npmInstall, which "Determines wether npm install will be ran for the sub-project (thus installing dev dependencies)."
In my index.html file, I would like to include a different javascript source file in production than I use in development. I am using requirejs in development and would like to use the single minified file in production.
The project
https://github.com/CaryLandholt/AngularFun
does exactly what I would like.
In my project, I am trying to get grunt to run the template task but I am running into problems with it knowing how to complete the task: "Task 'template' not found".
I don't see anything obvious in the AngularFun project's dependencies that would allow grunt to correctly process the template task, but the project builds correctly. What am I missing?
I am asking here because I have seen several questions dealing with different files in prod/dev and the AngularFun project looks like a nice way to do it.
I have a Gruntfile with the following in the initConfig:
template: {
dev: {
files: {
"index.html": "index.template"
},
environment: "dev"
},
prod: {
files: "<% template.dev.files %>",
environment: "prod"
}
}
I also have the following as my grunt default:
grunt.registerTask("default", ["template:dev"]);
The template task is located in grunt-hustler, an npm package, which must be listed as a dependency in the package.json file in order for npm install to locate it and make it available for your project.
My documentation for grunt-hustler is seriously lacking.