Webpack dev server "before" functionality - node.js

I'm working on an ejected Create React App project, and looking at the docs on webpack dev server, they seem a little bare: https://webpack.js.org/configuration/dev-server/#devserver-before
but I'm trying to see if it's possible to do something like:
before(app){
// read cookie for user session
// send user ID in cookie to external API
// retrieve user object from API
// attach user object to response, to be _somehow_ accessed via the React app client side
}
I know this is pseudo code, but I'm very unclear about what exactly you can do within this middleware, in terms of hooking into Create React App's rendering of the index.html and aforementioned client-side React app
In the docs, it says you could define a route handler, like so:
app.get('/some/path', function(req, res) { }
but I don't feel like that's going to be useful, as you wouldn't then be able to hook back into Webpack dev server's rendering process?

You can try adding this in your webpack config file, and practically you can use it as a mock server. Here is an example of how I configured mine and hope it helps.
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true,
before:(app) => {
app.post('/user/login', function(req, res, next) {
res.json({success: true})
});
}
},

In Webpack 5 you can get this goodness by configuring devServer.onBeforeSetupMiddleware.
Angies' answer applies to Webpack 4 devServer.before configurations.

Related

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

Validate http headers for authentication in every page using nuxt.js

I am trying to validate every HTTP request to the nuxt server for authorization.
In this official tutorial,
it requires me to add a validate function in every page, which seems not to work for me, as I'm seeking a way to write a middleware that validates all requests to the nuxt server.
And so, I found nuxt's middleware support, but the official document is really unfriendly, I can't understand at all.
What I'm expecting is a plugin-like module that allows me to put my middleware into nuxt.
Just like what can be achievable in Express (as following).
export default function (req, res, next)
So that I can easily validate headers per request to nuxt.
How can I achieve this? Thank you very much.
Go to your directory middleware/ and create an auth.js
The first argument is your context. Context contains alot of things like your store, app, route, redirect, and it also contains req
You can check out what context has in it: https://nuxtjs.org/api/context/
export default function ({ req, res, redirect }) {
let authenticated = false;
if(!authenticated) {
redirect("/login")
}
}
You can go now to on of your page, and add this to your export default {}
middleware: ["auth"]
Now if you try to access the page you should be redirected to login
I believe Nuxt Middleware is what you need.
In middleware/auth.js
// write any custom validation functions
export default function (context) {
context.userAgent = process.server
? context.req.headers['user-agent']
: navigator.userAgent
}
then in nuxt.config.js
// this will register the middleware functions above for every route
export default {
router: {
middleware: 'auth'
}
}

Angular Universal app can't make post requests to my Heroku node API

My website is a SPA built with Angular, but it uses SSR with Angular Universal to provide crawlable and social media sharing content.
All GET requests in my server are handled by Universal like this:
app.engine(
'html',
ngExpressEngine({
bootstrap: ServerAppModuleNgFactory,
providers: [provider]
})
)
app.set('view engine', 'html')
app.set('views', __dirname)
app.use('/', express.static('./dist', {index: false}))
app.use('/', expressStaticGzip('./dist', {
enableBrotli: true
}))
app.get('/*', (req, res) => {
res.render('./dist/index', {
req: req,
res: res
})
})
and my pages contents are provided by Angular Services POST requests built with the same queryParams of the requested url.
One example:
If the user visits the url https://mywebsite.com/products?page=1&itemsPerPage=12 (GET request by default), the Angular Universal app and the Angular Router dynamically build my page template and the products list is provided by a Service that triggers a POST request to this URL: https://mywebsite.com/request-products with the following params in body:
{
page: 1,
itemsPerPage: 12
}
Then the Universal App builds the template with some *ngFor directives to populate it before serving it to the client.
This approach makes all my pages visible to webcrawlers and I also get the benefits of a Single Page Application.
When I'm testing my app, I build my Angular app, both Browser and Server builds, and set my environment like this:
export const environment = {
production: true,
apiUrl: 'http://localhost:7070/'
}
and serves my app in localhost, it works perfectly, without errors. My POST requests, like mentioned before, are all handled perfectly. But when I try to set my apiUrl to 'https://mywebsite.com/' and serve my app also in localhost, to access directly my API hosted in Heroku, I just can't access my POST routes.
My node express server app in Heroku is configured to accept requests from other domains, I can access it normally in my localhost server, but when I try to access it through my Angular Universal server build, it just won't work.
I know that I have to use absolute URLS in my Universal Apps, and I'm doing it already, but it's not working.
Does anyone know what I have to do to access external APIs in my Angular Universal Apps via https?
Thanks!
I've found the problem, and it's something really simple.
It turns out that I must use 'www' in my absolute url, like this:
'https://www.mywebsite.com/'
Now everything works perfectly, both from my localhost and my heroku servers.
Thanks to everyone that took some time to read my question!

