I am new to Express and semi-new to nodejs and I am trying to run a simple app / webserver as a proof of concept. I have been stuck for hours because my server serves every file as index.html (with the content of index.html).
In my index.html I am making calls to JS files and CSS files and they are all coming back but with a 200 in the console but they are all coming back with index.html content instead of the actual content contained in them. I believe the problem is in my server.js file which is below:
// server.js
// modules =================================================
var express = require('express');
var app = express();
var mongoose= require('mongoose');
var path = require('path');
// configuration ===========================================
// config files
var db = require('../config/db');
var port = process.env.PORT || 9999; // set our port
//mongoose.connect(db.url); // connect to our mongoDB database (uncomment after you enter in your own credentials in config/db.js)
app.configure(function() {
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(express.logger('dev')); // log every request to the console
app.use(express.bodyParser()); // have the ability to pull information from html in POST
app.use(express.methodOverride()); // have the ability to simulate DELETE and PUT
});
// routes ==================================================
require('../../app/routes')(app); // configure our routes
// start app ===============================================
app.listen(port); // startup our app at http://localhost:9999
console.log('Magic happens on port ' + port); // shoutout to the user
exports = module.exports = app; // expose app
// app/routes.js
module.exports = function(app) {
// server routes ===========================================================
// handle things like api calls
// authentication routes
// sample api route
app.get('/api/nerds', function(req, res) {
// use mongoose to get all nerds in the database
Nerd.find(function(err, nerds) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err);
res.json(nerds); // return all nerds in JSON format
});
});
// route to handle creating (app.post)
// route to handle delete (app.delete)
// frontend routes =========================================================
// route to handle all angular requests
app.get('*', function(req, res) {
res.sendfile('/Users/...../app/public/index.html'); // load our public/index.html file
//res.sendfile(path, {'root': '../'});
});
};
I have been following this tutorial verbatum: http://scotch.io/bar-talk/setting-up-a-mean-stack-single-page-application but haven't had much success.
I cannot confirm without looking at your computer but I get the feeling the paths in your application are wrong.
The crucial parts in the express setup are:
app.use(express.static(__dirname + '/public'));
and
app.get('*', function(req, res) {
res.sendfile('/Users/...../app/public/index.html');
The first rule catches and returns any static file in __dirname + '/public'.
The second returns index.html for anything else.
The problem is that your server.js is not in the apps directory (I can see this since you use ../../app/routes.js to get to routes.js) this means __dirname + '/public' is not pointing to the public directory. Which is why your static files are being served by the global rule in routes.js.
In order to fix this change __dirname + '/public' to ../../app/public, or better yet place your server.js file where it should be and update your paths.
I can also see you are using an absolute full path to index.html in routes.js instead of a relative one so it seems as if your applications needs to tidied out.
The tutorial that you are following contains this route
app.get('*', function(req, res) {
res.sendfile('./public/index.html'); // load our public/index.html file
});
which explicitly defines the behaviour you described.
In this tutorial it makes sense because it explains how to build a single page application. This type of the application typically returns the same content for all the request while the actual presentation work happens on the client by the client-side library (angular in this example).
So if you what to serve more pages with different content you need to add more routes for them, just like route for /api/nerds in the example.
Update:
After clarifying that the issue is incorrectly served CSS and JS files, the proposed solution is to check the location of the server.js - it should be in the folder together with the folder "public".
Related
I am having an issue with some custom routing code, it all works fine and is in sync with the client-side view routing I do, but as soon as I have a subpage, it doesn't route my static files correctly.
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
Rather than giving me a file from the root directory, it'll serve it as if it were from the subfolder.
Example: i go to http://localhost/sign-up, and files loading in my index file from /scripts are loaded, but if i go to http://localhost/sign-up/2, it'll attempt to load the script from /sign-up/scripts
const express = require('express');
const path = require('path');
const app = express();
app.use('/views', express.static(path.resolve(__dirname, 'frontend', 'views')));
app.use('/styles', express.static(path.resolve(__dirname, 'frontend', 'styles')));
app.use('/scripts', express.static(path.resolve(__dirname, 'frontend', 'scripts')));
app.use('/media', express.static(path.resolve(__dirname, 'frontend', 'media')));
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'frontend', 'newSite.html'));
});
app.listen(process.env.PORT || 1234, () => console.log('Server is now running...'));
To manage this I have been following these tutorials by DCODE on youtube, but I can't see anything amiss:
https://www.youtube.com/watch?v=6BozpmSjk-Y
https://youtu.be/OstALBk-jTc
Resources loaded in the sign up folder should use URLs beginning with a '/' character, to make them relative to the site root, e.g.
src="/scripts/modulefile.js"
href="/css/stylesheet.css"
href="/media/image.png"
and not urls relative to the signup folder - which they will be if the leading '/' is omitted.
You don't need multiple routes to serve your static contents, and the static method of express do such kind of tasks for you:
// If your 'public' or 'static' directory is one of root directories
app.use(express.static(process.cwd() + '/public'));
// so all these requests will be served:
// -> /public/styles/custom.css
// -> /public/scripts/pollyfils.js
// -> /public/media/logo.png
I have a project made with create-react-app and i would like to use it within express ( as i need some back end functionnality).
basically, my server render a blank page when i run it....
here is the code of my server:
const express = require('express');
const path = require('path');
const app = express();
// Serve the static files from the React app
app.use(express.static(path.join(__dirname, 'public')));
// An api endpoint that returns a short list of items
app.get('/api/getList', (req,res) => {
var list = ["item1", "item2", "item3"];
res.json(list);
console.log('Sent list of items');
});
// Handles any requests that don't match the ones above
app.get('*', (req,res) =>{
res.sendFile(path.join(__dirname , 'public', 'index.html'));
});
const port = process.env.PORT || 5000;
app.listen(port);
console.log('App is listening on port ' + port);
if i enter the endpoint http://localhost:5000/api/getList, i can see the result, but when i want to display my react app for the other end point, the page is blank.
The react app use different Route and i also added a proxy in the package.json.
my server source file is at the root of the react app like the image.
Does someone has an idea why the react app doesnt show?
Thanks
You have two lines that are kind of doing the same thing:
// Serve the static files from the React app
app.use(express.static(path.join(__dirname, 'public')));
Will serve your index.html file to http://localhost:5000/index.html
According to the Express documentation https://expressjs.com/en/starter/static-files.html
And then it seems like you have the second route:
app.get('*', is formatted incorrectly.
It would need to be app.get('/*'.
If you aren't directing the user to multiple routes then it might be better to just use the root, app.get('/', rather than trying to catch all routes.
I am trying to use static files in my project, but when the user makes a get request to my "/" landing page. I want to send non-static things like a json. But for some reason it just automatically sends my index.html in my static file.
const express = require("express");
const app = express();
app.use(express.static("public"));
app.get("/", (req, res) => { //This sends the user to the index.html even tho i want to send 123
res.send("123");
});
app.listen("3000");
As your code is written, the express.static() middleware looks at the / request, finds an index.html file in the public directory and serves that as the response for the / request. This is a feature of express.static() that is causing a conflict for you with your custom route for "/".
You have at least four choices for a solution here:
You can specify an option for express.static() to disable the index.html feature so it will avoid the "/" route and pass control on to your subsequent route handlers.
You can move the express.static() middleware AFTER your app.get("/", ...) route so that your custom route gets first dibs at the request.
You can remove the index.html file from your public directory so express.static() won't find it. Using a template system for all your HTML files that locates all HTML template files in some other directory that express.static() can't see (such as a views directory) would cause this to happen too or just moving it to some private directory and using it from your code from the private directory would work too.
Give ALL your static resources a common path prefix so there is never a URL conflict between static resources and custom route handlers.
The first option (disable index.html feature in express.static()) would look like this:
const express = require("express");
const app = express();
// disable index.html feature
app.use(express.static("public"), {index: false});
app.get("/", (req, res) => {
res.send("123");
});
app.listen("3000");
The second option (change the order of route definitions/middleware) would look like this:
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("123");
});
// put this after custom route definitions so they take precendence
app.use(express.static("public"));
app.listen("3000");
The fourth option (give all static resources a common path prefix) would look like this:
const express = require("express");
const app = express();
app.use(express.static("/static", "public"));
app.get("/", (req, res) => {
res.send("123");
});
app.listen("3000");
With this fourth option, you'd then have to prefix all your static URLs with the static prefix (which you can make anything you want) and thus "/" would never be a match for express.static().
Is there any particular reason that you have an index.html file inside your public directory and are serving something else? The convention is serve static assets such as CSS, JS, images etc. from your public folder, and HTML / templates in folder which would be a sibling of public such as views.
The browser will always default to rendering an index.html file if it is found in the root of the public directory. Move the HTML file to a separate folder and the route should work
app.use is a middleware, so whenever you're running a app, it always first go through the middleware, Try the below code
const express = require("express");
const app = express();
app.get("/", (req, res) => { //This sends the user to the index.html even tho i want to send 123
res.send("123");
});
app.use(express.static("public"));
app.listen("3000");
I'm new on Nodejs.
I have to do a web app with node js, express, socket.io on an existing website.
I use JXcore on Parallels Plesk panel to execute node.
But when I run js file and I visit any page on the website it returns "Cannot GET ".
If I use express get() function:
var app = require('express')();
var http = require('http').Server(app);
var path = require('path');
app.get('/path/to/index.html', function(req, res){
res.sendfile( path.resolve(__dirname + '/index.html') );
});
http.listen(10500, function(){
console.log('listening on *:10500');
});
it works on /path/to/index.html but every other website page is blocked by the same error "Cannot GET ".
Is there a way to run node only on one page?
Thanks
What your code is doing is defining just one route /path/to/index.html and mapping that to your index.html file. If you want to serve files from a directory, static html/css/js/whatever files, you can use the static method express provides:
app.use("/", express.static(__dirname + '/myHtmlDirectory'));
Change the "myHtmlDirectory" to whatever directory you store your files in and make sure to change the includes to define express:
var express = require('express');
var app = express();
However, if you want all GET requests to point to one single file, index.html for example, you can use the following:
app.get('*', function (req, res) {
res.sendfile( path.resolve(__dirname + '/index.html') );
});
I have a basic expressjs app (using jade), but I am having trouble rendering basic Jade files. When I get a request, i parse the url for the pathname and use the handle object to route the request as follows:
index.js
var requestHandlers = require('./requestHandlers');
var handle = {};
handle['/'] = requestHandlers.start;
handle['/download'] = requestHandlers.download
requestHandlers.js
function start(res) {
console.log("request handler for start called");
res.render('home', {title: 'express'});
}
function download(res) {
res.render('download', {title: 'download'})
res.end();
}
exports.start = start;
exports.download = download;
home.jade
h1= title
p Welcome to #{title}
I am using Jade as my templating engine, and have configured the server in a seperate server.js file. When i request either of the pages, the title displays correctly on my browser tab, but the page doesn't display, it just keeps loading. Weirdly, when I cancel the request the page displays. It's as if everything works but nothing tells the process to end?
I am relatively new to node so excuse my naiveté on any of the above. Let me know if there are any questions I can clear up.
I'm not 100% positive why your code isn't killing the TCP connection as needed to prevent your browser from timing out, but I can provide a solution that is friendly towards Express conventions that should solve your issues and maintain code readability, maintainability, and separation.
./app.js (your main server script)
var express = require('express'),
app = express.createServer(),
routes = require('./routes');
app.configure(function () {
// Render .jade files found in the ./views folder
// I believe you are already doing this
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
// Use the built-in Express router
// This kills the "handle" method you had implemented
app.use(app.router);
// Client-side assets will be served from a separate ./public folder
// i.e. http://yourhost.com/js/main.js will link to ./public/js/main.js
app.use(express.static(__dirname + '/public'));
});
// Initialize routes
routes.init(app);
./routes/index.js
exports.init = function (app) {
app.get('/', function (req, res) {
console.log("request handler for start called");
// Render __dirname/views/home.jade
res.render('home', {title: 'express'});
});
app.get('/download', function (req, res) {
// Render __dirname/views/download.jade
res.render('download', {title: 'download'})
});
});
The above prevents you from needing to parse the URL parameters by yourself. Also you can define more readable and powerful request handlers (i.e. app.post for POST methods). You are now enabled to more easily tie in things like the Express-Resource module if you decide to build a REST API.
If you need more powerful mappings you can use regular expressions in the first parameter of app.[get/post/put/del] to filter for specific paths instead.