I am building a single page web application with Ember.js or Backbone.js as front end MVC, express.js(node.js) as back end server.
server/app.js code in short
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, '..', 'client')));
app.get('*', function(req, res) {
return res.render('base'); (will sendFile (client/index.html) )
});
It will load up the client/ folder with all the public assets, client folder structure looks like this
- client
-- index.html ( will be rendered as always )
-- app (front end mvc code)
-- assets
-- images
-- styles
When html5 pushstate is enabled by front end MVC, express server is always serving all the matching route as well, which in turn render index.html as always when page is refreshed or url is being manually inserted in the browser.
client/index.html (sample code)
<link rel="stylesheet" href="assets/styles/reset.css">
<link rel="stylesheet" href="assets/styles/base.css">
Here are three different URLs cases
localhost:3000/ (root)
localhost:3000/users || localhost:3000/#/users (hard url)
localhost:3000/users/1 || localhost:3000/#/users/1 ( dynamic segment)
When I defined any static resource as relative path, it works on matching path with root url and hard url on page refresh, it serves resources as
GET /assets/styles/reset.css 304 1ms
GET /assets/styles/base.css 304 2ms
But when I got to localhost:3000/users/1
and refresh the page, I got the wrong resource url, so it failed on loading client/index.html
since there are no resources in that path.
GET /users/assets/styles/reset.css 304 2ms
GET /users/assets/styles/base.css 304 6ms
Then I switched to absolute path in client/index.html (sample code)
<link rel="stylesheet" href="/assets/styles/reset.css">
<link rel="stylesheet" href="/assets/styles/base.css">
it works well even in the dynamic segment url localhost:3000/users/1
, all resource serve in the correct url path. but I have an html img
tag <img src="assets/images/icons/star.png" alt="star">
in front end mvc template which will be rendered when application boots up. When I load up localhost:3000/users/1
on page refresh, here is what I get
GET /assets/styles/reset.css 304 1ms
GET /assets/styles/base.css 304 2ms
GET /users/assets/images/icons/star.png 304 5ms
I tried with absolute path and relative path in front end mvc template (<img src="/assets/images/icons/star.png" alt="star">
), it loads with users
prefix no matter what.
I found a solution by tbranyen, but it did not quite work for me. I do not need to setup any cluster at all, what I want is my express server to serve any resource without any prefix when any dynamic segment is being matched. So I wrote this middleware, and it fires correct but still loads the static resource with users/
prefix.
// this route uses the ":user" named parameter
// which will cause the 'user' param callback to be triggered
router.get('/users/:user_id', function(req, res, next) {
console.log('req.params: ', req.params.user_id );
//console.log('@TODO: need to handle the params here');
//next();
return res.render('base');
});
Problem:
When using Express.js as a server, I want every browser request will be handled with response client/index.html
, even with dynamic query segment. Currently, whenever url query involves with dynamic query segment /users/:user_id
, the response from express server will prefix with users
to all the static resources.
For example, when I load the url with dynamic segment localhost:3000/users/1
. if i have a resources assets/images/icons/star.png
in handlebars template, express server response back /users/assets/images/icons/star.png
, but I do not have users
folder with the assets. What I want response back /assets/images/icons/star.png
.
I tried with absolute path /assets/images/icons/star.png
or relative path assets/images/icons/star.png
in the handlebars template, it always return with users
prefix in the response.
Thanks for any help!
In the <head>
of your base template, add this toward the top:
<base href="/">
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With