How to render multiple static files in express? - javascript

I am trying to use express to render a few different html files from my public folder. These are all static files. I also want to render a 404 page if a route is an invalid route is called. Here is my code.
const express = require("express")
const app = express()
app.use(express.static("public"))
app.get("/", (req, res) => {
res.render("index")
})
app.get("/about", (req, res) => {
res.render("about")
})
app.get("/contact-me", (req, res) => {
res.render("contact-me")
})
app.get("*", (req, res) => {
res.status(404).send("404 for all pages not defined in routes")
})
app.listen(8080)
The first route to render index.html works and the 404 status works, but all the other routes give me an error of "No default engine was specified and no extension provided." I tried added an ejs view engine, but the code still doesn't work. All html files are named properly and live in the "public" folder. Any help on this would be amazing! Thanks much!

You need to use handlebars for handling it. To see an example check this repo

Related

Why can I only load local resources for my index file?

I am hosting a server with nodejs, and have created a login, signup and menu. My login looks like this:
While my signup looks like this:
This is a snippet of my code:
const app = express();
app.use(express.static(path.join(__dirname + '/views')));
app.get('/', checkAuthenticated, (req, res) => {
res.render('index');
});
app.get('/users/signup', checkAuthenticated, (req, res) => {
res.render('signup');
});
Why will the CSS not load for signup, but will for login?
You are likely using relative paths instead of absolute paths. try replacing your 'views/view.css' with '/views/view.css' in your html file.

How to load a .js file in another folder with Express JS and render it?

I have a root directory containing two folders, that all have more folders within, I'm trying to reach the specified file and render it:
frontpage [FOLDER]
- server.js
login_register [FOLDER]
routes [Folder]
- index.js
- users.js
views
- movie_main_page.ejs
How can I take a file (server.js) from frontpage folder and use it in the login_register folder? I'm also trying to render this file as it will now serve as the main page instead of the dummy landing page after logging in (movie_main_page.ejs).
This is the code I use for rendering the landing page:
index.js
const express = require('express');
const router = express.Router();
//Main page of login/register
router.get('/', (req, res) => res.render('welcome'));
//Main page of movie site goes here
router.get('/movie_main_page', (req, res) => res.render('movie_main_page'));
module.exports = router;
users.js
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/movie_main_page'
})(req, res, next);
});
module.exports = router;
I haven't posted the full code from the files because the system works, it renders the movie_main_page fine after logging in, but how can I render another file now that the dummy one works?
Thanks!

Express.js routing 404

