1

Problem statement

dev team

Dev team wants to pre-build the SPA's (Angular App & React App) and provide single package containing JS, CSS, & HTML file. There's no server-side rendering / lazy loading also. Hence, configurations like service URL, app settings etc. have to be a build parameters. And expects DevOps team to build & deploy different builds for each environment for production as well.

DevOps team

DevOps teams wants to have a single build in QA environment and push the files to Prod, after completing testing. While moving to Prod, only configs can be changed, but all the built code should be same. If any new build is done, it is considered as untested code and hence unfit for production.

Archs

The configs have to be secure & users should not be able to easily read / modify it. Also, site will also be provided with http, hence using cookies or headers might not be a suitable option.

Is there any way to have configuration & application code be separated in an SPA?

Similar Questions:

  1. How to configure a SPA on loading?

  2. SPA javascript configuration file

  • Does your SPA have a backend? Because nothing you do in the frontend is secure. It's on your user's computer where your potential enemy is root. You cannot make it secure. The only option for security is to never transfer this data to the client in the first place. – nvoigt Aug 17 '18 at 10:07
  • @nvoigt No it doesn't. There's a backend service, but it will end up in one more request. – Prajwal Aug 17 '18 at 10:09
  • Well, if your whole app is client side javascript (and html and css) then there is no security. There is only good UI design so that Uncle Joe doesn't by accident click the "delete all" button. But nothing you do client-side is secure in case it's a malicious attacker. – nvoigt Aug 17 '18 at 10:14
0

You are completely right that it should be the same artifacts that are deployed to all environments. Especially in npm, dependencies tend to be loosely defined so a updated dependency could easily break the build just by building at different times. Even if you don't use hat or tilde in packages.json transient dependencies could be less strict with versioning.

What is suggested in the other answer regarding dotenv will not work unless you combine it with #2 og #3 from this answer.

Basically you have a few options.

  1. Switch on the url in order to find the current environment you are in. This is a complete hack. Do not do this!!

  2. Have some server side code replace global vars in index.html on each request. The simplest solution depends on what you have installed on your server. It could be php or even something simple as SSI if you are on IIS. You will want to keep you index.html as valid html so you still can do local development. SSI is nice in this regard since it works inside comments. If you do php, keep your index.html and make a index.php which reads index.html but replaces your vars. A html parser works well for this replacement.

  3. Setup your release to generate a transformed index.html from the index.html created during build. This transformed index contains a snapshot of variables for a given environment when release is run on the environment.

If your needs are simply configuration variables, I would recommend #3. If you need something a little more advanced, go for #2.

  • We are planning to use AWS S3 for hosting SPA files. Then I believe option 3 would be most suitable, but then it is required to know all the environment's variables beforehand. – Prajwal Jan 8 at 5:59
  • You could do something dynamic where you expose all variables at build time. Just be careful you don't expose something you didn't intend. – Esben Skov Pedersen Jan 8 at 6:55
  • I've updated #3 to reflect the fact that most CI environments allow us to specify variables for a environment. – Esben Skov Pedersen Jan 8 at 17:30
  • Now #3 requires the new build, which is against the initial requirement. – Prajwal Jan 9 at 9:14
  • What do you mean "the" new build? There is one build but released to multiple environments. For each environment a transformation occurs. – Esben Skov Pedersen Jan 9 at 10:49
3

I ran into this problem a while back while doing a React App, and came to share my experience.

In my environment, the SPA doesn't have a web server that I can fully control or modify. We use the Azure ASP solution and communicate with other back-end APIs elsewhere.

To provide configurations for these Apps in different environments: on deployment, a JSON file containing our configuration is copied to the build artifact at the root of the site. This config file is then pulled down and consumed by the SPA after the SPA loads.

The consequence of this approach is that your app is making a second request to your site for app configuration, but a major bonus is that, unlike other approaches suggested, you don't have to modify any existing source code.

0

Is there any way to have configuration & application code be separated in an SPA?

This is not only a problem of SPAs.

If you have a look at the 12 factor app, you get the advice

The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.

If you are doing node-stuff, there is the dotenv package, giving you, what you asked for. Or if you are using webpack (which is likely), there is a special package dotenv-webpack.

Regarding security: if you want to version control your "secret files" within the repository, there is blackbox from StackExchange (yep!).

Otherwise, there is Ansible vault, if you are using Ansible or Hashicorps vault. Whether these match your usecase or needs, you have to evaluate for yourself.

  • 1
    Actually, environment variables require different builds to be done, which devops wants to avoid. I'm currently using dotenv to get the configurations now. – Prajwal Aug 17 '18 at 10:12
  • 2
    @Prajwal Why would reading an environment variable require a rebuild? And btw: you can only really read environment variables in your backend. Just saying. – nvoigt Aug 17 '18 at 10:17
  • 1
    @nvoigt because webpack will generate only one JS file which also includes the configuration file. And there will be no backend server to keep configs. It is simple static file serving. – Prajwal Aug 17 '18 at 11:57
  • 1
    It seems more of a social problem than actual a problem about code or tools. – Thomas Junk Aug 17 '18 at 19:46
  • 1
    @DMH New build from same source code isn't considered as untested code? – Prajwal Aug 18 '18 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.