I'm trying to use grunt-express and grunt-watch. I would like the server to reload with I change my server file.
Here is what I got.
Gruntfile.js
var path = require('path');
module.exports = function(grunt) {
grunt.initConfig({
express: {
options: {
port: 8000
},
load: {
server: path.resolve('./app')
}
},
watch: {
express: {
files: ['app.js'],
tasks: ['express:load']
}
}
});
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express');
grunt.registerTask('server', ['express:load', 'express-keepalive', 'watch']);
};
app.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
app.get('/', function(req, res) {
res.sendfile(__dirname + '/public/index.html');
});
exports = module.exports = server;
exports.use = function() {
app.use.apply(app, arguments);
};
When I type grunt server in the console I get:
Running "express:load" (express) task
Running "express-server:load" (express-server) task
Web server started on port:8000, no hostname specified [pid: 21115]
Running "express-keepalive" task
The server start up fine and I can go to localhost:8000 to view my page. The watch task doesn't seem to start and when I make changes to app.js it doesn't restart. I basically want type grunt server and then when any changes happen to app.js, I want the server to restart. I've tried using the serverreload option, but I can't seem to get that to work either. I have also tried using express-restart (in place of express:livereload) in the watch:express task, but it says
Warning: path must be a string Use --force to continue.
After some playing around I was able to get it working, with an annoying issue. Here's the core of the Gruntfile:
var path = require('path');
module.exports = function (grunt) {
grunt.initConfig({
express: {
options: {
port: 8000,
hostname: '*'
},
livereload: {
options: {
server: path.resolve('./app.js'),
livereload: true,
serverreload: true,
bases: [path.resolve('./public')]
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express');
grunt.registerTask('default', ['express', 'express-keepalive']);
};
However there seems to be an issue where a different port is used every other save. If the other server reload option is working I would stick with that for the time being.
As a side note, it appears this grunt plugin also listening on the port which means the start app.js should return itself with module.exports = app; rather than the default express http.createServer. It appears both will run simultaneously as long as different ports are specified.
Related
I'm deploying a project on my hosting, but I've some trouble with the 'entry point' of my app.
I've developed an application under react js (with webpack).
When I setup it, I don't know which file to make the 'Application startup file'?
For the moment, it's a simple 'server.js' that say hello and give me the current version of node.
When I'm on my project in local, I just launch npm start and it works.
Resolved by editing the 'server.js' file like this :
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
});
app.listen(9000);
I'm trying to add Log4js-Node to a Node.js server running on Apache. Here's my code:
const path = require("path");
const express = require("express");
const log4js = require('log4js');
const app = express();
const logger = log4js.getLogger();
logger.level = "debug";
const port = 443;
log4js.configure({
appenders: { everything: { type: 'file', filename: 'logs.log', flags: 'w' } },
categories: { default: { appenders: ['everything'], level: 'ALL' } }
});
const server = app.listen(port, () => {
logger.debug("listening to requests on port " + port);
});
app.get("/log", (req, res) => {
res.sendFile(path.join(__dirname + "/logs.log"));
});
When I run the script on Node.js on my computer and navigate to localhost:443/log I see what I expect, which is this:
[2020-03-17T22:50:43.145] [DEBUG] default - listening to requests on port 443
But when I run the code on a remote server it crashes and I get this in the error page (with part of the path replaced by me with "[removed]"):
App 25925 output: at Server. ([removed]/index.js:27:9)
App 25925 output: at Logger. [as debug] ([removed]/12/lib/node_modules/log4js/lib/logger.js:124:10)
App 25925 output: at Logger.log ([removed]/12/lib/node_modules/log4js/lib/logger.js:73:12)
App 25925 output: at Logger._log ([removed]/12/lib/node_modules/log4js/lib/logger.js:90:16)
App 25925 output: at Object.send ([removed]/12/lib/node_modules/log4js/lib/clustering.js:97:15)
App 25925 output: [removed]/12/lib/node_modules/log4js/lib/clustering.js:97
App 25925 output: at Object. ([removed]/12/lib/node_modules/log4js/lib/clustering.js:8:13)
I'm using A2 Hosting which uses Apache 2.4.41. I opted for Node.js 12.9.0, and Log4js 6.1.2. The package.json should be the same on both my computer and the server, and I've run npm install on both.
Is this just an issue with Log4js and the server, or have I missed something somewhere?
This was actually a relatively simple fix. The path referenced by the last error in the stack trace is a Log4js module that implements clustering support through Node's "cluster" module. The line "8" referenced is cluster = require("cluster"). It's wrapped in a try/catch block like this:
try {
cluster = require("cluster"); //eslint-disable-line
} catch (e) {
debug("cluster module not present");
disabled = true;
}
The installation of Node.js on my computer came with the "cluster" module, however as far as I can tell, the server I'm using doesn't support it. Also, the version of Node I'm using on my computer is newer than what I'm using on the server (so I've now installed 12.9 on my machine). I believe the older version of Node doesn't bother trying to catch the exception and tries to load the cluster module, fails, and then throws the error.
So the simple fix was to comment out most of the "try/catch" block, leaving just the contents of "catch" like this:
// try {
// cluster = require("cluster"); //eslint-disable-line
// } catch (e) {
debug("cluster module not present");
disabled = true;
// }
If someone has a better fix, I'm open to suggestions.
The same response of #skittleswrapper,thx, it work for me.
I use Node.js 14.18.1 with log4js 6.3.0.
But i wondering what'is the necessary of this module 'cluster' and if we can
add it to our app in other way.
I've got a following Gruntfile.js which includes only two tasks: the first one parses/generates files and the second one, grunt-contrib-connect, starts web server:
module.exports = function(grunt) {
grunt.initConfig({
aglio: {
docs: {
files: {
'index.html': 'api.md',
},
options: {
theme: "slate"
}
}
},
connect: {
server: {
options: {
port: 9001,
hostname: 'localhost',
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-aglio');
grunt.registerTask('default', ['aglio', 'connect']);
};
The problem is that the server exits silently and I don't know why. In the console, it looks like this:
tducin#tducin-home:~/Workspace/duck-blueprint$ grunt
Running "aglio:docs" (aglio) task
>> Written to index.html
Running "connect:server" (connect) task
Started connect web server on http://localhost:9001
Done, without errors.
Can anybody point me on what is wrong with my connect task configuration?
Did you read the documentation of grunt-contrib-connect?
According to the document.You need to set keepalive true if want keep alive the server after grunt tasks compleated.
connect: {
server: {
options: {
port: 9001,
hostname: 'localhost',
keepalive : true
}
}
Keep the server alive indefinitely. Note that if this option is enabled, any tasks specified after this task will never run. By default, once grunt's tasks have completed, the web server stops. This option changes that behavior.
https://github.com/gruntjs/grunt-contrib-connect/blob/master/README.md
Ok, I'm searching a couple of hours for a solution to run my Mocha unit tests inside Jenkins, for my Express JS app.
Writing tests is quite easy, but connecting the tests with my app is a bit harder. An example of my current test:
/tests/backend/route.test.js
var should = require('should'),
assert = require('assert'),
request = require('supertest'),
express = require('express');
describe('Routing', function() {
var app = 'http://someurl.com';
describe('Account', function() {
it('should return error trying to save duplicate username', function(done) {
var profile = {
username: 'vgheri',
password: 'test',
firstName: 'Valerio',
lastName: 'Gheri'
};
// once we have specified the info we want to send to the server via POST verb,
// we need to actually perform the action on the resource, in this case we want to
// POST on /api/profiles and we want to send some info
// We do this using the request object, requiring supertest!
request(app)
.post('/api/profiles')
.send(profile)
// end handles the response
.end(function(err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
res.should.have.status(400);
done();
});
});
});
In above example I connect to a running app (see ```var app = 'http://someurl.com'``). Obviously this is not working inside Jenkins, except if I can tell Jenkins to first run the app and then check for a localhost url. But how to do this?
Now if I take a look at https://www.npmjs.org/package/supertest this should be enough to test my express app:
var request = require('supertest')
, express = require('express');
var app = express();
But it's not. I receive 404 errors on all urls which I would like to test.
Anyone who knows how to test my app inside Jenkins?
Is the app you referenced at http://someurl.com the app you're trying to write this test for? If so...
Supertest should allow you to run tests without needing an external server running. The way you accomplish this is by separating out the server routing Express code from the code you'll run that actually starts the server, and use Supertest on the server routing code.
Here is an example:
Given this directory structure:
./package.json
./server/index.js
./app.js
./test/server-test.js
Here are my files:
./package.json
All of these dependencies aren't required for this example, I just pulled this from my package.json I'm using in my project.
{
"name": "StackOverflowExample",
"version": "1.0.0",
"description": "Example for stackoverflow",
"main": "app.js",
"scripts": {
"test": "mocha"
},
"author": "Mark",
"license": "ISC",
"dependencies": {
"body-parser": "^1.15.2",
"ejs": "^2.5.2",
"express": "^4.14.0",
"express-validator": "^2.21.0",
},
"devDependencies": {
"chai": "^3.5.0",
"mocha": "^3.1.2",
"supertest": "^2.0.1"
}
}
./server/index.js
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('Hello World');
});
module.exports = app;
./app.js
var app = require('./server');
var server = app.listen(8000, function() {
console.log('Listening on port 8000');
});
./tests/server-test.js
var request = require('supertest');
var app = require('../server');
var assert = require('assert'); //mocha
var chai = require('chai');
var expect = null;
chai.should();
expect = chai.expect;
describe('GET /', function() {
it('should return a 200', function(done) {
request(app).get('/').expect(200, done);
});
});
I'm using Mocha and Chai here (didn't have time to refactor and make the example simpler, sorry). The main point is that within the it statement you can run your tests.
Doing it this way does not require a separate server running. Supertest magically starts one up for you and runs it based on the express server you exported from the server module. I think this approach should allow you to run your tests seamlessly through Jenkins.
In ./server/index.js, an Express object is created. That object is exported, and imported via require in both ./app.js and ./test/server-test.js. In ./app.js it's used to start a server via listen(). In the test file, Supetest uses it to start a server for testing internally.
When you are running the server in this example, you would run it via ./app.js. That would set the port you choose (8000 in this example) and start listening for connections on that port.
Hope this helps! Good luck!
I setup Yeoman 1.0 beta to handle my js/css tasks. Everything works fine that, if I run grunt server, it starts up a static server and connects a browser session to port 9000 (livereload). js/css concat, minification are also working.
Now, is there a way I can make it to connect to a google app engine development server (instead of starting a static server). The server is running at port 8080 on localhost, and I want grunt to reload the webpage upon css/js files under watch. These files would be served by GAE server.
I see a section rolling your own at grunt-contrib-connect documentation, but not sure it means an external server. As far as I see, these are the relavent configuration from Gruntfile.js
connect: {
livereload: {
options: {
port: 8080, //*** was 9001 originally **
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app)
];
}
}
},
When I change the port number to 8080, and try to start, obviously it gives error.
Fatal error: Port 8080 is already in use by another process.
so, I don't want to start a new server, but connect through GAE server already running.
Thanks.
In order to use GAE server instead of nodejs server, we need to do the following.
* Compile your less/coffeescript, concat[, minify], copy your code to the location where the app engine code resides.
* Create a task in grunt.js to spawn a shell command to run app engine.
This is the example, that I used as reference. https://github.com/cowboy/grunt/tree/master/tasks
Following grunt.js file may help!
module.exports = function(grunt) {
grunt.initConfig({
....
});
grunt.registerTask('appengine-update', 'Upload to App Engine.', function() {
var spawn = require('child_process').spawn;
var PIPE = {stdio: 'inherit'};
var done = this.async();
spawn('appcfg.py', ['update', 'build/task-manager-angular'], PIPE).on('exit', function(status) {
done(status === 0);
});
});
grunt.registerTask('clean', 'Clean the whole build directory.', function() {
require('child_process').exec('rm -rdf build', this.async());
});
grunt.registerTask('run', 'Run app server.', function() {
var spawn = require('child_process').spawn;
var PIPE = {stdio: 'inherit'};
var done = this.async();
spawn('dev_appserver.py', ['.'], PIPE).on('exit', function(status) {
done(status === 0);
});
});
});
//....
//Other settings
//....
grunt.loadTasks('tasks');
grunt.loadNpmTasks('grunt-coffeelint');
grunt.registerTask('build', 'coffee less concat');
grunt.registerTask('deploy', 'coffee less concat build appengine-update');
grunt.registerTask('default', 'coffee less');
};
Found this Google App Engine management plugin for Grunt