Webpack somehow bypasses Express routing completely - node.js

I am starting from this excellent tutorial: https://www.fullstackreact.com/articles/using-create-react-app-with-a-server/ and trying to extend it by adding a new page to serve through a new route. However after hours of mucking around I am realizing that somehow create-react-app is doing some weird magic (as mentioned in their docs here):
`create-react-app` configures a Webpack development server to run on `localhost:3000`.
This development server will bundle all static assets located under `client/src/`.
All requests to `localhost:3000` will serve `client/index.html` which will include Webpack's `bundle.js`.
The key quote is "All requests to localhost:3000 will serve client/index.html". I have no idea how this happens. So even though i mess around with routes/index.js:
app.route('/')
.get(function (req, res) {
res.sendFile(bipath.join(__dirname, '../public', 'THISCANBEANYRANDOMFILENAME.html'))
});
it doesnt matter because webpack is somehow directing localhost:3000 to index.html anyway. where and how is it doing this? Bottom line I am trying to modify my routes to serve a new html file and am running into all sorts of filepath issues (yes, even when i use require('path') or sendFile(...,{root: __dirname}).)
So what exactly is going on here and can you give me any hints to help me out?
Edit: this could be from babel as well as webpack - i'm not exactly clear where babel hands off and where webpack starts.

I haven't played around with create-react-app, but it seems like instead of using the default npm start, you could create your own server file and run that.
This looks like a good example.
https://medium.com/#patriciolpezjuri/using-create-react-app-with-react-router-express-js-8fa658bf892d#.6y4rrl61q
Alternatively, if you're looking to have routes used as an api, you could proxy them to a different port like shown in the tutorial you linked.

Related

Deploy production build of ReactJS with Node express as backend

Hi even after lot of search i am still confused what is correct way to deploy my react app created using create-react-app with express as backend.
I ran npm run build which created build folder. I copied the build folder to be served as static folder of express and had put
app.use(express.static('build'));.
It is working fine for homepage, that is homepage opens when i run my express node server but when i go to anyother link outside homepage it gives 404.
Everything is working fine in developer mode, which i run by npm start command. I just want to know what i am doing wrond here. Let me know anymore info required to understand the problem. Thankyou.
It sounds like you don't have the backend server running. You need to npm start your server, and then npm start your front end if that make sense. They are 2 separate things.
Are you using client-side routing? A popular implementation of that is react-router.
Let say you are trying to access /page1, what client-side routing does is use the JS to toggle between different components to "fake" the routing, instead of rending a new HTML.
Yet, by default when you change routes, the browser does the usual stuff and send a GET request to the server asking for the corresponding HTML file. But since you only have index.html served, that's why you received 404.
You need to add the following at the end of your app.js, right before you call app.listen of your express server to tell the server to always return index.html no matter what route does it received.
/* client-side routing.
* For GET requests from any routes (other than those which is specified above),
* send the file "index.html" to the client-side from the folder "build"
*/
app.get("*", (_, res) => res.sendFile("index.html", { root: "build" }));
// your usual app.listen
app.listen(port, () => console.log("Listening"));

React frontend, Node JS backend to hosting

How to host an application React js with node js backend. Couldn't find anything on the internet. Do I need to run the
build
command on the backend? Help me please.
Thanks in advance.
The way I do it:
I build my react project and host it on the server.
As for node js, I run it on it’s own, and use Pm2 to run it on the server ( https://pm2.keymetrics.io/docs/usage/quick-start/ ) but there’s plenty of other ways you can find on google.
I hope I answered your question
I suggest you use Heroku, you get to host your full stack application for free, directly from your GitHub reposity, it takes care of automatic redeploys whenever you push something on your repo.
The only – slight – downside is having to wait ~5 seconds for the server to start up if your app hasn't been visited for a while and becomes idle (if you use a free option that is).
There are plenty of tutorials on how to do so.
As for serving the static version to your app in production — this could be of use:
server.js
/* If in production mode - serve compressed/static react content to server. i.e. what would be otherwise localhost:5000 would display frontend content.
/!\ Do not forget to generate Procfile and script for Heroku to insure proper generation of "build" directory /!\ */
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "../frontend/build")));
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "../frontend", "build", "index.html"));
});
}
Heroku will take care of it automatically if you tell your server to serve the static version with the code above.
There is also Glitch.com

Node.js (MERN) Serving static files and API's

