I am sure I am missing something. I am trying to repurpose a gruntfile that worked on one project into a new project. The file runs and starts a server instance, but not at the port I have set, and it does not "go into watch mode".
The grunt command results in
Opening server for /Users/stevelombardi/Documents/command-central/cc on port 1337.
And indeed if I open my browser to http://127.0.0.1:1337 I see the home page. However, I expected port 9000 (see gruntfile) and for it to watch for changes to my files.
Here is the gruntfile. What did I mess up here?
'use strict';
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
options: {
livereload: true,
},
html: {
files: [
'{,*/}*.html'
]
},
sass: {
files: ['sass/{,*/}*.scss'],
tasks: ['sass:app'],
options: {
livereload: false
}
},
js: {
files: ['scripts/{,*/}*.js']
},
css: {
files: ['css/*.css'],
},
gruntfile: {
files: ['Gruntfile.js']
}
},
sass: {
app: {
options: {
style: 'compact',
sourcemap: 'auto'
},
files: {
'css/styles.css': 'sass/styles.scss',
}
}
},
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '127.0.0.1',
livereload: 35729
},
livereload: {
options: {
open: true,
base: ''
}
},
livepreview: {
options: {
open: true,
base: ''
}
}
}
});
grunt.registerTask('default', [
'sass',
'connect:livepreview',
'watch'
]);
};
I have no idea why, but this Gruntfile works fine now. I deleted my node_modules folder and package.json, then re-inititalized a new one and installed these modules:
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-connect": "^0.8.0",
"grunt-contrib-sass": "^0.8.1",
"grunt-contrib-watch": "^0.6.1",
"load-grunt-tasks": "^1.0.0"
}
and it works as i expected it to.
Here is what works for me (modified mine to fit your situation) - i think the "open" will help you:
in my gruntfile.settings.json:
"webServer": {
"port": 9000
}
outside of the tasks i have:
function mountFolder(connect, dir) {
path = path || require('path');
return connect.static(path.resolve(dir));
}
then my connect looks like this:
connect: {
livereload: {
options: {
port: settings.webServer.port,
hostname: '*',
middleware: function (connect) {
livereload = livereload || require('connect-livereload');
return [
livereload(),
mountFolder(connect, '.'),
expireHeaders
];
}
}
},
web: {
options: {
port: settings.webServer.port,
hostname: '*',
middleware: function (connect) {
return [
mountFolder(connect, '.'),
];
}
}
}
},
open: {
web: {
path: 'http://localhost:<%= connect.web.options.port %>'
}
}
and finally
grunt.task.run([
'web',
'connect:livereload',
'open:web',
'watch'
])
Otherwise, the only thing I can think of is perhaps something else is using that port already?
Related
I have a grunt project and I am using sass and jade together. I want to have a task for sass when developing where the style would be expanded for troubleshooting and a task for when I 'finish' the project and then the style would be compressed. I am new to grunt and don't know how to do it.
My gruntfile
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
jade: {
compile: {
options: {
pretty: true,
nospawn: false
},
files: {
'index.html' : 'src/index.jade'
}
}
},
sass: {
dist: {
options: {
style: 'expanded',
nospawn: false
},
files: {
'build/css/app.css' : 'src/sass/app.sass'
}
}
},
watch: {
jade: {
files: 'src/**/*.jade',
tasks: ['jade']
},
css: {
files: 'src/sass/**/*.sass',
tasks: ['sass']
},
options: {
livereload: true,
nospawn: false
}
},
connect: {
server: {
options: {
port: 9000,
base: '.',
hostname: '0.0.0.0',
protocol: 'http',
livereload: true,
open: true
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-jade');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.registerTask('default', ['connect', 'watch']);
};
To get compressed css instead of expanded, you would first need to make another sass-task (so within sass:{}), call it finish: for instance and change the compression setting.
It should look something like this:
finish: {
options: {
style: 'compressed',
nospawn: false
},
files: {
'build/css/app.css' : 'src/sass/app.sass'
}
}
Then after grunt.registerTask('default', ['connect', 'watch']);
you can add another task, ie finish that should like:
grunt.registerTask('finish', ['sass:finish']);
To run it you would type grunt finish on the command line.
I am trying to register a custom task that combines the connect and watch task on grunt, but it seems like it is just running the first element(task) of the array on the function grunt.registerTask. In this situation, it is just running the watch command, not the connect.
'use strict';
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
connect: {
server: {
options: {
port: '8000',
protocol: 'http',
hostname: 'localhost',
base: 'app',
keepalive: true,
livereload: true,
open: true
}
}
},
wiredep: {
task: {
src: ['app/index.html'],
}
},
jshint: {
options: {
reporter: require('jshint-stylish'),
jshintrc: '.jshintrc'
},
all: [
'GruntFile.js',
'app/scripts/*',
'test/spec/*'
]
},
sass: {
dist: {
files: {
'app/stylesheets/main.css': 'app/sass/main.sass'
},
options: {
compass: true
}
}
},
watch: {
options: {
livereload: true
},
styles: {
files: ['app/sass/*.sass'],
tasks: ['sass'],
options: {
livereload: true
}
},
scripts: {
files: ['app/scripts/*.js', 'GruntFile.js'],
tasks: ['jshint'],
options: {
livereload: true
}
},
bower: {
files: ['bower.json'],
tasks: ['wiredep']
}
}
});
// ========================================================
// Loading npm tasks
// ========================================================
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-wiredep');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
// ========================================================
// Register npm tasks
// ========================================================
grunt.registerTask('default', ['connect', 'wiredep', 'jshint', 'sass', 'watch']);
grunt.registerTask('serve',['watch', 'connect:server']);
// ========================================================
};
How can I work this two tasks together with registerTask function?
I am running grunt-contrib-watch 0.6.1 and have included livereload blocks in my gruntfile.js. I also included livereload.js call in my html:
<script type="text/javascript" src="http://myste.com:35729/livereload.js"></script>
When I run the server using my dev env everything seems to start correctly.
grunt dev
Running "env:dev" (env) task
Running "concurrent:dev" (concurrent) task
Running "nodemon:dev" (nodemon) task
[nodemon] v1.2.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node server.js`
Application Started on port 3000
When I make a change I can see the server reload in my ssh console, but livereload.js fails to load:
When I go to the port location where it should be http://myste.com:35729/livereload.js I get the standard "webpage not available" response. There also seems to be no server running on http://myste.com:35729/ at all.
I also include my gruntfile.js here for completeness
'use strict';
module.exports = function (grunt) {
var watchFiles = {
serverViews: ['app/views/**/*.*'],
serverJS: ['gruntfile.js', 'server.js', 'config/**/*.js', 'app/**/*.js'],
clientViews: ['public/views/**/*.html'],
clientJS: ['public/js/**/*.js'],
clientSASS: 'public/styles/sass/**/*.{scss,sass}',
clientCSS: ['public/styles/css/**/*.css']
};
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
env: {
dev: {
NODE_ENV: 'development'
},
prod: {
NODE_ENV: 'production'
}
},
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
}
},
clientSASS: {
files: watchFiles.clientSASS,
tasks: ['sass:dev'],
options: {
livereload: true,
spawn: false
}
},
clientCSS: {
files: watchFiles.clientCSS,
tasks: ['csslint'],
options: {
livereload: true
}
},
},
nodemon: {
dev: {
script: 'server.js'
}
},
nodeunit: {
dev: {
all: ['app/test/**/*_test.js'],
options: {
reporter: 'tap',
reporterOutput: 'tests.tap',
reporterOptions: {
output: 'outputdir'
}
}
}
},
jshint: {
dev: {
all: {
src: watchFiles.clientJS.concat(watchFiles.serverJS),
options: {
jshintrc: true
}
}
}
},
uglify: {
prod: {
my_target: {
files: {
'public/js/all.min.js': ['public/js/library/jquery.js', 'public/js/library/modernizr.js', 'public/js/library/selectivizr.js', 'public/js/library/delfin.js']
}
}
}
},
sass: {
dev: {
options: {
style: 'expanded'
},
files: {
'public/styles/css/style.css': 'public/styles/scss/style.scss' // 'destination': 'source'
}
}
},
cssmin: {
prod: {
files: {
'public/styles/css/style.min.css': 'public/styles/css/style.css'
}
}
},
csslint: {
dev: {
options: {
csslintrc: '.csslintrc',
},
all: {
src: watchFiles.clientCSS
}
}
},
concurrent: {
dev: {
target: {
tasks: ['nodemon', 'watch'],
options: {
logConcurrentOutput: true
}
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-csslint');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express-server');
grunt.loadNpmTasks('grunt-concurrent');
grunt.loadNpmTasks('grunt-nodemon');
grunt.loadNpmTasks('grunt-env');
grunt.registerTask('dev', ['env:dev', 'concurrent', 'nodemon', 'watch', 'jshint', 'nodeunit', 'sass']);
grunt.registerTask('prod', ['env:prod', 'cssmin', 'uglify', 'nodemon']);
};
You try to run nodemon and watch tasks twice. First, when you run concurrent task and second when you call themselves.
Change your concurrent task config to
concurrent: {
tasks: ['nodemon', 'watch'],
options: {
logConcurrentOutput: true
}
},
And remove extra tasks from grunt dev declaration:
grunt.registerTask('dev', ['env:dev', 'concurrent', 'jshint', 'nodeunit', 'sass']);
How to achieve a 'proxy' (similar to grunt-connect-proxy) option with webpack-dev-server ?
I am using webpack and webpack-dev-server with Grunt. A task in Gruntfile.js (below code) is able to start the server on port 8080. I want to add proxy setup for all the backend data requests (context URL /ajax/*).
"webpack-dev-server": {
options: {
webpack: webpackConfig,
publicPath: "/src/assets"
},
start: {
keepAlive: true,
watch: true
}
}
In the webpack config, you can use devServer.proxy like this:
proxy: {
'/ajax/*': 'http://your.backend/'
}
I ended up using 'grunt-contrib-connect' and 'grunt-connect-proxy' with 'webpack-dev-middleware'. So, I can have proxy middleware to handle all my data requests and webpack middleware to handle static bundle file requests.
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
var mountFolder = function (connect, dir) {
return connect.static(require('path').resolve(dir));
};
var prepareDevWebpackMiddleware = function() {
webpackConfig.devtool = "eval-source-map";
var compiler = webpack(require("./webpack.config.js"));
return webpackDevMiddleware(compiler, {
publicPath : "/assets"
});
};
---- GRUNT TASK ----
connect: {
options: {
port: 8080,
hostname: 'localhost',
livereload : true
},
proxies: [{
context: '/api',
host: 'localhost',
port: 8000
}],
livereload: {
options: {
middleware: function (connect) {
return [
prepareDevWebpackMiddleware(),
proxySnippet,
mountFolder(connect, 'src')
];
}
}
}
}
Webpack dev server proxy api has been changed since v1.15
https://github.com/webpack/webpack-dev-server/issues/562
glob * should be ** to proxy all request
devServer: {
proxy: {
'**': 'http://local.ui.steelhouse.com/'
},
}
webpack-dev-server didn't know how to deal with your content, so it has a config which can proxy all your request to specific server handle content.
for example:
you should run 'grunt content' to start your content server
then run 'grunt serve' to start develop
'use strict';
var webpackDistConfig = require('./webpack.dist.config.js'),
webpackDevConfig = require('./webpack.config.js');
var mountFolder = function (connect, dir) {
return connect.static(require('path').resolve(dir));
};
module.exports = function (grunt) {
// Let *load-grunt-tasks* require everything
require('load-grunt-tasks')(grunt);
// Read configuration from package.json
var pkgConfig = grunt.file.readJSON('package.json');
grunt.initConfig({
pkg: pkgConfig,
webpack: {
options: webpackDistConfig,
dist: {
cache: false
}
},
'webpack-dev-server': {
options: {
hot: true,
port: 8000,
webpack: webpackDevConfig,
publicPath: '/assets/',
contentBase: {target : 'http://localhost:13800'},
},
start: {
keepAlive: true,
}
},
connect: {
options: {
port: 8000,
keepalive: true,
},
proxies: [
{
context: '/',
host: '127.0.0.1',
port: 8031,
https: false,
xforward: false
}
],
dev: {
options: {
port : 13800,
middleware: function (connect) {
return [
mountFolder(connect, pkgConfig.src),
require('grunt-connect-proxy/lib/utils').proxyRequest
];
}
}
},
dist: {
options: {
middleware: function (connect) {
return [
mountFolder(connect, pkgConfig.dist),
require('grunt-connect-proxy/lib/utils').proxyRequest
];
}
}
}
},
open: {
options: {
delay: 500
},
dev: {
path: 'http://localhost:<%= connect.options.port %>/webpack-dev-server/'
},
dist: {
path: 'http://localhost:<%= connect.options.port %>/'
}
},
karma: {
unit: {
configFile: 'karma.conf.js'
}
},
copy: {
dist: {
files: [
// includes files within path
{
flatten: true,
expand: true,
src: ['<%= pkg.src %>/*'],
dest: '<%= pkg.dist %>/',
filter: 'isFile'
},
{
flatten: true,
expand: true,
src: ['<%= pkg.src %>/styles/*'],
dest: '<%= pkg.dist %>/styles/'
},
{
flatten: true,
expand: true,
src: ['<%= pkg.src %>/images/*'],
dest: '<%= pkg.dist %>/images/'
},
]
}
},
clean: {
dist: {
files: [{
dot: true,
src: [
'<%= pkg.dist %>'
]
}]
}
}
});
grunt.registerTask('serve', function (target) {
if (target === 'dist') {
return grunt.task.run(['configureProxies', 'build', 'open:dist', 'connect:dist']);
}
grunt.task.run([
'open:dev',
'webpack-dev-server'
]);
});
grunt.registerTask('content', ['configureProxies', 'connect:dev']);
grunt.registerTask('test', ['karma']);
grunt.registerTask('build', ['clean', 'copy', 'webpack']);
grunt.registerTask('default', []);
};
We're using Mean.io for a project and getting erratic behavior from Grunt.
When we make changes on different files (while Grunt is running, of course), Grunt may detect the changes or not. HTML changes are usually detected by Grunt, but CSS/JS changes not.
And even worst, we often have to reboot (CTRL+C, grunt -f) Grunt to make it displays the project correctly because it prints random errors that actually don't exist. And thus the page is not displayed correctly in the browser.
For instance:
/vagrant/vavel/node_modules/dependable/index.js:115
throw new Error("dependency '" + name + "' was not registered");
^
Error: dependency 'access' was not registered
Or:
/vagrant/vavel/node_modules/mongoose/lib/index.js:323
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "User".
Use mongoose.model(name, schema)
These errors just disappear if we restart Grunt again (using "rs" or CTRL+C + grunt -f).
In fact, sometimes there is not any error displayed in console and the page doesn't show up well.
Are we doing something wrong with ow we are using Grunt?
Gruntfile.js
cat Gruntfile.js
'use strict';
var paths = {
js: ['*.js', 'test/**/*.js', '!test/coverage/**', '!bower_components/**', 'packages/**/*.js', '!packages/**/node_modules/**'],
html: ['packages/**/public/**/views/**', 'packages/**/server/views/**'],
css: ['!bower_components/**', 'packages/**/public/**/css/*.css']
};
module.exports = function(grunt) {
if (process.env.NODE_ENV !== 'production') {
require('time-grunt')(grunt);
}
// Project Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
assets: grunt.file.readJSON('config/assets.json'),
clean: ['bower_components/build'],
watch: {
js: {
files: paths.js,
tasks: ['jshint'],
options: {
livereload: true
}
},
html: {
files: paths.html,
options: {
livereload: true,
interval: 500
}
},
css: {
files: paths.css,
tasks: ['csslint'],
options: {
livereload: true
}
}
},
jshint: {
all: {
src: paths.js,
options: {
jshintrc: true
}
}
},
uglify: {
core: {
options: {
mangle: false
},
files: '<%= assets.core.js %>'
}
},
csslint: {
options: {
csslintrc: '.csslintrc'
},
src: paths.css
},
cssmin: {
core: {
files: '<%= assets.core.css %>'
}
},
nodemon: {
dev: {
script: 'server.js',
options: {
args: [],
ignore: ['node_modules/**'],
ext: 'js,html',
nodeArgs: ['--debug'],
delayTime: 1,
cwd: __dirname
}
}
},
concurrent: {
tasks: ['nodemon', 'watch'],
options: {
logConcurrentOutput: true
}
},
mochaTest: {
options: {
reporter: 'spec',
require: [
'server.js',
function() {
require('meanio/lib/util').preload(__dirname + '/packages/**/server', 'model');
}
]
},
src: ['packages/**/server/tests/**/*.js']
},
env: {
test: {
NODE_ENV: 'test'
}
},
karma: {
unit: {
configFile: 'karma.conf.js'
}
}
});
//Load NPM tasks
require('load-grunt-tasks')(grunt);
//Default task(s).
if (process.env.NODE_ENV === 'production') {
grunt.registerTask('default', ['clean', 'cssmin', 'uglify', 'concurrent']);
} else {
grunt.registerTask('default', ['clean', 'jshint', 'csslint', 'concurrent']);
}
//Test task.
grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);
// For Heroku users only.
// Docs: https://github.com/linnovate/mean/wiki/Deploying-on-Heroku
grunt.registerTask('heroku:production', ['cssmin', 'uglify']);
};