I have an incredibly basic node.js server test app running on port 3000 in VSCode. The server appears to work via node on localhost or deployed to Azure, and hosts an index.html file. I have clients happy to talk to it.
/* Server.js */
const express = require('express');
const app = express();
app.use(express.json());
app.get("/", function(request, response){
response.sendFile(__dirname + "/index.html");
});
app.post("/", function(request, result){
console.log(request.body["itema"] + " " + request.body["itemb"]);
result.send("Pong!!");
});
app.listen(3000, function(){
console.log("Server started on port 3000");
});
<!-- Index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Simple App</title>
<link rel="stylesheet" href="style.css" type="text/css"/>
</head>
<body>
<h1>Test!</h1>
</body>
</html>
/*style.css*/
h1 {
color: tomato;
}
Azure Configuration Settings
The index.html links to a css file which doesn't appear to be linked when deployed. I've tried deploying the app to azurewebsites.net through VSCode, however I'm seeing the same results. Only index.html is present in the sources view. I get an error claiming it can't render the source it didn't find.
"Refused to apply style from https://<appname>.azurewebsites.net/style.css because its MIME
type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is
enabled."
If I view the advanced page (.scm.azurewebsites.net), again I can see only index.html.
Index only
But .scm.azurewebsites.net/wwwroot/ shows me the css file has been uploaded correctly.
Index and linked sources
I'm convinced it'll be a simple solution to someone and that the PATH variables will need to be set...somehow... but I've hit a brick wall and my Google-Fu has finally been exhausted.
Thanks!
Adding the following to server.js resolved the issue.
app.use(express.static("./"));
This is further explained here and is required in express to serve static files.
https://expressjs.com/en/starter/static-files.html
Related
I made an express Nodejs server and set the static folder.
The CSS has access to the page, but the JS does not find any elements. Everything is NULL.
app.use(express.static(__dirname + '/static'))
app.get('/', (req, res) => {
res.render('index')
})
//test from clientside index.js
document.body.append('test')
<script src="js/index.js"></script>
<link rel="stylesheet" href="style/main.css">
What am I doing wrong?
Problem
DOM doesn't load yet when your JS runs. It's not related to EJS, that's just how every script works.
Solution
Add defer attribute
<script defer src="js/index.js"></script>
I made the "Getting started" example of socket.io, it works perfectly on localhost on my computer. But when I upload it to my hosting it is not working, the client throws a 404 error trying to get socket.io.js:
<script src="/socket.io/socket.io.js"></script>
I solved this with this other reference (I didn't need to do this on localhost):
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
But then, I am getting 404 errors constantly when the client is running on the hosting. It seems like Node.js server is not running on server and not serving socket.io files when is on hosting. I don't get these 404 errors when I am on localhost. There is an example of this calls:
GET http://localhost/socket.io/?EIO=3&transport=polling&t=MMc5E4X (200 works fine on local)
GET http://tinatest.gearhostpreview.com/socket.io/?EIO=3&transport=polling&t=MMc5E4X (404)
I got this example on a free Node.js hosting so you can have a look at it, I activated Node.js 8 on this server and this is running on port 80:
http://tinatest.gearhostpreview.com/
The files on the server are:
Index.html
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
</html>
Index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(80, function(){
console.log('listening on *:80');
});
package.json
{
"name": "socket-chat-example",
"version": "0.0.1",
"description": "my first socket.io app",
"dependencies": {
"express": "^4.15.2",
"socket.io": "^2.1.1",
"socket.io-client": "^2.1.1"
}
}
How can I make this work? Or if not, why is it not possible?
Think about what a Node.js + express server does. Among many things, it can serve files based on various types of http requests. However, you have to tell it exactly what types of requests to listen for (GET, POST, etc.) and on what routes (/, /folder). You can even listen for query strings, params, bodies of post messages, etc, etc. However, its up to you to define them.
Look over your code, what route have your defined?
Just one: / and you allow a GET requests to that route and in response you are serving index.html, which has all of your front-end logic, at least in this case.
If you were to try to GET other routes, like /socket.io/ you will by default get a 404 error.
The script file you mention has as it's src value /socket.io, since you don't have a route to serve the socket.io code, it fails in production.
On localhost, if the files are available in the same project, your browser can resolve the relative path on your local machine. Once the project is deployed, the relative paths are no longer looking to your machine but hitting your router with a full blown url. It's expecting those files to be served.
You can solve the problem in production by giving a full url reference to the necessary socket.io code.
MORE: An Example:
index.js - see comments below
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
/**
* Your ROUTES
* in production, when someone goes to http://tinatest.gearhostpreview.com/
* they are calling your root route "/"
* Your callback function is sending back index.html from your root directory
* You add __dirname because you don't know where gearhost is actually putting
* your stuff.
*
* In production, you can only access server-side files if you serve them
*/
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
/**
* ONE WAY TO SERVE JS TO YOUR CLIENT
* (there are many better ways of doing this)
*
* If you do this, you will not get a 404 error
*/
app.get('/socket.io/socket.io.js', function(req, res){
// this assumes you have a folder within your root named socket.io
// and that it contains socket.io.js,
res.sendFile(__dirname + '/socket.io/socket.io.js');
})
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(80, function(){
console.log('listening on *:80');
});
index.html - only looking at scripts
<!--
The src is the URI of an external script, that is,
a script external to this particular document.
Below, the URIs are absolute paths for getting for files hosted by other services.
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<!--
You can also use relative paths.
If your src value is /socket.io,
then your page looks for a file
relative to the current location of itself.
On localhost, your page has access to files within its own folder
-->
<script src="/socket.io/socket.io.js"></script>
<!--
HOWEVER, in production, you cannot use relative paths
UNLESS you are serving your files either as static assets
via middleware (http://expressjs.com/en/guide/using-middleware.html)
OR via a public route (http://expressjs.com/en/4x/api.html#app.use)
You are getting a 404 in production because you aren't serving
assets.
BUT!!! you can always use an external 3rd party service
-->
As i was thinking all the time the problem was i was not running any node server. I followed these steps, in my case that i was on a free not dedicated hosting (no remote desktop), I used VS Code:
Change my hosting to a windows VPS (with remote Desktop).
Install node.js there.
Create a separate socket.io server app.
Run the server with node index in localhost:8080 with Code cmd.
Installled iis from windows control panel.
Create separate client code that points to server: VPS_IP_ADRESS:8080
Build the client and copy dist folder content to IIS root folder (most probably C:\inetpub\wwroot)
Run IIS.
Now everything works perfectly in my VPS IP in any device. I can chat between my devices. I used IIS for the client because i use to publish there. I think i can´t do this in my old hosting in any way since i ask for Node support and they told me they don´t have. Ubuntu VPS should be a cheaper option but that is to much for me now. If you have expiernce with Node + Ubuntu server, you should try.
I will edit these with the final production code (hidding my IP) in a few hours
This question already has answers here:
How to server specifc static files with express.js
(11 answers)
Closed 4 years ago.
I am developing a express.js app. I am developing admin and users two routes. But in admin section I created sub directories like post, media, etc. I want to use static files like style sheet for post, media, etc.
/admin/posts/js/lib/jquery/jquery.min.js 404 92.978 ms - 19288
where this file locate in
/admin/js/lib/jquery/jquery.min.js
I put all stylesheet and javascripts file in public/admin/. and I want use this stylesheet for all sub directories like posts, media, feedback, etc
app.use(express.static(path.join(__dirname, 'public')));
You can combine static files with dynamically generated content using Express. For example you can default to serving static content, then serve dynamic content for some routes. e.g.
index.js
const express = require('express');
const app = express();
app.use(express.static('./'));
app.get('/info', function(req, res) {
res.json({ status: 'OK', timeStamp: new Date() });
});
app.listen(8080);
index.html
<!DOCTYPE html>
<html>
<head>
<title>Static Root</title>
<link rel="stylesheet" type="text/css" href="/stylesheets/test.css">
</head>
<body>
<h4 class="center">I am static content!</h4>
</body>
</html>
You'd serve this initially from one folder with index.js and index.html.
Any route other than /info will look for static files, e.g. / or /index.html will pull index.html.
You can easily add stylesheets for example, in a ./stylesheets folder
e.g.
/stylesheets/test.css
.center {
text-align: center;
color: green;
}
This is then referenced by index.html
In my express app, I am keeping the below config:
var express = require("express");
var path = require("path");
var jsonServer = require("json-server");
var app = express( );
app.use(express.static('public'));
app.get("/", function( req, res ) {
res.sendFile( express.static( path.join(__dirname, "/public/index.html" ) ) );
});
app.use('/api', jsonServer.router('./db.json'));
app.listen( 3000 );
All this is works fine. the problem is, I am not able to add the jquery from node_modules. here is my HTML :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Promise Defined</title>
<script src="node_modules/jquery/dist/jquery.js" type="text/javascript"></script> //not working sibling folder of public
<link rel="stylesheet" href="styles/app.css"> //works fine. inside public folder
</head>
<body>
<h1>New Title</h1>
</body>
</html>
What is the correct way to fix this? or how to handle this kind of scenario?
Thanks in advance.
node.js does not serve any files by default (unlike some other web servers). So, if you want node_modules/jquery/dist/jquery.js to work, then you have to either make sure that your express.static() line of code will include that file or you have to define a route specifically for that file. Also, it is sometimes dangerous to use a relative path with no leading / because that makes it relative to the path of your page which is generally not necessary and can make things difficult if you want to serve the same file in lots of different pages on your site.
For example, you could do this in the web page:
<script src="/jquery.js" type="text/javascript"></script>
And, this:
app.get("/jquery.js", function(req, res) {
res.sendFile(path.join(__dirname, "node_modules/jquery/dist/jquery.js"));
});
Personally, I would probably move jquery.js to a public/scripts directory on my server so I'm not serving anything out of the node_modules directory, so all my publicly served files are centralized in one place so it's entirely clear what can be served to a client and what cannot and so I could design one or two express.static() statements to serve all my public files.
I am trying to serve an html page with a linked js script using node.js and express.
This is the server that provide the page:
var express = require("express");
var app2 = express();
app2.get('/', function(req, res) {
res.sendfile('./index.html');
});
app2.listen(process.env.VCAP_APP_PORT || 3000);
and this is the page:
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
</head>
<body>
<h1>Demo</h1>
<script src="/js/socket.io.js"></script>
<script src="/js/codice.js"></script>
</body>
As you can see I have two js scripts in my js folder but they are not loaded when I launch the page. What can I do?
What you would normally do is place any public resources (JavaScript files, CSS files, images etc) in a directory (Express names it public by default) and then use the express.static middleware in your app.configure call:
app.configure(function () {
// Various other middleware functions...
app.use(express.static(path.join(__dirname, "public")));
});
This effectively runs a static file server which will return any file inside the public directory. Currently, your browser is making a request for your JS files, but the Express server doesn't know what to do with them. They will eventually time out.
If you generate the initial state of your app with the global express executable (available if you installed Express via npm globally), it will set most of this up for you.