Unable to get connect-livereload to work with express server in gulp task - node.js

I am working off of Yeoman's gulp-webapp generator. I have modified my gulp serve task to use my Express server, rather than the default connect server it ships with. My issue is with Livereload functionality. I am trying to simply port the connect-livereload to work with my Express server rather than having to install new dependencies. It's to my understanding that most connect middleware should work fine with Express, so I am assuming connect livereload is compatible with Express 4.
Here are the contents of the relevant tasks in my gulpfile:
gulp.task('express', function() {
var serveStatic = require('serve-static');
var app = require('./server/app');
app.use(require('connect-livereload')({port: 35729}))
.use(serveStatic('.tmp'));
app.listen(3000);
});
gulp.task('watch', ['express'], function () {
$.livereload.listen();
// watch for changes
gulp.watch([
'app/*.ejs',
'.tmp/styles/**/*.css',
'app/scripts/**/*.js',
'app/images/**/*'
]).on('change', $.livereload.changed);
gulp.watch('app/styles/**/*.css', ['styles']);
gulp.watch('bower.json', ['wiredep']);
});
gulp.task('styles', function () {
return gulp.src('app/styles/main.css')
.pipe($.autoprefixer({browsers: ['last 1 version']}))
.pipe(gulp.dest('.tmp/styles'));
});
gulp.task('serve', ['express', 'watch'], function () {
require('opn')('http://localhost:3000');
});
With this simple setup, when I run gulp serve in my cmd everything spins up fine and I can accept requests at http://localhost:3000.
Now if I go and change the body's background color from #fafafa to #f00 in main.css and hit save, my gulp output will respond with main.css was reloaded, as seen in the bottom of this screenshot.
However, my webpage does not update. The background color is still light-grey instead of red.
Is there perhaps a conflict between my express server config and the way gulp handles its files? Is my Express server forcing the use of app/styles/main.css rather than the use of .tmp/styles/main.css? Shouldn't the livereload script handle the injection of the new temporary file?
Thanks for any help.
EDIT:
I was able to move forward a bit by adding livereload.js to the script block of my index file, like so:
<script src="http://localhost:35729/livereload.js"></script>
I am now able to get live changes pushed to the client. Why was this file not getting injected before? How can I ensure this is getting used programatically as opposed to pasting it into my files?

I was able to get past this issue by removing the app.use(require('connect-livereload')({port: 35729})) from my gulpfile, along with a couple of other lines, and having that instantiate in my Express server's app.js file.
My gulpfile's express task now looks like this:
gulp.task('express', function() {
var app = require('./server/app');
app.listen(3000);
});
I added in the connect-livereload just above where I specify my static directory in Express:
if (app.get('env') === 'development') {
app.use(require('connect-livereload')());
}
app.use(express.static(path.join(__dirname, '../app')));
Once I started using this setup, I was getting the livereload.js script injected into my document, and client-side changes are now auto-refreshed just how I wanted.
Hope this helps someone!

Related

express app is not sending index.html file to client

