I am using node.JS to build a web app with chat functionality. My server is serving up the basic content of the page but i'm running into problems importing external files like jpgs and style sheets. Here is the head of my main page, with the files I want to import:
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="stylesheets/main.css" />
<link href='http://fonts.googleapis.com/css?family=Alegreya+Sans' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Slabo+27px' rel='stylesheet' type='text/css'>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script type ="text/javascript">
var socketio = io.connect();
socketio.on("message_to_client",function(data) {
//Append an HR thematic break and the escaped HTML of the new message
document.getElementById("chatBox").appendChild(document.createElement("hr"));
document.getElementById("chatBox").appendChild(document.createTextNode(data['message']));
});
function sendMessage(){
var msg = document.getElementById("message_input").value;
socketio.emit("message_to_server", {message:msg});
}
This is the chat server I use to serve up the main page and handle messages. I'm stuck on getting it to handle static resources:
var http = require("http"),
socketio = require("socket.io"),
fs = require("fs"),
mime = require('mime');
var url = 'home.html';
var app = http.createServer(function(req, resp){
fs.readFile(url, function(err, data){
if(err) return resp.writeHead(500);
var mimeType = mime.lookup(url);
resp.setHeader('Content-Type', mimeType);
resp.writeHead(200);
resp.end(data);
});
});
app.listen(3456);
var io = socketio.listen(app);
io.sockets.on("connection", function(socket){
// This callback runs when a new Socket.IO connection is established.
socket.on('message_to_server', function(data) {
// This callback runs when the server receives a new message from the client.
console.log("message: "+data["message"]); // log it to the Node.JS output
io.sockets.emit("message_to_client",{message:data["message"] }) // broadcast the message to other users
});
});
In order to serve static files, do this (I use express, so I add a middleware to do that)
In your main app file, add this middleware:
app.use(express.static(__dirname + '/public')); //the argument is the location of the root directory with static files
Actually that's it. Your clients will be served the static files hosted in path /public
Related
This question already has an answer here:
Link index.html client.js and server.js
(1 answer)
Closed 2 years ago.
I have a simple web app that I am using to control a device, its just html+css+js.
I want to host that app on a raspberry pi and use it as a local server, so that I can open that app from tablets, pcs, phones etc, whatever I want.
I tried setting up a nodejs server to host the app, this is the code that I used, found it somewhere here on the forum:
var http = require('http');
var fileSystem = require('fs');
var server = http.createServer(function(req, resp){
fileSystem.readFile('./index.html', function(error, fileContent){
if(error){
resp.writeHead(500, {'Content-Type': 'text/plain'});
resp.end('Error');
}
else{
resp.writeHead(200, {'Content-Type': 'text/html'});
resp.write(fileContent);
resp.end();
}
});
});
server.listen(8081);
console.log('listening');
And it is kinda working. If I open the app from http://127.0.0.1:8081 on the computer on which it is hosted (mind you atm I am not on the raspberry, still testing on my personal pc) it is working as expected, if I directly open the index.html it is also working just fine.
But if I go and try to open it from my phone, or from my laptop from http://192.168.0.2:8081 it is not working. By not working I mean the following:
On the laptop it just renders the bare html and nothing else, there are several errors in the console about 'unexpected token <' I have one for each of my javascript files, and it is pointing at the first row of my HTML file the row
On my phone, same issue, I connected it for USB debugging to chrome to see the Console, I have the same errors screenshot: http://prntscr.com/s65x0t
Here is my HTML code, I did some research, many people were pointing out that some of the JS files that I have linked in my HTML may have incorrect directory or file name, but at least I dont see an issue there:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<script type="text/javascript" src="./js/jquery-3.5.0.js"></script>
<script type="text/javascript" src="./assets/scripts/main.js"></script>
<script type="text/javascript" src="./js/easy-numpad.js"></script>
<script type="text/javascript" src="./js/jquery-modal.js"></script>
<script type="text/javascript" src="./js/Model.js"></script>
<script type="text/javascript" src="./js/UI.js"></script>
<script type="text/javascript" src="./js/config.js"></script>
<link href="./css/main.css" rel="stylesheet" type="text/css" >
<link href="./css/easy-numpad.css" rel="stylesheet" type="text/css" >
Did You Serve Assets of HTML in Node Js?
You Can Server Static Content in Node js With the following code:
fs.readFile(__dirname + req.url, function (err, data) {
if (err) {
resp.writeHead(404);
resp.end(JSON.stringify(err));
return;
}
resp.writeHead(200);
resp.end(data);
});
Replace this and use http://192.168.x.x/index.html to open your html file and html file call for assets.
maybe require to remove . from address of assets files
(for example
<script type="text/javascript" src="./js/jquery-3.5.0.js"></script> convert to <script type="text/javascript" src="/js/jquery-3.5.0.js"></script>)
All requests to your server will return the index-html page which is why you see the Syntax Error/Mime-Type warning when Chrome tries to load the js/css files.
The solution is to set up additional routes/handling for other html, javascript and css files.
However, I recommend using express and just serving the content statically, as express takes care of this automatically:
// server.js
const express = require('express');
const app = express();
const port = 8081;
app.use(express.static('public'));
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));
With that just create a directory called public in the same directory as the server.js and all static content will be served automatically from there, e.g.
- your-server-app
-- server.js
-- public
--- index.html
--- js
---- test.js
and an example for the index.html page:
<html>
<script src="js/test.js"></script>
<body>
<h2>Hello from Index page</h2>
</body>
</html>
I'm developing a simple server that loads an HTML page after a request.
The code works fine, but i'm not able to load the local resources "connected" to my HTML page (CSS and Javascript files), i get the error mentioned in the title.
This is my Node.js server:
var server = http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
console.log("Print path:"+ path);
switch(path){
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
response.end();
break;
case '/index.html':
console.log("print full address:"+__dirname + path);
fs.readFile(__dirname + path, function(error, data){
if (error){
response.writeHead(404);
response.write("opps this doesn't exist - 404");
response.end();
}
else{
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
response.end();
}
});
break;
default:
response.writeHead(404);
response.write("opps this doesn't exist - 404");
response.end();
break;
}
});
server.listen(5000);
The index.html file is loaded, but i won't be able to access to all the local scripts and stylesheets inside my HTML file.
This is my HTML (short version, just the script and stylesheet part):
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>A Pen by Mattia Surricchio</title>
<link rel='stylesheet' href='02cbe09766a509e291eb2a444.css'>
<link rel='stylesheet' href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css'>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src='02cbe09766a509e291eb2a444.js'></script>
<script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/tone/13.8.9/Tone.min.js'></script>
<script src="script.js"></script>
</body>
All the files are in the same folder of my node.js file, so the server, HTML, CSS and Javascript files are all in the same folder.
I'm accessing the server with http://localhost:5000/index.html in my browser.
I checked the paths with console.log() and they seem correct (the HTML is loaded properly, the problem are the CSS and Javascript files inside the page).
What could be the problem?
PS: If i load the index.html page by itself (just opening it with the browser), all the files are loaded and showed correctly.
EDIT:
I partially solved the problem moving to express.js, here's my new server (i followes this answer:nodejs/express include local js file):
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var path = require('path');
var express = require('express');
app.use(express.static(path.join(__dirname, 'Pad')));
app.get('/', function(req, res) {
res.redirect('index.html');
});
My directory structure is the following:
root/
app.js //this is my node.js server
node-modules
package.json
Pad/
index.html
script.js
style.css
With this solution i'm able to load the HTML file, including the script.js file and the style.css that are linked inside the HTML file.
However, i'm also using local modules (in this particular case i'm using Tone.js and Tonal.js) which have been installed using npm inside the folder node-modules.
How do i access those resources? I'm getting error 404.
Do i have to move those resources inside my Pad folder?
You need to define a route for your CSS file(s) as you do it for index.html
case '/style.css':
res.writeHead(200, {'Content-Type': 'text/css'});
res.write(fs.readFileSync(__dirname + path, 'utf8'));
res.end();
break;
You need to call those files seperately like you call html file in the first place. Create direct url list for files that you want to parse first, then make get requests for them seperately.
I am running node project with html and javascript. How can I display the alert box in html.
My html (index.html)
<!DOCTYPE html>
<html>
<head>
<script src="./watch.js"></script>
</head>
<body onload="showBox()">
<h1>Heading</h1>
<p>Paragraph</p>
</body>
</html>
watch.js
function showBox(){
alert("this is alert box");
}
server.js
var http = require('http');
var fs = require('fs');
const PORT=8080;
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(PORT);
});
Error
I think that the problem is that you are not telling nodeJS where your statics files are.
For me, the simplest way is to set the server with Express
$ npm install express
And then setting up the server and where your static directory is:
var express = require('express');
var app = express();
//setting middleware
app.use(express.static(__dirname + 'public')); //Serves resources from public folder
var server = app.listen(5000);
There are other ways to doit using Native NodeJS, here are some resources:
Nodejs.org - How to serve static files
Also, you can write the script directly in your html file:
<!DOCTYPE html>
<html>
<head>
<script>
function showBox(){
alert("this is alert box");
}
</script>
</head>
<body onload="showBox()">
<h1>Heading</h1>
<p>Paragraph</p>
</body>
</html>
Your server is only ever returning index.html, no matter what path is requested. So, your watch.js is never loaded. The contents of index.html are returned instead of watch.js.
Either handle the other paths in your server code, or use something like Express.static, which does this for you.
Your http server is only outputting the index.html file. You need to either put all your client-side code in that file, or edit your server to load the watch.js file and make it able to send either page.
The first is simpler. Here's a basic example for the second. Most browsers will assume the mime-type by the extention.
Also, change your html for the script name from "./watch.js" to just "watch.js".
I simplified this down to be easier to understand... also const is deprecated and wont work on newer versions of node.
Specifying the mime header like you did is more compatible (Chrome and Firefox will assumebased on file extension, but for example Opera does not, or didnt used to).
var http = require('http');
var fs = require('fs');
var doc = {}
doc['/index.html'] = fs.readFileSync('index.html');
doc['/watch.js'] = fs.readFileSync('watch.js');
var server = (request, response)=>{
response.end(doc[req.url]);
}
http.createServer(server).listen(8080);
I need to get HTML page, enqueue CSS and JS files to it "on the fly" and then display it in the browser with NodeJS app file. I mean without changing HTML code of the page before getting it by NodeJS. Both CSS and JS files are in the same folder as NodeJS app file.
I'm trying this way
var fs = require('fs');
var http = require('http');
http.createServer(function (req, res) {
if(req.url === '/favicon.ico') {
res.writeHead(404);
res.end();
return;
}
var indexPageHTML = fs.readFileSync('index.html');
var indexPageHTML = indexPageHTML.toString();
var indexPageHTML = indexPageHTML.split('</head>')[0]+'<link rel="stylesheet" type="text/css" href="style.css"></head>'+indexPageHTML.split('</head>')[1];
var indexPageHTML = indexPageHTML.split('</body>')[0]+'<script src="my_client_script.js"></script></body></html>';
res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
res.end(indexPageHTML);
}).listen(80, 'localhost');
my minified index.html
<!doctype html><html><head><meta charset="utf-8"><title>Homepage title</title>
<style>html,body{height:100%;}</style></head><body>
<header></header>
<main role="main"></main>
<footer></footer>
</body></html>
In the browser I get the code I need, but none of files are loaded (CSS are not applied and JS doesn't work on the page) and in the browser console I get the error
Uncaught SyntaxError: Unexpected token <
and the warning
Resource interpreted as Stylesheet but transferred with MIME type
text/html: "http://localhost/app_style.css".
How to resolve the problem?
ps. I'm working with NodeJS in local computer on disk C inside of C:/User/Username
Ok, I've found the answer by the link NodeJS can't load css file
Just added the code
...
if(mimeType == 'text/html') {
var contents = contents.toString();
var contents = contents.split('</head>')[0]+'<link rel="stylesheet" type="text/css" href="style.css"></head>'+contents.split('</head>')[1];
var contents = contents.split('</body>')[0]+'<script src="my_client_script.js"></script></body></html>';
}
res.end(contents);
...
to the getFile() function
I'm new here.
I have a website (index.html) where several css and js files are included. Locally it works fine, but if I start the node-http server (which calls the index.html), the website (localhost:8080) doesn't know the files. It shows me only basic text (i.e. <h1>) which have nothing to do with the javascript files. I checked the source code in the browser to see the index.html. But if I click on the css and js links, I'll be forwarded back to index.html.
I assume, it's a linking problem. Or do you think the problem could be in the node http server implementation? It would be very helpful for me if you could give me some support.
Thanks and best wishes,
Kevin
webServer.js:
var express = require('express');
var connect = require('connect');
var http = require('http');
var path = "";
var app = connect().use(express.static(__dirname + path));
http.createServer(app).listen(8080);
index.html:
head:
<!-- Cascading Style Sheets -->
<link href="css/custom.css" media="screen" rel="stylesheet" type="text/css" >
<link href="css/rickshaw.css" media="screen" rel="stylesheet" type="text/css" >
<link href="css/envision.css" media="screen" rel="stylesheet" type="text/css" >
body:
<h1>Data monitoring</h1>
<!-- Drawing rickshaw based charts -->
<div id="chart-type1"></div>
<div id="chart-type2"></div>
<!-- Drawing envision based charts -->
<div id="chart-TimeSeries"></div>
<div id="chart-RealTime"></div>
<!-- JavaScript -->
<script type="text/javascript" src="lib/d3.min.js"></script>
<script type="text/javascript" src="lib/rickshaw.js"></script>
<script type="text/javascript" src="js/chart.js"></script>
<script type="text/javascript" src="js/chartTimeSeries.js"></script>
<script type="text/javascript" src="js/chartRealTime.js"></script>
<script type="text/javascript" src="js/collectionJson.js"></script>
You have to define routes for all your files in a way like this:
var http = require ('http');
var fs = require('fs');
var port = '8080';
var server = http.createServer(function (req, res) {
if (request.url === '/') {
fs.readFile('index.html', function(err, data){
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data, 'utf-8');
});
} else if (request.url === '/css/custom.css') {
/*Read /css/custom.css file*/
} else if (request.url === '/path/to/other.file') {
/*Read /path/to/other.file*/
}
}).listen(port);
But this is difficult to read and write so it's better to use a Web Framework for this. You can try Express or the framework written by me: Simples. You can put all your static files in a directory then use this code:
var simples = require('simples');
var server = new simples(8080);
server.serve('path/to/staticFiles');
// or in some special cases:
server.get('/some_url', function (connection) {
connection.header('X-Some-Header', 'Header Value'); // Set a header
connection.drain('some_local_file.ext');
});
If you are using framework such as express,
var express = require('express');
var app = express();
You host all static files in the Public folder as follows:
app.use(express.static(__dirname + '/public'));
If you have a folder by a specific name as ‘media’:
app.use('/media', express.static(__dirname + '/media'));
You can use either express or connect (install them with npm) to create an app that you will host with http.createServer(). You will write in webServer.js:
var http = require('http');
var connect = require('connect');
var app = connect().use(connect.static(__dirname + path));
http.createServer(app).listen(8080);
where path is the path from your root folder (where you have webServer.js) to your index.html folder (path is an empty string if index.html and webServer.js are in the same folder).
Then, in the html page where you have a link to any css or js, you just have to put the path from the folder where the html page is to your css or js file. For example, I have webServer.js in root, html in html folder and js in js folder. In my html I will put: <script src="../js/myjsfile.js"></script>.
Be careful, you will not be able to find paths that go higher than the server root directory.
Use this in your html file
<script>
$.getScript("/js/yourjsfile.js", function () {
//alert("Script loaded and executed.");
// Here you can use anything you defined in the loaded script
});
</script>