Why express returns index.html when app.css is requested? - angularjs

I serve my Angular app using an express server.
var express = require('express');
var server = express();
server.use(express.static('./app'));
server.all('*', function(req, res) {
res.sendFile('index.html', { root: './app' });
});
server.listen(8000);
Full gulpfile.js is here.
When I navigate to http://localhost:8000, my Angular app redirects to http://localhost:8000/home, and app.css is served properly (I get CSS in the response).
However, if I refresh the page (http://localhost:8000/home), the response for app.css is index.html.
Why is this happening, and how would you fix that?
DEMO HERE

You need to use an absolute path.
<link rel="stylesheet" type="text/css" href="/app.css">
Otherwise the request to express for app.css from /home will be home/app.css not /app.css.

Related

How does express serve index.html for React App and how do I modify it?

I'm an express noob here and building a React App with server using express and client using create-react-app.
What I want to do
I want to update the title and meta tag in the index.html.
So browser requests url -> Server gets request and adds the title and tag to the index.html -> return it to the browser.
Listed my code here
...
app.use(bodyParser.json())
app.use(aMiddleware)
app.use("/api/foo", bar)
app.use(express.static('client/build'));
if (process.env.NODE_ENV === 'production') {
const path = require('path');
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
})
}
Questions
Code is functioning, but I don't know how to replace the title/tag in the index.html
How do I update/replace index for environment that is not prod?
Fo prod environment, I use path.resolve(__dirname, '../client', 'build', 'index.html'), then where is index.html for dev environment? I see there is an index.html in public folder, is it the one that got rendered for dev environment?
I tried to add this code before app.use(express.static(...))
app.get('/', function(req, res) => {
// maybe replace string in the index.html (though I don't know where is it
// then res.send(...)?
})
but this never got triggered. Why?
Stuck on this for a while, tried many things, any help would be great.
You can use react-helmet for this... Or switch to Nextjs which is server side.
https://www.npmjs.com/package/react-helmet

How to fix 404 when reloading page in reactjs

I'm having trouble with reactjs in production, in my development machine i can easily refresh/reload without redirecting to 404 (not found page) but during production every time i reload or refresh in http://example.com/subdirectory/dashboard it will always go to 404 page of http://example.com but when I'm in development machine http://localhost:3000/subdirectory/dashboard when I refresh/reload the page it will reload as expected.
Note: In production I uploaded my static data into subdirectory so i use basename in my route.
If your serving your application on a standard webserver you can add a .htaccess using the following which enables rewrite rules:
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
It's likely that the 404 issue you're facing will be solved by simply just serving the above alongside the root of the project.
Alternately you could use the following as well which would serve it as a node server:
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(9000);
The above can be used in conjunction with a .htaccess.
The create react app guys also promote serve which you can find here and the official react deployment documentation here
1: https://github.com/zeit/serve
2: https://create-react-app.dev/docs/deployment#docsNav
In your http server you have to rewrite all urls to your index.html file. If you are using nginx you can follow this: React-router and nginx
You might have to create a proxy server for your React.js application in production. You can do this in different ways but to do it with Express Node.js, you would have to create a file that looks like this:
const express = require('express');
const path = require('path');
const port = 7700;
const app = express();
app.use(express.static(path.join(__dirname, '../public')));
app.all('*', (req, res) => {
res.sendFile(path.join(__dirname, '../public/index.html'));
});
app.listen(port, () => {
console.log(`Listening on ${port}`);
});
The snippet above assumes you have built your React files and your index.html is in a public directory. This proxies all requests from the express server to your React routes with the * wildcard.
With that done, all that's left is to run this express app on your server and it handles your history API routes just like regular server routes.
add basename inside your src/index.js like this
(you can also add <base href="/subdirectory" target="_blank"> in your index.html file's head tag)
<Router
basename={'/subdirectory'}
>
<App />
</Router>
In your public folder make a file _redirects and write
/* /index.html 200 in it

Serve React App from Express Server Err - not a supported stylesheet MIME type

So I followed the documentation from the creat-react-app-docu and I can not figure out how to serve my react-frontend via express. In the docs it is stated as follows:
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(9000);
But my project structure looks like this:
--root
|
backend
|
src
|
index.ts (My express config)
|
web
|
build (Production build of my react app)
So I had to adapt the config in my index.ts like this:
// Present Frontend view
app.use(express.static(path.join(__dirname, '../../web')));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '../../web/build', 'index.html'));
});
// Start the server
server.listen(3000, () => console.log('BYOD is listening on port 3000!'));
But the error I am getting is that is:
Refused to apply style from 'http://192.168.145.135:3000/BYOD/static/css/main.74ea495e.chunk.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled..
My Question is now: Am I doing something conceptionally wrong? How can I solve this issue?
Update
So I figured out that that the urls in the index.html (within the build folder) has some wrong urls e.g.:
<link rel="shortcut icon" href="/BYOD/favicon.ico"/>
instead of just:
<link rel="shortcut icon" href="/favicon.ico"/>
These urls are automatically inserted by CRA. How can I prevent to load false public-urls into the index.html?
One Solution approach is to add in my frontend dir (react-project) a .env file and set explicitely the following:
PUBLIC_URL=/
My question now is there a better solution or is my project architecture completely messed up? Im extremely curios for advices! Thanks in advance!

How do I rewrite all urls to index.html in Heroku?

My Heroku app is using React with React Router. I use Switch to navigate through different components, so the URL changes as well (e.g. /room/4141). However, if I reload the page, it doesn't act like if it was a React app, but instead it searches for the mentioned .html file.
I used this Buildpack: https://github.com/mars/create-react-app-buildpack.git but it seems to do nothing in regards with pages being rewritten to index.html.
Is there a way to prevent this behaviour and rewrite all URLs to index.html?
**EDIT:
I'm not familiar enough with express, but here's how the index.html is served.
const express = require("../../node_modules/express");
const app = express();
const server = require("http").Server(app);
const io = module.exports.io = require('../../node_modules/socket.io/lib')(server)
const path = require("path")
app.use(express.static(path.join(__dirname, '../../build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../../build')));
console.log("DEBUG HERE", __dirname, path.join(__dirname+'../../build'));
//
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../build/index.html'));
})
}
//build mode
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../public/index.html'));
})
That buildpack can be configured via a JSON file:
You can configure different options for your static application by writing a static.json in the root folder of your application.
One of the sample routing configurations looks like it does exactly what you want:
When serving a single page app, it's useful to support wildcard URLs that serves the index.html file, while also continuing to serve JS and CSS files correctly. Route ordering allows you to do both:
{
"routes": {
"/assets/*": "/assets/",
"/**": "index.html"
}
}

Express Pass Variable to Angular Without Templating Engine

Question: Does this work without e.g. ejs/jade? And where is the difference between a framework like AngularJs and a templating engine?
E.g.
Server.js
var express = require('express');
var app = express();
Routes.js
app.get('/', function(req, res) {
// res.render('index.ejs');
res.sendfile('index.html', {
user : "Tom"//req.user
});
});
Index.html (Here I have no idea how to do this)
<body ng-app="App" id="App" ng-controller="RootCtrl as rootCtrl" ng-mouseleave="rootCtrl.exit()">
<script>
// angular.module('$user', []).constant('$user', <%= user %>)
</script>
....
Tutorials I looked into:
http://www.mircozeiss.com/how-to-pass-javascript-variables-from-a-server-to-angular/
http://www.linkplugapp.com/a/224929
Yes this should work, but you need to enable ejs in your express app.
app.set('view engine', 'ejs');
I did the same thing with laravel and blade.

Resources