Express app not firing proxy - node.js

I'm currently building an express app that uses webpack and in order to avoid duplicate files being created (multiple indexes etc.) I'm sending bundled webpack assets through a proxy.
I have the following route:
app.all('/assets/*', function (req, res) {
console.log('foo');
proxy.web(req, res, {
target: 'http://127.0.0.1:3001'
});
});
The foostatement is triggered when I visit http://localhost:3000/assets/ but NOT when I visit http://localhost:3000/assets/styles.css
Even weirder, when I change my SASS files to generate a new styles.css and visit http://localhost:3001/assets/styles.css the updated CSS is present but not when visiting the same file on :3000 (which I guess kinda makes sense if the proxy isn't being fired...)
I'm not gonna lie, this is seriously freaking me out and some hair is about to get pulled out :)

Related

How to serve an app with fastify, regardless of the subdomain?

I'm trying to serve different parts of my app on one server.
For instance, a user could visit,
http://app.my-site.com
or
http://admin.my-site.com
I'm using React on the frontend, conditionally producing the appropriate routes based on the subdomain, meaning I actually have one server serving one frontend that dynamically renders content.
When working with the webpack devserver, I'm able to enable this feature by adding the --allowed-hosts all option.
But then I build the project and try to serve it as follows:
app.register(require('fastify-static'), {
root: path.join(__dirname, 'client', 'dist'),
});
app.setNotFoundHandler((request, reply) => {
reply.sendFile(path.join(__dirname, 'client', 'dist', 'index.html'));
});
This works, but only locally (Heroku throws a 404 error).
After some research, I've found that express has a package for this purpose called express-subdomain. Is there a similar one for fastify or should I be doing something else entirely? After some research, I found answers online suggesting that I should add a CNAME for every subdomain I use.. which I could try, but I'm honestly just trying to understand why building my project works locally but not when deployed elsewhere.
I start the server like this:
​                ​app​.​listen​(​PORT​,​ ​'::'​,​ ​(​err​,​ ​address​)​ ​=>​ ​{
​                        ​if​ ​(​err​)​ ​throw​ ​err​;
​                        ​app​.​log​.​info​(​`Server listening on port ​${​address​}​`​)​;
​                ​}​)​;

Heroku Node/React Deployment Routes Everything to index.html

