I am trying to create an express application that works with React and React-router on the front end. So I'm loading the index.html file and let react router handle the rest of the routing. But when refreshing on a page with a react router url that doesn't have an express route I obviously get the message {cannot GET .....}. So i added a fallback route after all my routes to always return index.html when there is no route.
So now I have routes to "/api/...", "/" and "*", I am also serving static files from "/public/build" and "/app/src/static/". When calling the "/" everything works great, when calling the "*" the index.html gets loaded, but the index.js and styles.css files are both loaded with the content from index.html. So my browser gets a styles.css file with a bunch of html in it whereas when using the "/" route the .js and .css files get loaded correctly.
So navigating to "/" loads the index page correctly with all the static files. I can then use my react-router-dom NavLink to navigate to difirent views without making a request back to the server. But when i try to load any react-router-dom page directly I get my index.html but my index.js has the same contents as index.html, same for styles.css
My code:
const app = express();
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
passportConfig(passport);
app.use(passport.initialize());
app.use(passport.session());
app.use('/api/user', userRoutes);
app.use('/api', championRoutes);
app.use('/public/build', express.static(__dirname + '/public/ReactApp/build'));
app.use("/app/src/static/image", express.static(__dirname + '/public/ReactApp/src/static/image'));
app.use("/app/src/static/style", express.static(__dirname + '/public/ReactApp/src/static/style'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'index.html'));
});
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'index.html'));
});
app.listen(8080, () => {
console.log('started on port 8080');
});
The userRoutes and championRoutes variables both contain an express.Router object that has a few routes set.
Edit:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<link href="app/src/static/style/styles.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="public/build/index.js"></script>
</body>
</html>
<script src="public/build/index.js"></script>
This means that the location is relative to the current path, ie, if you are at http://somedomain.com/page2, the path to the index.js will be http://somedomain.com/page2/public/build/index.js (which in your case will serve the index.html file).
To specify a relative path from the base of your url instead, start the path with a /:
<script src="/public/build/index.js"></script>
Related
I have an app that I followed from a tutorial for the backend in nodeJS and Express. My connection to MongoDB via Mongoose is working. However, I've been trying to add a front-end- at the moment- just a simple html/ejs/css form. My endpoints are loading in localhost but only the html/ejs is rendering. My css file shows as plain code at http://localhost:3000/styles.css but isn't loading so I'm just getting plain html/ejs. I'm using VS Code. Here's my relevant code:
App.js:
const express = require('express');
const bodyParser = require('body-parser');
const product = require('./routes/product.routes'); // Imports routes for the products
const app = express();
var path = require('path');
const cors = require('cors');
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cors({
origin: '*'
}));
app.use(express.static(path.join(__dirname, '/public')));
app.use(express.static(path.join(__dirname, 'views')));
app.use("/styles", express.static(__dirname + '/styles'));
app.use('/product', product);
let port = 3000;
app.listen(port, () => {
console.log('Server is up and running on port number ' + port);
});
Product.routes.js
const express = require('express');
const router = express.Router();
// Require the controllers WHICH WE DID NOT CREATE YET!!
const product_controller = require('../controllers/product.controller');
// a simple test url to check that all of our files are communicating correctly.
router.get('/', product_controller.start);
router.get('/test', product_controller.test);
router.post('/create', product_controller.product_create);
router.get('/:book', product_controller.product_details);
router.put('/:book/update', product_controller.product_update);
router.delete('/:book/delete', product_controller.product_delete);
module.exports = router;
Product.controller.js
const Product = require('../models/product.model');
//Simple version, without validation or sanitation
exports.start = function (req, res) {
res.sendFile('index.html', { root: './views' })}
exports.test = function (req, res) {
res.render('index.ejs', { root: './views' })}
Index.ejs
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>HTML 5 Boilerplate</title>
<link rel="stylesheet" type="text/css" href='/public/styles.css'/>
<base href="/">
</head>
<body>
<h1>BookBooker</h1>
<h2>A library app for personal use.</h2>
<form action="/create" method="POST">
<input type="text" placeholder="Writer" name="name" />
<input type="text" placeholder="Book" name="book" />
<button type="submit">Submit</button>
</form>
<script src="app.js" type="module" type='text/javascript'></script>
</body>
</html>
My file structure looks like:
CRUD folder
-app.js
-package.json
-package-lock.json
-controller folder
--product.controller.js
-public folder
--styles.css
-routes folder
--product.routes.js
-views folder
--index.html
--index.ejs
Apologies if it's obvious- I'm super new to this. As you can see, I've tried static files, paths, CORS, and lots of combinations of file routing but I'm getting myself in a big muddle. I've considered caching but the css isn't showing in Chrome, Edge or Incognito mode either. Any help would be appreciated.
Instead of
<link rel="stylesheet" type="text/css" href='/public/styles.css'/>
write
<link rel="stylesheet" type="text/css" href='/styles.css'/>
The public folder name is not part of the stylesheet URL, it is just the folder where express.static looks for files.
The CSS showing as plain text may be caused by a wrong Content-type in the header. The browser is interpreting it as a plain text file, instead of handling it as CSS. Before you send the response, you can set response headers in your controller like:
res.header('Content-type', 'text/css');
See Express Docs
Hope this helps.
I use NodeJs, Express and Handlebars.
My server file app.js
const express = require('express');
const exphbs = require('express-handlebars');
const app = express();
app.engine('handlebars', exphbs({defaultLayout: 'index'}));
app.set('view engine', 'handlebars');
app.get('/start', function (req, res) {
res.render('start'); // render the "start" template
});
app.listen(8888, function () {
console.log('Server running on port 8888');
});
So when passing in the route localhost:8888/start there should be my index.handlebars
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Foo</title>
</head>
<link href="../../CSS/requirements.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<body>
<p>TEST - This is on all pages</p>
{{{body}}}
</body>
</html>
and the template to load (start.handlebars)
<script src="../Client/start.js"></script>
<p>Template 1 is active</p>
My directory structure
When running the server, my route is loading fine but the problem is, that the browser is not able to find the script and css files.
I checked my paths but I think they might be correct. Am I wrong?
You have to set static folder in your express app. Add following middleware
app.use(express.static(path.join(__dirname, 'public')));
right after
app.set('view engine', 'handlebars');
Create a public folder at your root level and move your Client and CSS folder in that public folder.
Ref: Link
I recently switched from starting to learn PHP to NodeJS since I have more knowledge in JS. My question is how do I display posted form data into a HTML File?
server.js
const app = require('express')(),
bodyParser = require('body-parser'),
path = require('path');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.get('/', (req, res) => res.sendFile(path.join(__dirname, 'html/index.html')));
app.post('/student', (req, res) => res.send(req.body.user.name));
app.listen(3000, (req, res) => console.log('Listening on port 3000.'));
html/index.html
<body>
<form method='post' action='post'>
<input type='text' name = 'user[name]'>
<input type='submit' value='submit'>
</form>
</body>
However in the post method, I want to send a HTML file, instead of req.body.user.name which I could obviously do like I did on the home page (/), I want to be able to include some variables into the new HTML File, maybe something looking along the lines of:
<body>
<h1><? req.body.user.name + 's page. ?></h1>
<!-- rest of code -->
</body>
I use ejs template for this purpose and it is very easy to use.
First of all, download ejs with npm install ejs -s and create a views folder inside your main directory. Inside that folder, create a normal html file but this time with an extension of .ejs.
App Directory
-views/myFile.ejs
/post.ejs
-html/index.html
-server.js
Now let's go to your server.js file. You need to use app.set('view engine', 'ejs') to run ejs. When you do res.render() you don't have specify the path because the program already looks for views/ folder in the main directory.
const app = require('express')(),
bodyParser = require('body-parser'),
path = require('path');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.set('view engine', 'ejs');
app.get('/', (req, res) => res.render('myFile.ejs', {username: 'myUser'}));
app.post('/student', function(req, res){
var username = req.body.user.name;
res.render('post.ejs', {user: username});
});
app.listen(3000, (req, res) => console.log('Listening on port 3000.'));
This is our sample myFile.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p><%=username%></p>
</body>
</html>
And this is our sample post.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p><%=user%></p>
</body>
</html>
You should use some template engine, there is tutorial on express page https://expressjs.com/en/guide/using-template-engines.html.
There is always possibility that you can write your own module for handling this.
You can also install express generator
npm install express-generator -g
then call:
express
Thanks to this you will setup express project with jade as template engine(it is default), it should allow you to progress further.
I am serving my front end code using node.js and express.js.
Here I'm facing an issue with my file path I provided in script src on different page URLs.
my project file structure is as follows:
react_jsx/
dst/
index.html
styles.css
main-62a2a28f9255e698905d.js // creating this file using a bundler.
Both styles.css and main-62a2a28f9255e698905d.js are adding to index.html dynamically using webpack bundler. But adding correctly as
<link href="style.css" rel="stylesheet"></head> and <script type="text/javascript" src="main-62a2a28f9255e698905d.js"></script>
Node server code is as follows:
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.resolve(__dirname, 'react_jsx/dst')));
app.use(express.static(path.resolve(__dirname)));
// app.use('/react_jsx/dst',express.static(path.join(__dirname, '')));
app.use(express.static(path.join(__dirname, ' ')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'react_jsx/dst/index.html'));
});
const PORT = process.env.PORT || 9000;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}!`);
});
The page is working fine on the base URL. ie., on localhost:9000.
But when I'm changing the page URL, the path to the files also changes. Suppose if the page Url is localhost:9000/app/login the path to my styles.css and main-[hash].js also changes.
The file path becoming localhost:9000/app/login/styles.css and localhost:9000/app/login/main-[hash].js
How can I resolve it? I went through a lot of SO answers and resolved issue with some other file paths, but couldn't resolve issue with files that located in the same folder of index.html
I think,you can use routing.
Like :
var router = express.Router();
app.use('/app/login', router);
Give relative path from domain root in the html as shown below.
<link href="/style.css" rel="stylesheet"></head>
<script type="text/javascript" src="/main-62a2a28f9255e698905d.js"></script>
Add this to the webpack config
output: {
publicPath: "/"
}
Using Express, I run the index.html file but cannot get the css, js or images to link up correctly. No images showing, css and js not linking.
<link rel="stylesheet" type="text/css" href="css/main.css">
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/main.js"></script>
img/logo.png
I have the following directory structure:
root
app.js
package.json
node_modules
assets
img
css
js
templates
theme1
css
fonts
img
js
index.html
about.html
services.html
news.html
contact.html
In app.js:
var express = require('express');
var app = express();
var path = require('path');
app.get('/', function(req, res) {
//res.sendFile(path.join(__dirname + '/assets/templates/theme1/index.html'));
});
app.get('/about/', function(req, res) {
res.sendFile(path.join(__dirname + '/assets/templates/theme1/about.html'));
});
app.get('/services/', function(req, res) {
res.sendFile(path.join(__dirname + '/assets/templates/theme1/services.html'));
});
app.get('/services/', function(req, res) {
res.sendFile(path.join(__dirname + '/assets/templates/theme1/news.html'));
});
app.get('/contact/', function(req, res) {
res.sendFile(path.join(__dirname + '/assets/templates/theme1/contact.html'));
});
app.listen(3000);
need better understanding of app.get and app.use as well as res.sendFile
Thanks all
So, it's not working because you're not telling Express to serve the files you want (the js and css and so on).
First you want to setup a static route using the static middleware:
app.use(express.static(__dirname + '/assets'));
At that point, everything in the 'assets' directory will be served relative to your root URL. So /img/someimage.jpg is the correct URL for it.