I have a problem with dynamic routing with express.js in my react app. Everything works on localhost but when im deploying i get 400. Here's link: https://shoppyshop.herokuapp.com/item/1
As you see in console there is 400 error. My goal is to fetch data properly from that route that i did setup in my index.js of express.
app.get('/api/item/:id', function (req, res) {
let find = data.filter((el => {
return el.product.id == req.params.id
}))
res.json(find)
console.log('found item')
})
I understand that there is a problem with express. Im probably using wrong method so it wants to fetch icon and rest files from wrong path. Was googling, couldn't find similar problem. How to fix that? Here's component that fetches data:
export default class ItemInfo extends Component {
constructor(props) {
super(props)
this.state = {
data: []
}
}
componentDidMount = () => {
axios.get(`/api/item/${this.props.match.params.id}`)
.then(res => {
const data = res.data;
this.setState({
data,
fetched: true
})
})
}
render() {
console.log(this.props.match.params.id)
return (
<div className="App">
<SideBar pageWrapId={"mainpage"} outerContainerId={"MainPage"} />
<div id="mainpage">
<TopBar />
<More data={this.state.data} fetched={this.state.fetched}/>
<Footer />
</div>
</div>
)
}
}
Here's branch with code that im working on: https://github.com/KamilStaszewski/shoppy/tree/itemrouting/client
My express.js file:
const express = require('express');
const path = require('path');
const data = require('./apiData');
const app = express();
// Serve the static files from the React app
app.use(express.static(path.join(__dirname, 'client/build')));
app.disable('etag');
app.get('/category/:category', function (req, res) {
let find = data.filter((el => {
return el.product.category == req.params.category
}));
res.json(find);
console.log('found category');
});
app.get('/api/item/:id', function (req, res) {
let find = data.filter((el => {
return el.product.id == req.params.id
}))
res.json(find)
console.log('found item')
})
// An api endpoint that returns a short list of items
app.get('/api/data', (req, res) => {
var questions = data
res.json(questions);
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 + '/client/public/index.html'));
});
const port = process.env.PORT || 5000;
app.listen(port);
console.log('App is listening on port ' + port);
UPDATE:
After many commits and pushing I found the answer. I dont know if its right way, but it works. The problem was with:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/client/public/index.html'));
});
Instead of serving index from build i was serving index from public which had no js inside it. To make it works i changed to:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/client/build/index.html'));
});
Now it works.
I am pretty sure that this is a problem with how you are serving static files in express.
From the express docs:
app.use('/static', express.static('public'))
Now, you can load the files that are in the public directory from the
/static path prefix.
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html
However, the path that you provide to the express.static function is
relative to the directory from where you launch your node process. If
you run the express app from another directory, it’s safer to use the
absolute path of the directory that you want to serve:
app.use('/static', express.static(path.join(__dirname, 'public')))
Your code has the following for serve static:
app.use(express.static(path.join(__dirname, 'client/build')));
So if I am reading this correctly, as I look at your code, I would understand that to be the following:
When you have an request that comes in for /, the rest of the call will search within client/build for the data. In your case, for your get request to /api/item/:id, that would probably be read by your server to try and find a static file in client/build/api/item/:whatevertheitemidis.
Instead, to serve static files, I would perhaps consider putting them in a directory called 'public' or something, and change your serve static to something like:
app.use('/public', express.static(path.join(//Wherever you keep your static files)));
With this all said, I may have been mistaken regarding some of the nuances of express.static so be sure to checkout the documentation. Either way, I hope to at least have pointed you in the right direction. If you comment out your serve static line and make a request with postman, you should see it working as expected.
UPDATE
I took a look at your code and noticed a couple of things:
I just pulled down your code and the endpoints are working. I tried http://localhost:5000/api/data and it provided the expected data.
It looks like your problem with serving static assets -- such as your favicon -- is because of the %PUBLIC_URL%/ part of your favicon url in your html. So far as I can find, there is nothing in your code that would translate that to an actual route. As soon as I turned that to /favicon, everything started working as expected.

Scotch-io/node-todo app

How is the index.html (frontend Angular) getting called exactly?
In the tutorial, it was said that by having one of the following routes in route.js, frontend is getting called
app.get('*', function(req, res) {
res.sendfile('./public/index.html');
});
----------or-------------------
app.get('*', function(req, res) {
res.sendfile('__dirname + '/public/index.html');
});
But even after removing that route, index.html is getting opened (or) If I rename index.html as index1.html at route and html file it is showing error.
Have you created a file index1.html in public folder? If yes, Use
res.sendfile('public/index1.html');
OR
var path = require('path');
res.sendFile(path.join(__dirname, '../public', 'index1.html'));
to render index1.html.
Note : sendfile is deprecated.

How come my views are not returned when exported from a file in my routes directory?

I'm just experimenting with basic routing in ExpressJS and so far I have two routes:
app.get('/', function(req,res) {
res.render('index');
});
app.get('/pics', function(req,res) {
res.render('pics');
});
When defined like this, in my app.js, everything works fine, but when exported as below, from individual files in my routes subdirectory, I get the error message that a callback function was expected, but an Object undefined was returned.
index.js:
exports.index = function(req,res) {
res.render('index');
});
pics.js
exports.pics = function(req, res) {
res.render('pics');
};
app.js
var routes = require('./routes');
app.get('/', routes.index);
app.get('/pics', routes.pics);
What am I doing wrong in the latter example to break everything?
The index route is working but your pics route isn't because you are trying to import it from index.js.
The route directory has index.js which means that if you do require('./route') you are actually doing require('./route/index'). This happens because index.js has a special meaning in Node.js.
So to get pics working you need to do:
app.get('/pics', require('./routes/pics').pics);
This can be really confusing and is a question that gets asked a lot on the IRC channel.
require('./routes') only loads ./routes/index.js, not ./routes/pics.js. So routes.pics will be undefined.
require() will try to load index.js.
Here is a small coffeescript snippet that you can paste (convert it to js) in index.js. It will autoload all your files(routes) in the current directory:
index.coffee
module.exports = (app) =>
require("fs").readdirSync(__dirname).forEach (file) ->
i = file.lastIndexOf('.')
ext = if (i < 0) then '' else file.substr(i)
if (ext == ".js" or ext == ".coffee") and file != "index"+ext
require("./" + file)(app)
app.js
require("./routes")(app)
someRoutes.js
app.get('/', function(req,res) {
res.render('index');
});

Categories