node Vue.js different code scenario if run in dev mode - node.js

I have Vue.JS front app with nodeJS backend based on expressJS. ExpressJS also used as web server for statically built Vue.JS app
Front app communicates with express backend via rest and websocket. It uses url host from window.location instance and easily communicates with backend
In production mode, when built application in static expressJS server area, everything work perfect
In dev mode, Vue use it's own web server, and backend urls based on window.location are incorrect because no expresJS on same host and port.
So my question is it possible change some code blocks if running in dev mode ?
Like something this :
if( devmode)
{
const url = "http://somebackendhost/rest"
}
else {
const url = location.host ....
}
}

I will assume you are developing your Vue app using Vue CLI
Changing app behavior depending on environment
In Vue CLI you can use Environment Variables
if(process.env.NODE_ENV === "development")
{
}
This works thanks to Webpack's Define plugin and big advantage is that process.env.NODE_ENV is replaced at build time by the real value. So in production build Webpack will see just if("production" === "development") {} and happily removes the code in optimization phase because it knows this can never be true
Better solution
But I would not use this approach for your problem. Using different API server (not same as the server used for serving Vue SPA) can easily lead to CORS problems
Exactly for this use case, Vue CLI (and Webpack Dev server used under the hood) supports proxying
vue.config.js
module.exports = {
devServer: {
proxy: {
'^/api': {
target: 'http://localhost:58300/',
ws: true, // websockets
changeOrigin: true,
}
}
},
},
This config makes Vue Dev server to proxy any request to /api to other server running at http://localhost:58300/ (your node/express app) and change the origin (so browser thinks response came from the dev server)
All of this can be done without Vue CLI but you will need to set it up by yourself in Webpack config...

The problem
You can't access this information from your browser.
But there are three solutions:
Solution #1
On compilation time create a variable in code which defines devmode (const devmode = true;)
Solution #2
Because your bundler can minify your variable names or changing the scope for security reasons, may be the situation where you can't access it.
So second solution is to define devmode in your localStorage.
Solution #3
Third solution is almost the best.
If you are developing, you are probably accessing your web app via localhost.
location.hostname will return the name of host, so you can make something like:
const devmode = location.hotname == 'localhost';
Best solution
Do not do this. Develop a fully working web app using local REST API and define the URL of REST API in some variable, so when you are preparing your production app, you or compiler just changes the URL adress variable in code of your REST API.
Why is this the best solution?
Because it do not impacts your end-user's performance and they will be loading less code, which is the best practise.
Post Scriptum
Don't forget to remove all devmode codepaths when compiling production version!

Related

Is there any dynamic way of changing the proxy target in React JS (or any other Front-end JS), without restarting the application?

Is there any dynamic way of changing the proxy target in React JS, without restarting the application?
I have multiple node JS servers in the local intranet (which Uses Private IPs, with No concept of deploying using public IP).
And I have one GUI using React JS, which will handle/manage multiple node JS servers.
Using one proxy settings configuration in package.json serves only one NodeJS server, If I update package.json with the next target in proxy, I need to restart the app again.
Is there any way to handle this?
First of all, it seems to be a bad idea to do so. You should have a stable / static proxy. Changing the proxy dynamically will cause many issues in your application.
you will have to handle n/w issues
you will have to handle white-listing/black-listing issues
assets loading issues and many other.
Still, if you want to try:
https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually
Check this URL.
This code worked for React 16.8.13
delete "proxy": {***} from package.json file
type npm install http-proxy-middleware
create the file src/setupProxy.js
-insert the code as following:
src/setupProxy.js
const {createProxyMiddleware} = require('http-proxy-middleware');
module.exports = (app) => {
app.use(
createProxyMiddleware('/endpoint/*', {
target: 'http://address/',
secure: false,
}),
);
};
src/proxy-config.properties
end.point='/endpoint/*'
target='http://address/'
secure=false
And then, you need to change the above code to get the current proxy from a file / DB as follows.
With some code, check whether the proxy is working or not
If not, get new proxy from the file/DB
With you NODE code (or manually), keep changing the proxy-config.properties file.

How can I connect my NodeJS/Express backend to my VueJS frontend using only one port on my local machine?

