Beginning with Grunt, which I love but cannot make it work as I get continously an error with my sass implementation. I get the following alerts:
Danis-MacBook-Pro:020 DanielRamirez$ grunt
Running "concat:dist" (concat) task
File "js/build/production.js" created.
Running "uglify:build" (uglify) task
File js/build/production.min.js created.
>> No "sass" targets found.
Warning: Task "sass" failed. Use --force to continue.
Aborted due to warnings.
Danis-MacBook-Pro:020 DanielRamirez$
If I --force I get the following:
Danis-MacBook-Pro:020 DanielRamirez$ grunt
Running "concat:dist" (concat) task
File "js/build/production.js" created.
Running "uglify:build" (uglify) task
File js/build/production.min.js created.
>> No "sass" targets found.
Warning: Task "sass" failed. Use --force to continue.
Aborted due to warnings.
Danis-MacBook-Pro:020 DanielRamirez$
This is my Gruntfile.js:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// 2. Configuration for concatinating files goes here.
// Concatonate various files into one
concat: {
dist: {
src: [
'js/vendor/*.js', // All JS in the libs folder
'js/plugin.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
},
// Creates a minified version of the javascript files of the project
uglify: {
build: {
src: ['js/vendor/*.js', 'js/plugin.js', 'js/global.js'],
dest: 'js/build/production.min.js'
}
},
// Minifies automatically the images of the project
// imagemin: {
// dynamic: {
// files: [{
// expand: true,
// cwd: 'images/',
// src: ['**/*.{png,jpg,gif}'],
// dest: 'images/build/'
// }]
// }
// },
// Watches for changes done on the project and builds the commands if neccesary
watch: {
options: {
livereload: true,
},
scripts: {
files: ['js/*.js'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
},
},
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/style.css': 'sass/style.scss'
}
}
},
css: {
files: ['css/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
// grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-watch');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['concat', 'uglify', 'sass', 'compass', 'watch']);
};
Any ideas?
Yes, what you've done is put the entire Sass configuration inside the watch config. Grunt does not work this way. Instead, change your config to something like this:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// 2. Configuration for concatinating files goes here.
// Concatonate various files into one
concat: {
dist: {
src: [
'js/vendor/*.js', // All JS in the libs folder
'js/plugin.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
},
// Creates a minified version of the javascript files of the project
uglify: {
build: {
src: ['js/vendor/*.js', 'js/plugin.js', 'js/global.js'],
dest: 'js/build/production.min.js'
}
},
// Compile sass to css
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/style.css': 'sass/style.scss'
}
}
},
// Minifies automatically the images of the project
// imagemin: {
// dynamic: {
// files: [{
// expand: true,
// cwd: 'images/',
// src: ['**/*.{png,jpg,gif}'],
// dest: 'images/build/'
// }]
// }
// },
// Watches for changes done on the project and builds the commands if neccesary
watch: {
options: {
livereload: true,
},
scripts: {
files: ['js/*.js'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
},
},
css: {
files: ['css/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
// grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-watch');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['concat', 'uglify', 'sass', 'compass', 'watch']);
};
Related
My "older" web application uses Grunt and Webpack, but I am wondering if I can remove Grunt completely and still have the same functionality with just Webpack? Or should I replace Grunt with another technology? I've noticed grunt development slow to a crawl, and as new security warnings arise, I am having difficulty upgrading packages.
Below is my grunt file which performs a few basic tasks and allows me to run some very handy commands like "grunt dev" (for packaging dev bundle), "grunt dev-watch" (for packaging and watching for changed files), and "grunt prod" (for production bundle). Additionally, I use maven to build my web application, so I can define these commands from within the pom.xml depending on the build profile (development vs production)
Below: Grunt file, Webpack (common), and Webpack (dev)
gruntfile.js
/**
* Grunt Settings
*
* Contains settings for Grunt tasks that allow for development and production environments
*
* Usage (in bash shell, /webapp directory):
* grunt dev
* grunt dev-watch
* grunt prod
*/
// Define webpack configuration files
const webpackConfig_dev = require('./webpack.dev.js');
const webpackConfig_prod = require('./webpack.prod.js');
module.exports = function(grunt) {
let baseDir = ".";
// Set fileVersion from command line arguments
let fileVersion = grunt.option('fileVersion');
if (typeof fileVersion === 'undefined') {
fileVersion = 'dev';
}
fileVersion = fileVersion.trim();
grunt.initConfig({
// Identify which packages to load
pkg: grunt.file.readJSON('package.json'),
// Remove old files
clean: {
build: {
src: [
// js files
baseDir + '/js/dist',
// css files
baseDir + '/styles/*.css',
baseDir + '/styles/*.map',
]
}
},
// Crunch style files (eg *.scss)
sass: {
options:{
implementation: require('node-sass'),
sourceMap: true,
outputStyle: 'expanded'
},
dist: {
files: [{
src: baseDir + '/styles/main.scss',
dest: baseDir + '/styles/main.' + fileVersion + '.css',
}]
}
},
// Modifications after main.css is created
postcss: {
options: {
map: true,
processors: [
require('autoprefixer')
]
},
dist: {
src: baseDir + '/styles/main.' + fileVersion + '.css'
}
},
// Copy jquery external library to the dist/ folder
copy: {
main: {
files: [
{
expand: true,
cwd: 'node_modules/jquery/dist',
src: 'jquery.min.js',
dest: baseDir + '/js/dist'
},
],
},
},
// Run webpack (depending on development versus production)
webpack: {
dev: webpackConfig_dev(fileVersion),
prod: webpackConfig_prod(fileVersion),
},
// Enable live reloading of js/scss files
watch: {
css: {
files: [baseDir + '/styles/**/*.scss'],
tasks: ['sass']
},
js: {
files: [baseDir + '/js/src/**/*.js', '!' + baseDir + '/js/src/**/*.min.js'],
tasks: ['webpack:dev']
}
}
});
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-postcss');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-clean');
// Available Grunt tasks
// development
grunt.registerTask('default', ['dev']);
grunt.registerTask('dev', ['clean', 'sass', 'postcss', 'copy', 'webpack:dev']);
// development (and watches for changes of .js and .css files)
grunt.registerTask('dev-watch', ['sass', 'postcss', 'webpack:dev', 'watch']);
// production ready
grunt.registerTask('prod', ['clean', 'sass', 'postcss', 'copy', 'webpack:prod']);
};
webpack.common.js
/**
* Webpack settings file :: Common (development & production)
*/
const ESLintPlugin = require('eslint-webpack-plugin');
const baseDir_js = "./js";
module.exports = {
// Define the "source" entry point for the application (or sub apps)
entry: {
main: baseDir_js + '/src/index.js',
admin: baseDir_js + '/src/admin.js',
sysAdmin: baseDir_js + '/src/sysAdmin.js',
},
// Let grunt know we have external libraries available
externals: {
jquery: 'jQuery',
google: 'google',
Stripe: 'Stripe',
},
module: {
rules: [
// process css files
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ],
},
// process images/fonts -> base64
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
type: 'asset/inline',
}
],
},
plugins: [new ESLintPlugin()],
};
webpack.dev.js
/**
* Webpack settings file :: Development
*/
// Import common settings
const {merge} = require('webpack-merge');
const common = require('./webpack.common.js');
const baseDir_js = "./js";
const path = require('path');
// Merge settings with "common"
module.exports = (fileVersion) => merge(common, {
mode: 'development',
// Use full source map
devtool: 'inline-source-map',
// Output entire code base to one file
output: {
filename: '[name].' + fileVersion + '.js',
// store in "dist/" directory
path: path.resolve(baseDir_js, 'dist'),
},
});
I am new to webpack and I'm trying to implement it in my project. I'm also using Compass for my .scss files.
I included all my scss files in my entrypoint (see the webpack configuration down below) and I have this error:
Error line 1: Function sprite-map doesn't support keyword arguments
The scss file that causes the module build to fail:
$icons: sprite-map("icons/icons-1/k/*.png", $spacing: 10px);
#each $i in sprite_names($icons) {
.k-#{$i}{
background-position: sprite-position($icons, $i, 0, 0, true);
}
}
.k-121, .k-122, .k-123, .k-124, .k-125, .k-126, .k-127, .k-128, .k-129, .k-130, .k-131, .k-132, .k-133, {
background-image: $icons;
background-repeat: no-repeat;
}
But looking at the documentation, it is possible to use keyword arguments, isn't it ?
Here is my webpack.config.js :
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: path.resolve(__dirname, 'scripts/app.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.s?css$/,
loaders: 'sass-loader'
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(jpe?g|png|gif|svg)$/,
loader: 'file-loader?name=/dist/img/[name].[ext]'
},
{
test: /\.(eot|otf|ttf|woff|woff2)$/,
loader: 'file-loader?name=dist/fonts/[name].[ext]'
}
]
},
devtool: 'source-map',
plugins: [
new HtmlWebpackPlugin()
]
};
Thanks for your help !
I am receiving the error "file to import not found or unreadable: "compass"" when I am attempting to run my "grunt" task.
"Running "sass:app" (sass) task"
Warning: build/global/css/base:1: file to import not found or unreadable: "compass"
Here is my gruntfile:
module.exports = function(grunt) {
// COMMANDS
// comple css and js - $ grunt
// optim - run $ grunt imgoptim
// FILE STRUCTURE
// css/app.css, css/app.min.css
// build/global/css/*.scss
// build/global/css/**/*.scss
// build/components/componentname/css/*.scss
// css/singlefile.css, css/singlefile.min.css
// build/global/solo/css/*.scss
// js/app.js, js/app.min.css
// build/global/js/*.js
// build/global/js/**/*.js
// build/components/componentname/js/*.js
// singlefile.js, singlefile.min.js
// build/global/solo/js/*.js
var watch = {};
var uglify = {};
var concat = {};
var sass = {};
var cssmin = {};
var js_files = [
'build/global/js/vendor/respond.js',
'build/global/js/vendor/AccessifyHTML5.js',
'build/global/js/vendor/jquery.equalHeights.js',
'build/global/js/vendor/jquery.infinitescroll.js',
'build/global/js/vendor/jquery.verticalcentering.js',
'build/global/js/global.js',
'build/components/**/js/vendor/*.js',
'build/components/**/js/*.js'
];
// WATCH =========================================/
watch.solocss = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['css/*.css', '!css/*.min.css']
},
files: 'build/solo/css/*.scss',
tasks: [
'newer:sass:solo'
]
};
watch.appcss = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['css/*.css', '!css/*.min.css']
},
files: [
'build/global/css/**/*.scss',
'build/global/css/*.scss',
'build/components/**/*.scss'
],
tasks: [
'sass:app',
'concat:appcss',
'sass:solo' // run solo here too incase there are changes to sass vars etc
]
};
watch.cssmin = {
files: ['css/*.css', '!css/*.min.css'],
tasks: [
'newer:cssmin:compress',
]
};
watch.solojs = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['js/*.js', '!js/*.min.js']
},
files: 'build/solo/js/*.js',
tasks: [
'newer:uglify:solojsdev',
'newer:uglify:solojsprod'
]
};
watch.globaljs = {
options: { livereload: true }, // currently not working correctly, should be able to remove this line
livereload: {
options: { livereload: true },
files: ['js/*.js', '!js/*.min.js']
},
files: ['build/global/js/*.js', 'build/global/js/**/*.js', 'build/components/**/*.js'],
tasks: [
'concat:appjs',
'uglify:appjs'
]
};
// CSS COMPLILATION ====================================/
//solo files, compiled to /css/file.css
sass.solo = {
options:{
includePaths: require('node-bourbon').with('build'),
sourceComments: true,
style: 'expanded', // compile in expanded format with comments for dev,
compass: true
},
files: [{
expand: true,
src: watch.solocss.files, // where it's coming from
dest: 'css', // where it's going
flatten: true, // removes folder tree
ext: '.css', // what file extension to give it - standard
extDot: 'last'
}]
};
// app scss files, compiled individually to /css/build/...
sass.app = {
options:{
includePaths: require('node-bourbon').with('build'),
style: 'expanded', // compile in expanded format with comments for dev
sourceComments: 'normal',
},
files: [{
//cwd: 'build',
expand: true,
src: watch.appcss.files, // where it's coming from
dest: 'css', // where it's going
ext: '.css' // what file extension to give it - standard
}]
};
// concat app.css files
concat.appcss = {
src: [
'css/build/global/css/**/*.css',
'css/build/global/css/*.css',
'css/build/components/**/*.css'
],
dest: 'css/app.css',
seperator: '\n'
};
// create compressed version of all css files for prod
cssmin.compress = {
files: [{
expand: true,
cwd: 'css/',
src: ['*.css', '!*.min.css', '!editor.css'],
dest: 'css/',
ext: '.min.css',
extDot: 'last'
}]
}
// JAVASCRIPT COMPLILATION ============================/
// concat app.js files
concat.appjs = {
src: js_files,
dest: 'js/app.js',
separator: ';'
};
// minify app.js
uglify.appjs = {
files: {
'js/app.min.js': [
'js/app.js'
]
}
};
// uglify solo files for dev
uglify.solojsdev = {
options: {
compress: false,
mangle: false,
beautify: true
},
files: [{
expand: true,
flatten: true, // removes folder tree
src: watch.solojs.files,
dest: 'js/'
}]
};
// uglify + minify solo files for prod
uglify.solojsprod = {
options: {
compress: true
},
files: [{
expand: true,
flatten: true, // removes folder tree
src: watch.solojs.files,
dest: 'js/',
ext: '.min.js',
extDot: 'last',
}]
};
// IMAGE OPTIMISATION ==========================/
imageoptim = {
optimise: {
src: ['images']
}
}
// GRUNT ======================================/
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: watch,
sass: sass,
concat: concat,
cssmin: cssmin,
uglify: uglify,
imageoptim: imageoptim
});
// DEPENDENT PLUGINS =========================/
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-imageoptim');
grunt.loadNpmTasks('grunt-newer');
// TASKS =====================================/
grunt.registerTask('default', [
'sass',
'concat',
'newer:cssmin',
'newer:uglify',
'watch'
]);
grunt.registerTask('imgoptim', [
'imageoptim'
]);
}
My directory structure looks like the following relative from the gruntfile.js:
/build/global/components/FOLDERS/*.scss files
/build/global/css/FOLDERS & *.scss files
/dist/*.css files
Here is my config.rb file in the same directory as the gruntfile:
http_path = "/"
css_dir = "css"
sass_dir = "build"
images_dir = "images"
javascripts_dir = "javascript"
I already have compass installed and all the node_modules.
I'm working on a multi-website project where all the website share the same structure:
-sites
-site1
-css
-scss
-site2
-css
-scss
In my gruntfile.js i have my sass task wrote this way:
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
pippo: {
files: {
'sites/site1/css/main.css': 'sites/site1/css/sass/main.scss',
'sites/site2/css/main.css': 'sites/site2/css/sass/main.scss',
}
}
}
is it possible to write it in this way?
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
pippo: {
files: {
'sites/**/css/main.css': 'sites/**/css/sass/main.scss'
}
}
}
I tested it and it is adding a new ** folder when I build it... Any advice?
after a couple of hours I found a working solution, at the very top of the grunt file I added:
module.exports = function(grunt) {
var fs = require('fs');
console.log("Inside the gruntfile");
//create dynamic list of scss file paths
var objDestSource = {
'public/css/main.css': 'public/css/sass/main.scss'
};
fs.readdirSync('sites').forEach(function(folder){
objDestSource['sites/'+folder+'/css/main.css'] = 'sites/'+folder+'/css/sass/main.scss';
});
console.log(objDestSource);
// end scss function
while in the grunt sass task I just changed to:
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
taskName: {
files: objDestSource
}
}
and the watch task:
watch: {
sass: {
files: [
'public/css/sass/**/*.scss',
'sites/**/css/sass/**/*.scss'
],
tasks: ['sass'],
options: {
spawn: false
}
}
}
This way I can add a new sub-website without have to edit the gruntfile each time!
I cloned the meanjs and running with npm install and grunt
at the start up it shows debugger listening on port 5858,
but when i open the chrome with
localhost:8080/debug?port=5858
it shows the webpage is not available.
is there anything i need to do to make the node-inspector debugger to work for meanjs ?
Ok, if you're using the Gruntfile from the Yeoman Generator (meanjs.org) as I presume, just run grunt debug instead of simply grunt in your console. Then the node inspector will be available at http://localhost:1337/debug?port=5858 if you have default settings like:
watch: {
serverViews: {
files: watchFiles.serverViews,
options: {
livereload: true
}
},
serverJS: {
files: watchFiles.serverJS,
tasks: ['jshint'],
options: {
livereload: true
}
},
clientViews: {
files: watchFiles.clientViews,
options: {
livereload: true,
}
},
clientJS: {
files: watchFiles.clientJS,
tasks: ['jshint'],
options: {
livereload: true
}
},
clientCSS: {
files: watchFiles.clientCSS,
tasks: ['csslint'],
options: {
livereload: true
}
}
},
nodemon: {
dev: {
script: 'server.js',
options: {
nodeArgs: ['--debug'],
ext: 'js,html',
watch: watchFiles.serverViews.concat(watchFiles.serverJS)
}
}
},
'node-inspector': {
custom: {
options: {
'web-port': 1337,
'web-host': 'localhost',
'debug-port': 5858,
'save-live-edit': true,
'no-preload': true,
'stack-trace-limit': 50,
'hidden': []
}
}
},
concurrent: {
default: ['nodemon', 'watch'],
debug: ['nodemon', 'watch', 'node-inspector'],
options: {
logConcurrentOutput: true,
limit: 10
}
}
And the main cli tasks are defined at the bottom of the gruntfile:
// Default task(s).
grunt.registerTask('default', ['lint', 'concurrent:default']);
// Debug task.
grunt.registerTask('debug', ['lint', 'concurrent:debug']);
You need to start the node inspector server, that one will listen on 8080:
node-inspector
Then you're ready to hit the debug URL