My question might be silly so please bear with me.
Background : I have a project which consists of multiple java solutions as BE and 1 react application as FE application. when we build the entire solution, a war file gets generated which we deploy on different servers to load the application.
Requirement : We need to create single war file irrespective of the env.
Issue : we cannot have separate build scripts and generate different war files, so creating config with different values will not work. the only option is to read the URL and use it. But it wont be available at the time of war generation.
env1 URL : https/abcdefg.com/abc/rma/....
env2 URL : https/abcdefg.com/def/rma/....
Till now, we kept application_context in env file, and were updating that as per the env we are deploying. I am not getting how do I update it without the access of the URL in webpack. And if it can be done in react application, how do I do it? As of now if I deploy env1 war file to env2 I get this error -
GET https/abcdefg.com/abc/rma/script/react-app/vendor/js/index.min.js net::ERR_ABORTED 404
CodePudding user response:
There are two ways you can solve this problem.
First approach involves using <base />
tag along with document.write
. The idea is to generate a bundle without using any hard-coded URL. All the bundle scripts that are added to your index.html
file (probably by html-webpack-plugin) should be relative URLs. The index.html
file should have following code in the head
tag.
<head>
<!-- VERY FIRST STATEMENT -->
<script>
const [_, appname] = window.location.pathname.split('/');
// The trailing slash `/` is important.
document.write(`<base href="/${appname}/" />`);
</script>
<!-- Auto injected by html-webpack-plugin -->
<script src="rma/script/react-app/vendor/js/index.min.js"></script>
</head>
This will cause your rma/script/react-app/vendor/js/index.min.js
to be loaded as https/abcdefg.com/abc/rma/script/react-app/vendor/js/index.min.js
where abc
is your application name parsed from the URL.
However, using document.write
is anti-pattern and discouraged. But advantage is that you can make use of Webpack's hash or chuckhash for bundle names to easily bust cache for the script on each new deployment.
The second approach involves writing an async injector for your bundled scripts. In your index.html
, add the following to head tag:
<head>
<!-- VERY FIRST STATEMENT -->
<script>
document.addEventListener('DOMContentLoaded', () => {
const [_, appname] = window.location.pathname.split('/');
const script = document.createElement('script');
// Use root relative `src` for the scripts
script.src = `/${appname}/rma/script/react-app/vendor/js/index.min.js`;
document.body.append(script);
});
</script>
</head>
The advantage is that this is cleaner approach. The downside is that, you will have slight momentary delay and you need to no upfront the name of the generated bundle file like react-app/vendor/js/index.min.js
meaning you won't be able to use Webpack's [hash]
or [chunkhash]
feature.