I can't use <script src="node_modules/jquery/dist/jquery.min.js"></script>
in my index.html file because of:
Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8080/node_modules/jquery/dist/jquery.min.js
This happens because of my else statement in server file code:
var http = require('http')
var url = require('url')
var fs = require('fs')
var server = http.createServer((req, res) => {
let parsedUrl = url.parse(req.url, true)
if (parsedUrl.pathname === '/') {
console.log('home page')
fs.readFile('./index.html', (err, data) => {
res.writeHead(200, { 'Content-Type': 'text/html' })
res.end(data)
})
} else if (parsedUrl.pathname === '/readJson') {
console.log('read json')
fs.readFile('./data.json', (err, data) => {
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(data)
})
} else {
console.log('We can\'nt load any resources because of this statement')
res.writeHead(404)
res.end()
}
})
server.listen(8080)
I've read about how to fix this problem when using express module. Is there any way to solve the problem without using that module?
The easiest way would be to simply load jQuery from a CDN instead of serving it from your own server. This is a widely accepted best practice.
Example:
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
You can find various options for loading jQuery from a CDN here: https://code.jquery.com
If you create an HTTP server like in your code example and want it to serve jQuery, then you'd have to read the jquery.min.js using fs.readFile and serve its contents, just like you're doing with your data.json file.
I recommend the use a CDN instead. If you install the jQuery module you can use it for your back-end JavasSript. However you want to use it on the front-end. You are using NodeJS as web server to serve a HTML page. The http module doesn't know anything about other files because it only read the index.html.
So you might wanna search for a solution to read/serve a complete folder. Withing this folder, lets call it public, you can store you HTML, CSS and JS files that are public available. Since the HTTP module knows about the entire folder all files can be used on the front-end. This is also a good solution to separate your back-end en front-end JavaScript.
Related
I have a very simple https Nodejs server that serves an index.html that includes a request for a Javascript file. I cannot seem to get the browser to recognize the Javascript file.
<html>
<head>
<script src="deviceMotion.js"></script>
</head>
<body>
</body>
</html>
For this example, the contents of deviceMotion.js are immaterial. When I load the page and check Crhome debug tools, I receive a syntax error in the first line of the Javascript file, saying
Uncaught SyntaxError: Unexpected token '<'
I look at the "javascript" file's contents only to see that it is exactly the same as my index.html. This leads me to believe that there is an issue with the way my Node HTTPS server is serving the Javascript. Likely, it is just serving the html twice, even though my console logs show 3 separate requests being made, and only 2 when I remove the script tag from index.html. Obviously, it is trying to request the Javascript file, but there is something not right.
Here is the code for my server app.js
const http = require('http');
const fs = require('fs');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
console.log("request received");
console.log(req.headers.referer);
fs.readFile('./src/index.html', function (error, data) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data);
});
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
My files are structured such that I have app.js in the same directory as a folder called "src" and I have index.html and deviceMotion.js under src.
How can I control what files I serve and when depending on incoming requests? How can I differentiate requests made in order to serve the right file? I have tried parsing req.baseUrl and req.path and both are undefined.
Your Node.js server always returns a HTML file and sets the content type to HTML, so when your website requests the JavaScript file, it returns a HTML file, causing the Uncaught SyntaxError: Unexpected token '<' error. To fix the error, don't set the content type and let the browser figure it out, and also modify the code to return the requested file.
I have written some possible code below. However, it will need to be modified to suit your file structure.
const server = http.createServer((req, res) => {
console.log("request received");
console.log(req.headers.referer);
fs.readFile('./' + req.url, function (error, data) {
res.end(data);
});
});
I created a new vue project with the CLI and want to deploy it. Based on this documentation
https://router.vuejs.org/guide/essentials/history-mode.html#html5-history-mode
I added the history mode to the router. After running npm run build I took the example code for a static native Node server
https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations
const http = require('http')
const fs = require('fs')
const httpPort = 3000
http.createServer((req, res) => {
fs.readFile('../base/index.html', 'utf-8', (err, content) => {
if (err) {
throw err;
}
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8'
})
res.end(content)
})
}).listen(httpPort, () => {
console.log('Server listening on: http://localhost:%s', httpPort)
})
So when navigating to localhost:3000 the vue project seems to load correctly
but I have a blank page with two errors
When I click on those js files it shows me the content of the index.html file. Obviously js is not able to understand this html content. How can I fix that problem?
Server will not send the whole vue app at once.
Browser get html file from server, when you browse to that url.
Browser parse the html file.
Browser detects assets (js, images, css).
Browser request those files.
It request those file from server, but you haven't initialized server to find those files.
So, need to add static files.
https://expressjs.com/en/starter/static-files.html
You can take reference from here
as #Sukul answer before, you just need to server the static files because you have now only one handler to server all the request coming with the HTML file (the mount point document) and when its requesting the *.js app it's expecting the valid javascript syntax instead it finds HTML, and that what the error messages are on the network tab
const http = require('http')
const fs = require('fs')
const nStatic = require('node-static');
var fileServer = new nStatic.Server('./public');
const httpPort = 3000
const controllers = (req,res)=>{
if(req.url.includes(".")
return fileServer.serve(req, res);
else
fs.readFile('../base/index.html', 'utf-8', (err, content) => {
if (err) {
throw err;
}
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8'
})
res.end(content)
})
}
}
http.createServer(controllers).listen(httpPort, () => {
console.log('Server listening on: http://localhost:%s', httpPort)
})
node-static ref
however, I highly recommend you trying to use express.js
I'm trying to make a simple game using Node.js and HTML. I want to be able to run the game locally (so localhost). But when I start my Node server, only the HTML content is rendered - my images don't show up and the JS is not loaded. I reference JavaScript files, CSS files and images in the HTML code. Not sure why the server cannot reference these from within the HTML.
Here is my server code:
const path = require('path')
const http = require('http')
var fs = require('fs')
//Set port number:
const port = 3000
const requestHandler = (request, response) => {
console.log(request.url)
response.writeHead(200, {"Content-Type": "text/html"});
response.end(fs.readFileSync('game.html'));
}
const server = http.createServer(requestHandler)
server.listen(port, (err) => {
if (err) {
return console.log('Error: ', err);
}
console.log(`Game started\nGo to http://localhost:3000 to play\n`);
console.log(`Server is listening on ${port}...`);
})
Can anyone tell me how I can get my images/JS loaded?
TIA
You are not serving the static content correctly (i.e. images, CSS). Consider what happens when one navigates to http://localhost:3000/some_image.png - they will be served game.html!
You need to account for users requesting that content in your requestHandler by for example reading the file they want with fs.readFileSync(request.url). Remember to check that they can only request files you want them to be able to read!
You need static handlers to return static content. Check this
https://www.pabbly.com/tutorials/node-js-http-module-serving-static-files-html-css-images/.
Also, if your application is going to be huge then use some middle-ware like Express. (https://expressjs.com/)
If you use express framework, you can use static rendering:
app.use(express.static('public'));
where 'public' is the folder name
I have a text file that I would like to read with Node.js using the fs module. I know how to read the file but I do not know how to take the data of the text files and be able to put it to a website page.
For Example: I would like to read a file that has the contents of 'hello world!!!' and then using jQuery put it to a div.
NodeJS is not a web server.
However, you can easily add dependencies to provide such
capabilities.
e.g. express, koa, or hapi.
So far, you've got [something like]:
const fs = require('fs');
fs.readFile('data.json', (e, data) => {
if (e) throw e;
console.log(data);
});
You could use express as follows (note: if you have not
already run npm init, do so and provide sensible defaults):
npm init
npm install --save express
Then, create a file, app.js, to serve you're data, e.g.:
const fs = require('fs');
const express = require('express');
const app = express();
app.use('/', (req, res) => {
if (e) throw e;
// **modify your existing code here**
fs.readFile('data.json', (e, data) => {
if (e) throw e;
res.send(data);
});
});
app.listen(5555);
Launch your node "web server":
node app.js
Finally, point your browser to:
http://localhost:5555/
If you are using jquery and express just build an endpoint on your express server that serves the contents of the text file.
your jquery:
$.getJSON("/text", function(data){
<write code here to render contents of text file to the DOM>
})
your end point in node:
router.get("/text", function(req, res){
fs.readFile(textFile, 'utf8', function(err, data) {
if (err) throw err;
return res.json(textFile);
})
})
})
As I understand your question you want to "render" the text on the client, not on the server. The easiest way to do this with jQuery is using $.ajax like this:
const URL_TO_STATIC_TXT = 'https://cdn.rawgit.com/fabe/2a371ce28effb32fa1120f8d25225d37/raw/6d0bfebff1d0b52d72ed5ded4011a0bbff80d679/file.txt';
$.ajax({ url: URL_TO_STATIC_TXT })
.done(data => {
$('body').text(data);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Then you only need to host the static .txt files with Node.js, without even using fs. With Express you can achieve this with app.use:
app.use('/', express.static(__dirname + '/public'));
If you want to render the files on the server (using fs) you can also look into countless templating libraries like pug.
I don't know what is the purpose of this, but you can use Express to start a simple web server that provide the content of your text file. Then, you just need to request this web server from your website page using jQuery.
const URL_TO_STATIC_TXT = 'https://cdn.rawgit.com/fabe/2a371ce28effb32fa1120f8d25225d37/raw/6d0bfebff1d0b52d72ed5ded4011a0bbff80d679/file.txt';
$.ajax({ url: URL_TO_STATIC_TXT })
.done(data => {
$('body').text(data);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
So I have craeted a node.js server with two routes. I use the fs to get the html files from the views folder and then append them to the page. In those html files I have a normal link to the css file, which does not seem to work. Here is my node.js app:
var port = 1357;
var http = require('http'),
path = require('path'),
mime = require('mime'),
fs = require('fs');
var app = http.createServer( function(req, res) {
if (req.url === '/home') {
fs.readFile('views/index.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
}
else if (req.url === '/about') {
fs.readFile('views/about.html', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(page);
res.end();
});
}
else {
res.writeHead(301,
{Location: '/home'}
);
res.end();
}
});
app.listen(port);
console.log('Server running on port: ' + port)
In the html files I have:
<link rel="stylesheet" type="text/css" href="./styles/styles.css">
It does not work. In chrome's console I get "Resource interpreted as Stylesheet but transferred with MIME type text/html. "
You defined 2 routes: /home and /about. You also defined that anything apart from these two routes should default to an HTTP redirect to the /home route, and this is what causes the problem.
When the browser encounters the link to the css file, it requests the following URL: /styles/styles.css. the server receives this URL and since it doesn't match the two defined routes it will go into the else statement which will send a redirect to /home, so your browser, asking for a css file, will only receive the html page located in /home.
To fix this, you might need to add a new rule for your css file:
else if (req.url === '/styles/styles.css') {
fs.readFile('styles/styles.css', function(err, page) {
res.writeHead(200, {'Content-Type': 'text/css'});
res.write(page);
res.end();
});
}
Of course, if you have more css files you need to manage a specific folder instead of files. I suppose you're doing this to learn Node, because if you don't you might want to use express which is a Node ready to use web server that will save you lot of time.
When the client (the browser) asks the server for /styles/styles.css the server responds with 301 Moved Permanently and Location: '/home'.
The browser then asks for /home and gets an HTML document, which is not a stylesheet.
You have to give the browser the stylesheet when it asks for it.
static assets (as in your stylesheets) wont be served automatically. So what happens is that it falls through and lands at the 301 redirect to /home, where you serve text/html.
If you want to serve css that way, add a rule req.url==="/styles/styles.css"
Generally, I would recommend using a routing lib like express or koa. Or as minimum, connect. They make it easy to hook in features called middleware and enable you to make everything in a directory (like /public) serve static content with one rule.