My Vue app is set up using Vue CLI (Webpack) and it's working as it should. My NodeJS/Express REST API is also working properly. However, to run them simultaneously I now start a local server for each of them -- each with its own port. I would like to have both of them communicate over one port.
Localhost:8080 should point to the home page of my Vue App and the API requests should follow localhost:8080/api/...
In my production environment I use one and the same port/URL by serving the Vue App as a set of static files ('dist' folder). In my development environment I don't know how to set this up, however.
I looked around for answers online, but feel lost among all the different terms I have come across (.env, crossenv, nginx, cors) and that I am running in circles.
What would be a good way of setting this up?
Thank you
Edit:
I ended up creating three modes to run my application:
Development
I use one script in a package.json to start the frontend and backend server on different ports, using pm2 to run the servers in the 'background' rather than blocking further commands in the terminal/cmd. I use configured a proxy inside my vue.config.js to redirect my API calls made in the frontend to the right base URL and used cors as middleware to allow requests to my API from other domains/ports.
Staging
I use one script in a package.json to build the Vue app into a folder ('dist' folder inside my backend folder) that is a collection of static files and start the backend server. My backend is set up to know when I want to go into staging mode and then serve the static files in the 'dist' folder.
Production
I use one script in a package.json to build the Vue app into a folder ('dist' folder inside my backend folder) that is a collection of static files and push my backend (incl. the built static files) to Heroku.
Well if you need to run both on the same port you could first build your app so that you receive a dist directory or whatever your output directory is named and set up an express server that serves that app and otherwise handles your api requests
const express = require("express");
const path = __dirname + '/app/views/';
const app = express();
app.use(express.static(path));
app.get('/', function (req,res) {
res.sendFile(path + "index.html");
});
app.get('/api', function (req,res) {
// your api handler
}
app.listen(8080)
Assuming that node and the 'app' will always run on the same server you can just use a template library like ejs.
You would then just bundle the app and api together, assuming that the front-end is tied to the backend, realistically you would not even need to hit the API as you could just return the records as part of the view, however if dynamic elements are needed you could still hit the API.
Now, with that said, if the API is something used by many applications then it would probably make sense to build that out as its own microservice, running on its own server and your frontend would be on its own. This way you have separation of concerns with the API and Vue app.

Proxy running node-react application

I just created a react-node-SQL app and I want it to run on Google Cloud (not firebase)
My React app runs on different port and my node app runs on different port.
I followed this article and added this line in my react-app package.json but I didn't worked out i.e href in button was still going to localhost:8081 but It didn't worked
I had my node running on port 8080, In package.json of my react app i added "proxy": "http://localhost:8080/" and in button when I did href="/api/status" it was going to localhost:8081 on which the react app was running
Now, Is it possible to run both node and react under the same project? or we need to create separate project for them.
[Update:] I am using webpack, In my webpack config file, I added this
devServer: {
proxy: {
'/': 'http://localhost:8080'
}
},
The problem with this, that even in my react app, on Startup (running on 8081) when it opens the webpage localhost:8081/ it throws an error saying cannot get the page
but if I do something like this
devServer: {
proxy: {
'/api': 'http://localhost:8080'
}
},
it opens the page homepage normally. Now my api and callback uRL after authentication aren't configured with have prefix as api.
Basically, when you do an ajax request from react app, like axios or fetch it will use the proxy: <..> for the backend url. But, href doesn't work with proxies. In that case you need to manually configure proxy using the setupProxy.js documented in the manual proxy page.
Check out this issue:
Same error here, it still routes to localhost:3000/api/auth/google, my
CRA version is 2.1.3 It seems http-proxy-middleware is the only
working way. I have to Configuring the Proxy Manually
From the react doc:
If the proxy option is not flexible enough for you, you can get direct
access to the Express app instance and hook up your own proxy
middleware.
You can use this feature in conjunction with the proxy property in
package.json, but it is recommended you consolidate all of your logic
into src/setupProxy.js.

How to properly configure Browsersync to proxy backend

I'm struggling with proper configuration of Browsercync (and maybe some middleware?).
My configuration is like:
local.example.com it's mine local address configured via /etc/hosts.
devel.example.com it's our company devel environment (backend).
staging.example.com it's our company staging environment (backend).
As I'm UI developer I want to use my local code, but work with one of backend environments.
I'm using gulp to build my project etc. It's also has task to run browser-sync and watch file changes. But of course there is now problem with cookies domains that are coming from backend. CSRF token cookie domain is set by browser to currently used backend.
I have tried:
To use middleware http-proxy-middleware with configuration:
server: {
baseDir: './build',
middleware: [
proxyMiddleware('/api', {
target: 'http://devel.example.com',
changeOrigin: true,
})
]
]
But problem I have is that it's doing non-transparent redirects, which are visible in browser console. I thought that it will work like this, that proxy will mask those requests to browser will think that all requests and responses are coming from local.example.com. But it seems that it doesn't work like this (or maybe I configured it badly).
Also big problem with this solution is that it somehow changes my POST HTTP requests to GET (WTF?!).
To use build in browser-sync proxy option. In many tutorials I saw using proxy option with server option, but it seems not work anymore. So I have tried to use it with serveStatic like this:
serveStatic: ['./build'],
proxy: {
target: 'devel.example.com',
cookies: {
stripDomain: false
}
}
But this doesn't work at all...
I would really appriciate for any help in this topic.
Thanks

Running Keystone.js app over https on Heroku

I have a web app built on Keystone.js CMS for node.js that I will be deploying with a custom domain on Heroku. I want the whole app to run on https by default and not allow any http connections. I've look around quite a bit and can't seem to find a definitive answer as to the best way to go about this. Typically, i.e. for a Rails app, I would just buy a Heroku add-on SSL certificate for my custom domain(s) and point my DNS to point to the Heroku provisioned SSL endpoint. In my app, I would configure to default all connections to HTTPS.
For a node instance (and specifically a Keystone.js instance), I'm a little unclear. Can I just go about the same process as above, buy an SSL add-on and point my DNS to the Heroku SSL endpoint? Do I need to do anything in the base node code to support? And how to enforce https and not allow http?
New to node and keystone and so any help would be greatly appreciated!
Use express-sslify.
I put it in my routes/index.js since the function I export from there receives a reference to the express application.
All you need to do is to tell express to use sslify, but you probably want to not enable it for development.
Since july, Heroku defaults NODE_ENV to production so you can do
// Setup Route Bindings
exports = module.exports = function(app) {
if (process.env.NODE_ENV === 'production') {
var enforce = require('express-sslify');
app.use(enforce.HTTPS({ trustProtoHeader: true }));
}
// Declare your views
};
That will send a 301 to anyone trying to access your app over plain HTTP.

Resources