I'm working on an app that is going to be deploy on-prem (no cloud) and there are requirement to deploy the application to different server path. For example in one company it might be company1.com and on another it might be company2.com/app because they already have a server and want to deploy it on the same server under a different context path.
The problem is in Webpack we compile the app and create HTML+JS+CSS files. The HTML and JS files have the server context path (part after the domain name) hardcoded into the code. For example loading the JS files will be done with <script src="/hello.js" /> so if the app will be deploy to company2.com/app I need the script tag to be <script src="/app/hello.js" />
I'm looking for way to change the server context path dynamically preferably using environment variable.
For compare we use Spring on the server side and there we can define env-var server.contextPath which will change the context path in which the app works.
If it changes anything the app is deployed as docker image.
Any ideas how to implement such thing?
That's an interesting question, and there are some ways you can resolve that. I'll list some options below.
I'm looking for way to change the server context path dynamically preferribly using environment variable.
I will list some other options, but the first one is using env vars.
Using Environment Variables When Building
webpack has a plugin (DefinePlugin) that allows us to set environment variables to the javascript code.
Then, you will be able to get those environment variables using process.env. For exemple, if you have the following configuration:
plugins: [
new webpack.DefinePlugin({
fruit: JSON.stringify('orange'),
MY_VAR: JSON.stringify('value'),
API_URL: JSON.stringify('http://some-api')
})
]
Then, in your code you can get them using:
console.log(process.env.fruit); // "orange"
console.log(process.env.MY_VAR); // "value"
console.log(process.env.API_URL); // "http://some-api"
This said, you can do something like this:
Passing environment-dependent variables in webpack
Then, for example, you can just use process.env.API_URL in your code, instead of using it hardcoded.
IMPORTANT: this method will only work if you have can build your code before releasing it to production. (I think it's not a problem for you).
I think this is the best option, because your code will be "clean", it is more "customizable" and it will "simply work", regardless your environment.
Using a Map
You can have some application logic to decide your variables. For example, you may "look" to the URL (i.e. location.href) and decide the values to use based on this address.
let api;
if (domain === 'domain1.com') api = 'api1';
if (domain === 'domain2.com') api = 'api2';
Using an Extra HTTP Server
You can always point to a hardcoded path in your server, lets say /api. Then, in your code, you will point to /api. So, all your requests will go to /api.
You will need to have an HTTP Server (it can be a Nginx, a NodeJS, whatever you want) listening to /api and then have this "routing" logic there.
It will work fine, but you will need to control the deployment of this HTTP server. This may not be a good option for you, but it may suit your needs.
One advantage is that you'll be able to only change the code of this HTTP server when changing some routes, without need to deploy your front-end code again.
I think that sums it.
Hope it helps!
Related
Problem :
I am new to React JS, and looking for an option to read environment configs from an external property file. This problem is more specific for one of my clients, who is looking to have an option to change the environment files dynamically. E.g. change the hostname/port dynamically whenever there is a change. The build process is not owned by my client. I create a minified final package, which my client deploys it on tomcat/web server.
Tried Solution :
With some read-outs, I have configured .env files for different environments and able to successfully read configs from these files. However, these are more of a build process environment files. And, I am trying to find a way to read the configs from an external source after my package is created.
Possible solutions : Here is one possible approach I can think of -
Read external property file using libraries like "properties-reader". I will provide the property file as part of my release bundle (i.e. build folder). My client can change this property file whenever required.
Please suggest if this is the correct approach or is there a better solution to this problem?
A Solution which worked for me !!
1) Create a "config.js" file inside public folder of react project. Sample Content of the
"config.js" file -
window.env = {
API_DOMAIN_ADDR: "http://localhost:8080"
};
2) Refer "config.js" file inside index.html. Code for index.html will be -
<body>
<div id="root"></div>
<script src="%PUBLIC_URL%/config.js"></script>
</body>
3) Now, content of the config.js file will be accessible to react code. Sample code to retrieve the value of config.js variables -
window.env.API_DOMAIN_ADDR
Add this code wherever variable value needs to be accessed. I added this in my service class which is making ajax call.
I would suggest using something like Firebase Realtime DB. I had a similar requirement for pointing the App builds to production or development server APIs for my company. For this, we use to load a Firebase Config and from there the UI used to pick up the host server endpoint.
Advantages:
This saves you from deploying your build folder every time.
This is realtime and less prone to errors.
FirebaseDB is free for small stuff like this.
The second option is to create two environment files which I see you have already done.
I have a website with game client and a server running next to the website. They communicate via sockets. The problem is that I need to have a way of setting url
for my socket depending whether the code is on server or on my local pc. When I want to debug my code and write development code I want the url to be localhost:5051 and when I push it to the server I want it to be the name of the website with specific port.
Is there any way of determining whether my code is on production or development?
I don't use webpack, I only use requirejs and I would like it to stay that way, because I need to change only one line and I don't want to use the whole framework to change one line.
Let's assume your Node file is server.js and you typically start your app by typing node server.js. When you run your app locally, instead use:
NODE_ENV='development' node server.js
Now in your app, set a var for your url.
var appUrl = (process.env.NODE_ENV === 'development') ? 'localhost:5051' : 'your-prod-url.com';
Use appUrl as needed.
You should be able to determine which environment you're on by logging socket.localAddress and .localPort, where socket is your socket's name, and setting the URL accordingly.
https://nodejs.org/api/net.html#net_socket_localaddress
I'm running a Node.js server along with an Angular frontend. One of the Angular dependencies I'm using requires me to import a javascript file into my html page, by the name of swing.js. However, when I try to do this, it sends the required file as an http request to the server, resulting in requests that look like the following:
http://localhost:3000/home/me/app/node_modules/angular-swing/dist/swing.js
Obviously, this comes up as a 404. As an alternative, I've tried changing
<script src="/home/me/app/node_modules/angular-swing/dist/swing.js"></script>
into
<script src="swing.js"></script>
and then on the server-side, doing:
app.get('swing.js', function(req, res){
res.sendFile('home/me/app/node_modules/angular-swing/dist/swing.js');
});
This works a little more, but then the file doesn't run properly, as I'm assuming it's no longer in the npm environment it needs to be in. I've tried multiple iterations of changing
<script src="/home/me/app/node_modules/angular-swing/dist/swing.js"></script>
into something that uses periods (.) to represent more relative paths, but that doesn't appear to work either. Overall, I'm very stuck, and would appreciate any insight. If it's of any use, I'm also using:
app.use(express.static(__dirname+'/public'));
Making my comments into an answer...
node.js does not serve any files by default so any script files that you need sent from your server to the client upon request need an explicit route to handle them or they need some generic route that knows how to handle all the requested script files.
swing.js in the client is not part of any "NPM environment". It's running the browser at that point, not in any NPM enviornment. It's possible that swing.js itself needs some other scripts or resources that also need routes and that's why it doesn't work after you make an explicit route for it. You can probably examine the specific errors in the console to give you a clue why it isn't working.
You may also want to read this: How to include scripts located inside the node_modules folder?
I have a web server setup. And my web app (JQuery + HTML) is up and running. I would like to use the path that is provided in the URL as some variable and perform different operation.
E.g.
http://subdomain.mydomain.com/
This points to /var/www , and has my index.html
I am trying to achieve the functionality that, when path with some value is provided, e.g.
http://subdomain.mydomain.com/c3212
I will catch the value c3212 in javascript and set it as some static variable. The view/js code in index.html uses this code to make requests to server to fetch some data and layout the data accordingly.
How do I go about doing this ? Googling didn't help much, since I don't actually know what terms should I search for. Do I also need to make changes in Apache VirtualHost configuration?
I am not a web guy, help would be appreciated, thank you.
You can use the window.location JavaScript object to get the path like so:
var path = window.location.pathname;
console.log(path); // this will output "/c3212" based on your example
Once you have this you can use it with the rest of your script.
I hope this helps!
I have a bizarre routing issue with my ASP.NET MVC project that I hope you guys can help me with.
Overall everything works fine when I run the project off my localhost or run it on the server while it's deployed directly at http://myServerName. The problems start when I deploy the application to various enviornments on the server located under different virtual directories. For example: http://myServerName/QaEnviornment or http://myServerName/TestEnviornment
The problem is that all Javascript calls to application URLs ignore my environment virtual directories and fail.
For example on my QA server whenever I have to make an Ajax call I take a standard approach such as:
var myUrl = '/ControllerName/ActionMethodName/'
$.ajax({url:myUrl,success:function(){Do stuff} })
Because my application is deployed on http://myServerName/QaEnviornment, when rendered I expect myUrl to be http://myServerName/QaEnviornment/ControllerName/ActionMethodName. Instead it comes back as http://myServerName/ControllerName/ActionMethodName and ofcourse fails.
To get around this for now I declared a global Javascript variable that contains the environment folder name and when I build URLs for javascript calls I have to remember to ALWAYS construct them as var myUrl = myGlobalFolderVar + '/ControllerName/ActionMethodName/'
Using a global JavaScript variable to get around this issue seems as a bad solution to me. Is there anything I can do to get routing to work properly so whenever JavaScript calls are made whatever subfolder the application is running under is always included in the URL ?
Instead of always having to remember to construct them correctly, make a helper function that you call to create your URLs
function CreateUrl(string path){
return myGlobalFolderVar + path;
}
To answer your second question, not really. Routing is not aware of what made the request and you cannot always rely on the X-Http-RequestedWith header to base that decision on. In addition, your site application root is not at the domain root, therefore routing would only kick in when it visits your application. The only other way I am aware of is to have MVC actually generate the Url for you (var url = '#Url.RouteUrl(params)';) but this does not help at all when you have your JavaScript in a single or a few .js files.
EDIT
The above function is a JavaScript function that can sit anywhere you would like in your application, including external JS files. As for setting your myGlobalFolderVar, there are a few ways you could set this.
1.Actually hard code the variable in your external JS file.
var myGlobalFolderVar = 'TestEnviornment';
This is hard however if you are deploying to several different testing servers.
2.If you are using web.config transformations, you could add an AppSettings key/value pair in your web.config transformations depending on build type. Then, using that value, set your global Javascript variable in your master page layout/views.
<appSettings xdt:Transform="Replace">
<add key="folderLocation" value="TestEnvironment" />
</appSettings>
In your external JS file
//this makes it a site wide/global variable in any place you
//include your external JS file
var myGlobalFolderVar = '';
And in your master view
<script type="text/javascript">
myGlobalFolderVar = '#ConfigurationManager.AppSettings["folderLocation"]'
</script>
3.Same as number two, but use the URL helpers to figure out what the path to your application is in your master view instead of using the web.config transformations
<script type="text/javascript">
myGlobalFolderVar = '#Url.Content("~/")'
</script>
The basic idea is using .NET to figure out where it lives and set a global JavaScript variable with that path information. Then, in conjunction with the helper JavaScript function provided at the top of this answer, you can correctly generate paths as needed throughout your application - regardless of path depth, deployment location or any other deployment type concerns.
var myUrl = CreateUrl('/ControllerName/ActionMethodName/');
$.ajax({url:myUrl,success:function(){Do stuff} });