This has been working fine until "yesterday." I don't recall installing anything new on my dev machine. I can see nothing in my recent code changes that might have caused this behavior. This started happening right after a system restart. Running on Windows. My IDE is WebStorm.
I have a Javascript project which has a file with some large .mp4 video files in it. I open a command window and run
> grunt serve
and the browser comes up fine. If I browse to the resource:
http://localhost:9000/Themes/a1.mp4
the video plays in the browser. If I browse to
http://localhost:9000/Themes/a2.mp4
after about 6 seconds the error message in the title appears in my command window and the browser spins on, eventually timing out with ERR_EMPTY_RESPONSE
I have a variety of .mp4 files. Only the larger ones cause this issue (>400MB) smaller ones (<200MB) don't cause this issue.
Here's the relevant connect section of the gruntfile.js file. This was generated by Yeoman.
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect.static('test'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect().use(
'/app/styles',
connect.static('./app/styles')
),
connect.static(appConfig.app)
];
}
}
},
test: {
options: {
port: 9001,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect.static('test'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
}
},
dist: {
options: {
open: true,
base: '<%= yeoman.dist %>'
}
}
},
[... snip ...]
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'bowerRequirejs:app',
'concurrent:server',
'postcss:server',
'connect:livereload',
'watch'
]);
});
I've tried using grunt-connect instead. It serves the larger video file fine, but I don't know how to configure it to serve the same range of folders that the extract above is serving.
Related
I'm trying to add grunt-connect-proxy to my gruntfile.js in a yeoman generator-angular project (generator-angular 0.15.1) but I can't seem to get it to work since the way it's written changes and I'm inexperienced in how Grunt works.
I've read many posts about this and none are particularly up-to-date, and the gruntfile changes seemingly often in how it implements livereload middleware This makes the documentation for grunt-connect-proxy to not work in my case.
The tricky part is under livereload
This is how it looks in generator-angular gruntfile:
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
proxies: [{
context: '/api',
host: 'localhost',
port: 8080,
https: false,
xforward: false
}],
livereload: {
options: {
open: true,
// --- how the code looks like before I do anything
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use('/bower_components', connect.static('./bower_components')),
connect().use('/app/styles', connect.static('./app/styles')),
connect.static(appConfig.app)
];
}
}
},
...
When I look at the documentation it looks like this:
livereload: {
options: {
middleware: function (connect, options) {
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
// Setup the proxy
var middlewares = [require('grunt-connect-proxy/lib/utils').proxyRequest];
// Serve static files.
options.base.forEach(function(base) {
middlewares.push(connect.static(base));
});
// Make directory browse-able.
var directory = options.directory || options.base[options.base.length - 1];
middlewares.push(connect.directory(directory));
return middlewares;
}
}
}
Can someone help me translate the documentation to the new way of writing the middleware part?
Thanks!!
So I got some help and this is how it was solved:
livereload: {
options: {
open: true,
middleware: function(connect) {
var middlewares = [require('grunt-connect-proxy/lib/utils').proxyRequest];
return middlewares.concat(
connect.static('.tmp'),
connect().use('/bower_components', connect.static('./bower_components')),
connect().use('/app/styles', connect.static('./app/styles')),
connect.static(appConfig.app)
);
}
}
}
Hope this helps someone else too.
I'm running an Angular.js application and all the task management are made with grunt, for now I have three components that I'm watching in live reload, bower_components, invoices and users, eventually they are going to increase in number, so I would like to know if there's a way to call an external file like components.json and iterate through its n members. Here is my code:
// The grunt server settings
connect: {
options: {
port: 9000,
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect().use(
'/invoices',
connect.static(invoicesAppPathConfig.root)
),
connect().use(
'/users',
connect.static(usersAppPathConfig.root)
),
connect.static(secureAppPathConfig.app)
];
}
}
},
dist: {
options: {
open: true,
base: '<%= main.dist %>'
}
}
}
I have already created the component.json file:
{"data":[
{
"resource":"/bower_components",
"config":"./bower_components"
},
{
"resource":"/invoices",
"config":"invoicesAppPathConfig.root"
},
{
"resource":"/users",
"config":"usersAppPathConfig.root"
}
]}
And in the Gruntfile.js I created this variables, having in mind that I need to iterate in the content of data:
var components = require('./components.json');
var data = components.data;
Now I have the question, how can I do it this in the code?
middleware: function (connect) {
return [
connect.static('.tmp'),
// Here comes the data iteration
connect.static(secureAppPathConfig.app)
];
}
Thanks in advance.
Sure you can:
grunt.initConfig({
components: grunt.file.readJSON('components.json'),
[...]
});
More info on grunt.file here
You can also require it:
var components = require('./components.json');
Create the next variables:
var components = require('./components.json');
var data = components.data;
var arrayComponents = [];
Then in the options for livereload iterate the json data and add it to arrayComponents:
middleware: function (connect){
arrayComponents.push(connect.static('.tmp'));
// The modules to be watched are added
for(var i in data){
arrayComponents.push(connect().use(data[i].resource, connect.static(data[i].config)));
}
arrayComponents.push(connect.static(secureAppPathConfig.app));
return arrayComponents;
}
It works, but maybe it is not the most elegant solution.
I'm trying to use environment variables in my AngularJS to do environment-specific configuration. I'm using the Yeoman workflow which uses Grunt, and the grunt-ng-constant plugin is purported to help with environment-specific configuration. In following this tutorial, I set up my Gruntfile accordingly, but when I run grunt serve in the console, config.js is not written into /app/scripts/. Without config.js, I cannot inject the environment variable into the angular application.
Here's a snippet of my Gruntfile:
module.exports = function (grunt) {
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Automatically load required Grunt tasks
require('jit-grunt')(grunt, {
useminPrepare: 'grunt-usemin',
ngtemplates: 'grunt-angular-templates',
cdnify: 'grunt-google-cdn'
});
// Configurable paths for the application
var appConfig = {
app: require('./bower.json').appPath || 'app',
dist: '../server/dist'
};
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-ng-constant');
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
yeoman: appConfig,
ngconstant: {
// options for all environments
options: {
space: ' ',
wrap: '"use strict";\n\n {%= __ngModule %}',
name: 'config'
},
// Development/Testing environment
development: {
options: {
dest: '<%= yeoman.app %>/scripts/config.js'
},
constants: {
ENV: {
name: 'development',
apiEndpoint: 'http://localhost:3000'
}
}
},
// Production environment
production: {
options: {
dest: '<%= yeoman.dist %>/scripts/config.js'
},
constants: {
ENV: {
name: 'production',
apiEndpoint: 'http://productionUrl'
}
}
}
},
...
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'autoprefixer:server',
'connect:livereload',
'watch',
'ngconstant:development'
]);
});
...
What is generated is /.sass-cache and /.tmp in the same directory (client) as the Gruntfile.
My app file structure:
The ngconstant task is not being called because it is after the watch task. Modify the run block so the line 'ngconstant:development' is next to 'autoprefixer:server', so it is before connect & watch tasks. Don't forget to add a comma!
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'autoprefixer:server',
'ngconstant:development',
'connect:livereload',
'watch'
]);
Also, the app path might be wrong in the bower.json file. To be sure, modify the path to your app by changing appConfig so it looks like this:
var appConfig = {
app: 'app',
dist: '../server/dist'
}
I'm having problems to configure my grunt file to add refs (css & js) to my index.html
here's my project structure:
src/
demo/
index.html
app.js
bower_components/
angular/
angular.js
index.html:
<script src="./bower_components/angular/angular.js"></script>
<script src="../app.js"></script>
gruntFile:
connect: {
demo: {
options: {
port: 9000,
hostname: 'localhost',
open: true,
base: 'src/demo'
},
livereload: {
options: {
middleware: function(connect) {
return [
connect().use(
'/bower_components',
connect.static('./bower_components')
)
];
}
}
}
}
}
I don't know why, but index.html cannot find app.js or angular.js.
Some observations:
the web root is src/demo;
so /index.html maps to src/demo/index.html;
therefore, ../app.js from within index.html doesn't make sense, because the you can't go "up" from the web root;
./bower_components/... tries to find the bower_components directory in src/demo/ because it's a relative path, it should be /bower_components/...
On my MEAN stack application, I'm trying make changes to the HTML view files and see those changes as I make them using Grunt's livereload.
Grunt's livereload is working fine in the sense that it detects changes in my HTML files and refreshes the page during development. However, the actual changes are not reflecting on the page. If I push the files up the server, and reload the publicly available site, the changes are there. But I still can't see the changes while I'm developing.
I'm 99% sure that the problem has to do with the server is using the "build" files or something rather than the files located in the /public folder. However, I'm new to using the back-end and the MEAN stack and can't figure out what file the browser is showing or where this file is. Could anyone give any guidance on how to figure out what file the browser is displaying and what I can do to show HTML changes I make as I make them?
Here is my gruntfile if this helps. The below files I'm making changes to are watchFiles.clientViews.
'use strict';
module.exports = function(grunt) {
// Unified Watch Object
var watchFiles = {
serverViews: ['app/views/**/*.*'],
serverJS: ['gruntfile.js', 'server.js', 'config/**/*.js', 'app/**/*.js'],
clientViews: ['public/modules/**/views/**/*.html'],
clientJS: ['public/js/*.js', 'public/modules/**/*.js'],
clientCSS: ['public/modules/**/*.css'],
mochaTests: ['app/tests/**/*.js']
};
// Project Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
options: { livereload: true },
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
}
}
},
jshint: {
all: {
src: watchFiles.clientJS.concat(watchFiles.serverJS),
options: {
jshintrc: true
}
}
},
csslint: {
options: {
csslintrc: '.csslintrc',
},
all: {
src: watchFiles.clientCSS
}
},
uglify: {
production: {
options: {
mangle: false
},
files: {
'public/dist/application.min.js': 'public/dist/application.js'
}
}
},
cssmin: {
combine: {
files: {
'public/dist/application.min.css': '<%= applicationCSSFiles %>'
}
}
},
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': []
}
}
},
ngAnnotate: {
production: {
files: {
'public/dist/application.js': '<%= applicationJavaScriptFiles %>'
}
}
},
concurrent: {
default: ['nodemon', 'watch'],
debug: ['nodemon', 'watch', 'node-inspector'],
options: {
logConcurrentOutput: true,
limit: 10
}
},
env: {
test: {
NODE_ENV: 'test'
}
},
mochaTest: {
src: watchFiles.mochaTests,
options: {
reporter: 'spec',
require: 'server.js'
}
},
karma: {
unit: {
configFile: 'karma.conf.js'
}
}
});
// Load NPM tasks
require('load-grunt-tasks')(grunt);
// Making grunt default to force in order not to break the project.
grunt.option('force', true);
// A Task for loading the configuration object
grunt.task.registerTask('loadConfig', 'Task that loads the config into a grunt option.', function() {
var init = require('./config/init')();
var config = require('./config/config');
grunt.config.set('applicationJavaScriptFiles', config.assets.js);
grunt.config.set('applicationCSSFiles', config.assets.css);
});
// Default task(s).
grunt.registerTask('default', ['lint', 'concurrent:default']);
// Debug task.
grunt.registerTask('debug', ['lint', 'concurrent:debug']);
// Lint task(s).
grunt.registerTask('lint', ['jshint', 'csslint']);
// Build task(s).
grunt.registerTask('build', ['lint', 'loadConfig', 'ngAnnotate', 'uglify', 'cssmin']);
// Test task.
grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);
};
In addition, here is the file structure to my MEAN stack. The highlighted below is where the HTML file that I'm making changes to is located.
Please let me know if there is any other code or info I could provide that would make solving this problem easier. Thank you.
Update: Content of Server.js
Here is my server.js content:
'use strict';
/**
* Module dependencies.
*/
var init = require('./config/init')(),
config = require('./config/config'),
mongoose = require('mongoose');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Bootstrap db connection
var db = mongoose.connect(config.db, function(err) {
if (err) {
console.error('\x1b[31m', 'Could not connect to MongoDB!');
console.log(err);
}
});
// Init the express application
var app = require('./config/express')(db);
// Bootstrap passport config
require('./config/passport')();
// Start the app by listening on <port>
app.listen(config.port);
// Expose app
exports = module.exports = app;
// Logging initialization
console.log('MEAN.JS application started on port ' + config.port);
It's hard to tell exactly what your "server.js" is serving without seeing the contents of it, but if my assumption is correct and you are serving the contents of the "public" directory, you don't have any sort of task being fired by watch that facilitates copying the contents of your changed files into your "public" directory. It looks like this happens initially when your server is started (by running the build task), but not run subsequently whenever something is changed.
I would suggest modifying your watch tasks to perform some of the build-related tasks on your files as they are changed. Since your build-related tasks are physically copying the changes to the "public" directory for you as part of their jobs, you should finally see the results of your changes. Here's an example of your watch task list that's modified to copy your JS and CSS files on change:
watch: {
options: { livereload: true },
serverViews: {
files: [watchFiles.serverViews],
options: {
livereload: true
}
},
serverJS: {
files: watchFiles.serverJS,
tasks: ['jshint', 'loadConfig', 'ngAnnotate', 'uglify'],
options: {
livereload: true
}
},
clientViews: {
files: watchFiles.clientViews,
options: {
livereload: true,
}
},
clientJS: {
files: watchFiles.clientJS,
tasks: ['jshint', 'loadConfig', 'ngAnnotate', 'uglify'],
options: {
livereload: true
}
},
clientCSS: {
files: watchFiles.clientCSS,
tasks: ['csslint', 'cssmin'],
options: {
livereload: true
}
}
},
One last thing: Assuming your views don't need to have any modifications done to them post-change, you can simply straight-up copy them to the public directory when they are changed. Take a look at grunt-contrib-copy for doing simple file copying between directories.
I was facing the same issue and solved it by disabling the cache in the network tab
Go to Inspect -> Network and make sure disable cache is checked.
Hope this helps someone in future :)