So my express app has a small Node server setup so it can serve up the index.html file when the home route '/' is hit. This is a requirement of using the App Services from Azure, there has to be this server.js file to tell the server how to serve up the client, and i had a previous implementation of this working, however i wanted to change my file structure. previously i had, the client React app in a folder client and the server.js in a folder server along with all of the conrtollers and routes. i've since moved the server API to its own application as there are other apps that depend on it. and i moved the client up one directory into the main directory. Everything was working fine till the other day when all of the sudden when you hit the home route / it will not serve up the index.html file. if you hit any other route it works, if you even hit a button linking back to the homepage, it works, but it wont serve up the app from the / and i cannot for the life of me figure out why, on my development server there are no errors in the console. and im most definitely targeting the correct directory and place for the index. but its like the server isnt reading the route to serve up.
if (process.env.NODE_ENV === 'production') {
console.log('running');
app.use(express.static(path.resolve(path.join(__dirname, 'build'))));
// no matter what route is hit, send the index.html file
app.get('*', (req, res) => {
res.sendFile(path.resolve(path.join(__dirname, 'build', 'index.html')));
});
} else {
app.get('/', (req, res) => {
res.send('API is running...');
});
}
So here im saying if the NODE_ENV is in production make the build folder static, and then whatever route is hit. (Note: i also tried this app.get with other route formats such as /* or / all have the same issues. however in my previous iteration when the client and server where deployed in the same location, /* is what i used.) The .env varialbes are setup correctly, as when the server is ran, itll console log running.. but even if i put a console log inside of the app.get() its like its never hit unless i access the route from something else first.
for example, if i place a console log inside of app.get that states hit whenever the route is hit, hitting / directly does nothing, but if i go to /login itll serve up the correct html on the client and console log hit in the terminal...
If you are having server files inside the client react app, then we are basically accessing file which are not inside our server file. So, we can serve static files using the following code:
const express = require("express");
const app = express(); // create express app
const path = require('path');
app.use(express.static(path.join(__dirname, "..", "build")));
app.use(express.static("build"));
app.listen(5000, () => {
console.log("server started on port 5000");
});
Now in your packages.json of the client react app change the name of start tag under scripts tag to start-client. Then add this following tag to the scripts tag:
"start":"npm run build && (cd server && npm start)",
Basically, this will build the react app and start the server.
It should look like this :
Also in the packages.json of your server add the following tag under script tag
"start":"node server.js"
So when you run the following command npm start it should look like this :

deploy module to remote server that is running node.js

I'm working on my app.js in node.js
-- trying to deploy server-side script.
Many fine node.js modules need a require('something');
I use NPM locally, which works for require, as modules are nicely visible in the local node_modules folder structure. but now I'm ready to upload or bundle to a host. I can't run npm on this hosted server.
const Hapi = require('hapi');
will result in
Error: Cannot find module 'hapi'
because I don't know how to copy/install/bundle/ftp files to my host.
Hapi is just an example. Most anything that has a require will need something on the host.
I used webpack to create a server side bundle.js but just sticking bundle.js under /node_modules doesn't do anything.
Most modules have a complex folder structure underneath --- I'm trying to avoid copying a ton of folders and files under /node_modules. Ideally, I want to combine the modules into a bundle.js and have those modules visible to app.js
but I am open to other ideas.
I have not yet tried using webpack to bundle app.js TOGETHER with the various modules. Have you had luck with that approach?
thanks.
I've tried to upload hapi files a folder-ful at a time, reaching a new require('something') error at every step.
'use strict';
const Hapi = require('hapi'); // <-- how can I deploy hapi on my node.js server?
// Create a server with a host and port
const server=Hapi.server({
host:'localhost',
port:8000
});
// Add the route
server.route({
method:'GET',
path:'/hello',
handler:function(request,h) {
return'hello world';
}
});
// Start the server
async function start() {
try {
await server.start();
}
catch (err) {
console.log(err);
process.exit(1);
}
console.log('Server running at:', server.info.uri);
};
start();
one approach that worked: using webpack to bundle the back end js.
thanks to
https://medium.com/code-oil/webpack-javascript-bundling-for-both-front-end-and-back-
end-b95f1b429810
the aha moment... run webpack to create bundle-back.js then
tie bundle-back.js to my node server
**You start your backend server with ‘bundle-back.js’ using:
node bundle-back.js
In other words, include app.js in the bundle with the modules.

Node starts my server, so does gulp, but gulp doesn't find any paths

I am sure this is something small, but I am unable to figure it out. Node, nodemon and gulp use app.js to start my server so I am not sure why one way works while gulp does not. If I start my server using:
nodemon app.js or
node app.js it starts fine and when I use the path localhost:1337 in the browser it does what it is supposed to do.
When I use the command:
gulp
it says that it started the server but when I navigate to localhost:1337 it does not display anything other than "Cannot GET /" and none of my sources are showing in the inspector. I still get the message that "the port is listening" as indicated in my app.js console.log. My gulpfile is as follows:
var gulp = require('gulp');
var nodemon = require('gulp-nodemon');
gulp.task('nodemon', function(){
nodemon({
script: './app/app.js'
})
});
gulp.task('watch', function(){
gulp.watch('*.js', ['nodemon']);
});
gulp.task('default', ['nodemon']);
my app.js file is:
express = require('express');
var app = express();
app.use(express.static('../views'));
app.use(express.static('../bower_components/angular'));
app.use(express.static('./directives'));
app.listen(1337);
console.log("The port is listening");
The 'Cannot GET /' being displayed when you go to localhost:1337 is Express's generic message when a request is made against a route that is undefined. A route needs to be defined for the pages that you want to serve. You need to add a Route to handle the request to the root of your app at http://localhost:1337/.
app.get('/', function(req, res) {
// return back a message
res.send('Welcome!');
});
Place the above snippet above app.listen() and the message "Welcome!" will be displayed.
To serve a view in an html file you need to add a view engine so Express knows how to render the file. Additionally, the views property needs to be configured so Express knows where to render your views from. The example below uses ejs to just handle plain html files and not worry about a template engine like jade.
app.use('views', path.join(__dirname + '/views'));
app.engine('html', require('ejs').renderFile);
app.use('view engine', 'html');
Now we can use the render function on the res object to send our index.html file:
app.get('/', function(req, res) {
res.render('index');
});
This a guide from ExpressJS on how to implement routing in Express.

How to setup gulp browser-sync for a node / react project that uses dynamic url routing

I am trying to add BrowserSync to my react.js node project. My problem is that my project manages the url routing, listening port and mongoose connection through the server.js file so obviously when I run a browser-sync task and check the localhost url http://localhost:3000 I get a Cannot GET /.
Is there a way to force browser-sync to use my server.js file? Should I be using a secondary nodemon server or something (and if i do how can the cross-browser syncing work)? I am really lost and all the examples I have seen add more confusion. Help!!
gulp.task('browser-sync', function() {
browserSync({
server: {
baseDir: "./"
},
files: [
'static/**/*.*',
'!static/js/bundle.js'
],
});
});
We had a similar issue that we were able to fix by using proxy-middleware(https://www.npmjs.com/package/proxy-middleware). BrowserSync lets you add middleware so you can process each request. Here is a trimmed down example of what we were doing:
var proxy = require('proxy-middleware');
var url = require('url');
// the base url where to forward the requests
var proxyOptions = url.parse('https://appserver:8080/api');
// Which route browserSync should forward to the gateway
proxyOptions.route = '/api'
// so an ajax request to browserSync http://localhost:3000/api/users would be
// sent via proxy to http://appserver:8080/api/users while letting any requests
// that don't have /api at the beginning of the path fall back to the default behavior.
browserSync({
// other browserSync options
// ....
server: {
middleware: [
// proxy /api requests to api gateway
proxy(proxyOptions)
]
}
});
The cool thing about this is that you can change where the proxy is pointed, so you can test against different environments. One thing to note is that all of our routes start with /api which makes this approach a lot easier. It would be a little more tricky to pick and choose which routes to proxy but hopefully the example above will give you a good starting point.
The other option would be to use CORS, but if you aren't dealing with that in production it may not be worth messing with for your dev environment.

display html page with node.js

This is my first time with node.js. I get it to display the index.html, but it doesn't display the images on the site or anything else, it ONLY shows the basic html stuff. Here's how I set it up.
There's no apache, php or anything else on the server, just ubuntu, proftp and node(and curl and the other dependencies). I made the main directory for the node files /var/nodeFiles and the directory for the html/site files is /var/nodeFiles/www
so for my node server file I did it like this:
var http = require('http'),
fs = require('fs');
fs.readFile('/var/nodeFiles/www/index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(80);
});
this works, but it ONLY shows the index.html file and NOTHING attached to it, so no images, no effects or anything that the html file should display. The files and directories are all correct, I've double checked and the permissions of the folders are correct. So what else do I have to do to get node to display the rest of the site?
I hope I've explained my self correctly, I was told this is the place to ask development questions.
Thank you for taking the time to read this.
but it ONLY shows the index.html file and NOTHING attached to it, so no images,
no effects or anything that the html file should display.
That's because in your program that's the only thing that you return to the browser regardless of what the request looks like.
You can take a look at a more complete example that will return the correct files for the most common web pages (HTML, JPG, CSS, JS) in here https://gist.github.com/hectorcorrea/2573391
Also, take a look at this blog post that I wrote on how to get started with node. I think it might clarify a few things for you: http://hectorcorrea.com/blog/introduction-to-node-js
Check this basic code to setup html server. its work for me.
var http = require('http'),
fs = require('fs');
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(8000);
});
This did the trick for me:
var express = require('express'),
app = express();
app.use('/', express.static(__dirname + '/'));
app.listen(8080);
If your goal is to simply display some static files you can use the Connect package. I have had some success (I'm still pretty new to NodeJS myself), using it and the twitter bootstrap API in combination.
at the command line
:\> cd <path you wish your server to reside>
:\> npm install connect
Then in a file (I named) Server.js
var connect = require('connect'),
http = require('http');
connect()
.use(connect.static('<pathyouwishtoserve>'))
.use(connect.directory('<pathyouwishtoserve>'))
.listen(8080);
Finally
:\>node Server.js
Caveats:
If you don't want to display the directory contents, exclude the .use(connect.directory line.
So I created a folder called "server" placed index.html in the folder and the bootstrap API in the same folder. Then when you access the computers IP:8080 it's automagically going to use the index.html file.
If you want to use port 80 (so just going to http://, and you don't have to type in :8080 or some other port). you'll need to start node with sudo, I'm not sure of the security implications but if you're just using it for an internal network, I don't personally think it's a big deal. Exposing to the outside world is another story.
Update 1/28/2014:
I haven't had to do the following on my latest versions of things, so try it out like above first, if it doesn't work (and you read the errors complaining it can't find nodejs), go ahead and possibly try the below.
End Update
Additionally when running in ubuntu I ran into a problem using nodejs as the name (with NPM), if you're having this problem, I recommend using an alias or something to "rename" nodejs to node.
Commands I used (for better or worse):
Create a new file called node
:\>gedit /usr/local/bin/node
#!/bin/bash
exec /nodejs "$#"
sudo chmod -x /usr/local/bin/node
That ought to make
node Server.js
work just fine
You can simply use
res.senFile('PATH_TO_FILE');

Resources