Im currently building a simple app using the MERN stack to learn. What Ive done so far:
-User Registration and Login (API)
-TODO List (API and Frontend with static files)
Ok, Everything works good and as expected, except for one thing.
I attempt to use my API's for any request, but at the same time I want my whole app to work rendering in a web browser (TODO list). So, the process I've followed is:
-Start node instance
-npm run build (To build react project files)
I did a research on how to use React build in node project and I did the following:
app.use(express.static('myproject/build'));
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'myproject', 'index.html'));
});
Good! So when I go to http://localhost:4000, it renders my index file and it actually works with my Login API, but I have some API's that are only available for consuming data and not rendering UI.
So, my problem is that when running the app, if I go to: http://localhost:4000/api/users/getdata
I get an error saying: Error: ENOENT: no such file or directory pointing the index.html
Ok, if I uncomment the code I posted before, then of course my app is not rendering UI, but my routes from API's work normally.
I know this might be setup/configuration process, but Im trying my best to understand this. If somebody could assist me with this problem please.
The hierarchy im working goes as follows:
myproject (contains models, routes (API's), middlewares, index.js)
frontend (inside folder 'myproject') (build, src (Components))
I did what #MaxAlex suggested. Changed the code from:
app.get('/*')
to
app.get('/')

react-router, resolve URL beyond root

I have a create-react app with react-router-dom. It works quite well if I start from the root (i.e. '/') and then follow links defined in Links. But if I try to load the app not from the root path, it says
Cannot GET /<path>
As I understand, this should be set on the server-side (I am working on regular localhost:9000). Or not? Anyway, how to achieve this practically?
Notice, this is not relevant to the base path resolving problem, described here: Can I set a base route in react-router
UPDATED:
I suppose, there should be a solution similar to using .htaccess. But I still cannot figure out how to apply it to create-react-app. Or, maybe, it is possible to set an appropriate option in webpack.config.js?
Update 2. Repo is here: https://github.com/srgg6701/react-mini
Since all your routes are handled by a router, which normally sits in the '/' (index) path, you would need to fallback to your index so that the router knows where to redirect. This can be done by setting the paths on your server side, but I've found this package to be particularly helpful in these matters.
Webpack
If you are using webpack-dev-server, you should know that it serves the following (taken from official docs):
Use webpack with a development server that provides live reloading.
This should be used for development only.
It uses webpack-dev-middleware under the hood, which provides fast
in-memory access to the webpack assets.
...
Either method will start a server instance and begin listening for
connections from localhost on port 8080.
This means that a server will be running listening to localhost. You can either solve this by using the previous approach (server side coding or middleware) or by using the history api fallback option:
"scripts": {
"start": "webpack-dev-server --history-api-fallback --config webpack.dev.config.js",
"build": "webpack"
},
Have a look at the official documentation of webpack for more info on all of its components.

Express app doesn't find node_modules folder to load scripts from

I'm rather new to how webservers behave in general, so I have a few questions I hope someone can help me with.
It would also be nice if anyone could point me to an article or some documentation about the following topics.
Basically I'm trying to develop a webapp using Angular2, Expressjs and obviously node.js.
I have already successfully developed some basic Angular2 apps without a backend attached to it, which worked fine.
However, now I'm trying to send the index.html file (which contains a tag referring to an Angular component) to the browser from my server.
app.get('/test', function(req, res) {
res.sendfile('index.html');
});
You can find the html here: http://pastebin.com/utMHk8Pe
However, even though the node_modules package is on the same hierarchic level as both server.js and index.html, going to localhost:8080/test gives me a 404 for the node_modules script files in my html header.
Q1: Why doesn't my server find the node_modules folder?
Now, when I run my index.html file through following link, http://localhost:54720/testapp/index.html, everything works just fine.
Somehow it finds the node_modules at port 54720 but not 8080 (which is the port I made the express app listen on).
Q2: Why can't my server find the node_modules folder at the port I make it listen on?
As I've already said, I'm really new to node.js and webservers in general.
I'd be very grateful for any help!
Even linking me to an article which could be helpful would help me tons, since I can't really find anything since I don't know what to Google for.
You need to define a static folder to enable this. Something like this:
var express = require('express');
var app = express();
(...)
app.use('/static', express.static('public'));
This way, you will be able to serve the static files you need for Angular2, the ones that are present under the node_modules (angular2, systemjs and rxjs).
See this documentation for more details: http://expressjs.com/en/starter/static-files.html.
Hope it helps you,
Thierry

Resources