I have an app.js node main file where I define my api path as the following
app.get('/api/users', UserController.get);
Below in the same file I have the following
app.use(express.static(path.resolve(__dirname, "./front/build")));
app.get("*", function (request, response) {
response.sendFile(path.resolve(__dirname, "./front/build", "index.html"));
});
The index.html successfully serves React App.
If I open my heroku app somewhere at my-app.herokuapp.com it will open the React app which is intended but the Problem is my-app.herokuapp.com/api/users also serves index.html file instead of JSON that the endpoint is supposed to return.
I tried
I replaced endpoint route definition to come before the "" definition (didn't suffice)
EVEN more, I removed redirection to index.html but heroku still opens the index.html page with any type of request (the "" redirection still works). So, it might have cached something?
Is it about cache (how to clean?) or any other suggestions?
You should create routes and work in a proper flow for each functionality,
For Example:
//app.js
app.use("/api/user",userRoutes);
//UserRoutes
router.post("/signup",UserController.signup);
//UserController
exports.signup = async (req,res,next) => {
//Signup function to add a new user when the user provides required info
}
In this way, you code will be easily accessible and much efficient

Serving webpack generated CSS file via CDN in Heroku CI environment

I have an Node.JS Meteor app that I bundle with webpack, that generates a CSS file with a hash in the name: [hash].bundle.css. I can set the publicPath to the CDN domain:
output: {
publicPath: 'https://xxx.cloudfront.com/',
},
On Heroku the bundle will be generated in the staging-environment and the generated slug will then be moved to the live-environment (including the css file).
When there is a change in the CSS, there will be a new hash in the staging-environment. When the site is opened (testing...) cloudfront will be asking the live-environment for that file, but the Node.JS-server responses with the app-HTML, that is issuing a not-found error on the browser.
Idea: Making the CDN fallback to staging
This is recommended in ther heroku documentation. But since the app-server does not respond with a 404 http error, cloudfront will not look at the staging server.
Problem: serving a 404 http error for missing files
This sound's not to difficult. Meteor webapp uses connect and I use FlowRouter on the client side, so I can:
WebApp.connectHandlers.use('/', function(req, res, next) {
if(FlowRouter.matchPath(req.url).route.name == 'not-found') {
res.writeHead(404);
res.end('Not found.');
} else {
return next();
}
});
But: there is many other connectHandlers that I would need to know, and make FileSystem checks. I tried going down that road, but it seems endless, maintenance intensive and not fail-proof.
Idea: Using Meteor's ?meteor_css_resource=1
There is a Meteor specific treatment of a css file with a query parameter xx.css?meteor_css_resource=1, but that won't be counting as a 404 error for the CDN to make the request to staging again.
Instead of checking all available connectHandlers, we filter just the .css files.
WebApp.connectHandlers.use('/', function(req, res, next) {
const urlParts = url.parse(req.url)
if(urlParts.pathname.endsWith('.css')) {
res.writeHead(404)
res.end('CSS file not found.')
} else {
return next()
}
}

Separate Node and React App: Allow Express passthrough to React Router

I have two separate apps: one of them is my API in Node with Express, and the other is my front end in React with React Router.
Typically when doing smaller apps, you might have the server code colocated with your client code in the same repo, but in this case they are separate repos. I am trying to allow passthrough to React Router from Express if the route is not matched, and we traditionally do it like this:
app.get('*', function(req, res) {
res.sendFile(path.resolve(__dirname + 'dist/index.html'));
});
See the problem? I don't have the dist folder on my server, so I have no reference to the index.html available. The reason I broke out the repos is because I upload all the front end code to a CDN, and can just proxy the network requests to my API.
How do I allow the passthrough from Express to React Router if I don't have a file or path to resolve in the res.sendFile catch-all ?
A bit of a hack, but I realized that this would probably work and I tried it out and it does indeed. You can probably take this a step further and even extract the referrer from req.headers.
request("https://yourwebsite.com/index.html",(error, response, body) => {
res.send(body)
}

Angularjs4 with express generator

Just developed a simple angular 4 application with this tutorial
https://scotch.io/tutorials/mean-app-with-angular-2-and-the-angular-cli
But how can i integrate angular 4 app to a express application that generated with express generator??.
One approach is REST API's method that is express JS app use as API provider and the angular application communicate with REST api.
But i would like to serve the angular application from express application itself..
I think this will helpful to you. First I assume, you use express server to handle some api request and let's say those routes are begin with /api. they can be differ from yours.
First build your angular application by ng build and it will create a folder called /dist in your project folder.
Copy that folder in to your express project /public folder. You have to put them in an static routed folder. /public folder is a default static route folder. That is why I put it there. If you have your own one, you can put there too.
edit your app.js file as follows
// Set our api routes
app.use('/api', api); // API router definitions.
// Catch all other routes and return the index file
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
Hope you will help this way. Thanks.
You can serve it through your server like this:
// Catch root route and return index.html
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'app/index.html'));
});
// Catch all other routes
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'app', req.originalUrl));
});
But be careful to set the right path to your index.html.
There is a technology stack called MEAN which means (coincidence :) MongoDB, Express, Angular and Nodejs. So this is basically what you are looking for.
Altough you can create you own file structure, there is a mean-cli similar to Express-generator and the angular-cli. You can find it here.
In order for Angular to work properly (like requesting a site like example.com/something and then also activate the route something) I always return my index.html for any request and setup express to return all static files as well. Then I create a route /api which handles all my REST api requests.
Make sure to first setup your /api route, then your other static files from angular like bundle.js and finally index.html as route **.

Resources