POST request with updating json file using create-react-app

I'm making a project using create-react-app. There is a configured server and so on. I'm using react-router-dom for routing in my app. There is 'Comments' component. When it starts render itself it goes to my local json file and takes comments from there using ajax. When user clicks 'submit' It sends POST request with form's fields to the same json file. I have code for adding a new object to my json file. It should work when user in '/api/comments' route . This is the code for adding a new object to my json file (requires express):
`app.post('/api/comments', function(req, res) {
fs.readFile(COMMENTS_FILE, function(err, data) {
if (err) {
console.error(err);
process.exit(1);
}
var comments = JSON.parse(data);
var newComment = {
id: Date.now(),
author: req.body.author,
text: req.body.text,
};
comments.push(newComment);
fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4),
function(err) {
if (err) {
console.error(err);
process.exit(1);
}
res.json(comments);
});
});
});`
But I don't know where I shoud put this code if I'm using 'create-react-app' and it uses it's own configured server (as far I know). Maybe there is a way to change server which 'create-react-app' uses and put there this code to handle this route? Or maybe there is a way to handle this route using 'react-router'?
If I understand your question correctly the code you have posted here is server side code. The app you have made using create-react-app is a front end application and therefore does not have any server side code. You could however host a second server that would expose the api routes you need and then call into that server using a http library like axios.
I'm using a create-react-app and express as my api server. Setting up express to run alongside webpack-dev-server is a supported feature of create-react-app.
I use npm-run-all to fire-up both the client and proxy express api server in my start-up script defined in package.json. Here is what I believe is all that I needed to do:
In my webpack.config.dev.json file I defined a proxy setting in the devServer json block. Specifically:
proxy: { "/api": "http://localhost:3001" },
In my package.json file I configured a start script that uses npm-run-all to fire up both the react-app and express simultaneously.
I use server.js to fire-up express; this is where I store the equivalent of the code you outlined in your question.

Node React structure without view engine

I'm new to node. I was using express-handlebars as my view-engine, but now I've added React and I understood that I no longer require handlebars. The problem that I'm having is that in order to get to the index.html page, without handlebars, I had to use
app.use(express.static('./public'));
Everything gets rendered from react, but what if I want to do some other things when the user goes to the index page like
app.get("/",function(req,res){
console.log("connected");
});
If I add the get request after exporting the static files, the console.log never gets called. If I use it before, it does get called, but I can see the page loading forever. How should I structure the application now that I'm using react and I don t have a view engine anymore?
In your specific case, if you don't want to render anything to the user, you should turn your function into a middleware :
app.get("/",function(req,res, next){
console.log("connected");
next();
});
and put it before the app.use(express.static('./public'));
However, if you want to do actual logic with return values and such, I would suggest that you setup some kind of API that you request using Ajax from the client.
You can check my repository
https://github.com/kennethmervin01/react-node-production
it's a boilerplate to serve react app in node.js/express
then check my code inside app.js
You just need to copy the production build of your react app inside the react folder
app.use(express.static(path.join(__dirname, "../react")));
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "../react", "index.html"));
});

Resources