Make a directory called env that’s a sibling of src. Put env in .gitignore and also in source-directories.
Inside that directory, put things like modules containing environment-specific paths, third-party API credentials, etc. All they should do is expose constants like strings.
Other modules can import and access values from these as normal. Then you just need a system for distributing different versions of the env modules to team members for local development and the various servers that ought to have different values, and you’re all set!
If any of them ever gets out of sync (i.e. you add a value in one environment and forget to add it in one of the others) the code won’t compile!
Partly yes, but a bit complicated than same domain.
Some reverse proxies can check the referrer of an access and pass it to proper path.
At least, when we use different domain, it should be checking referrer to realize CORS access.
The reason “partly” is because it cannot pass to your local development server if you does not publish your machine to the Internet.
From the above, I recommend the way using reverse proxy if your project uses (or can migrate to use) same domain to serve web API, and if not, using complicated way of reverse proxying or some way like rtfeldman tells.
Here is how I am setting things up to deploy to different environments.
I define a Config module which specifies all the parameters of the environment:
type alias Config =
{ applicationContextRoot : String
, apiRoot : String -- The main API being consumed.
, avatarApiRoot : String -- Another API.
, ... -- More APIs...
}
At the top-level I use programWithFlags, and pass in the config as a Value in the flags, and decode it to a Config.
The config parameters can be put in a .js file, under an environment specific directory, like env described by Richard, and set things up so that the index.html containing the Elm application can pick that up on a known relative path from the web server.
<script src="env/params.js"></script>
OR I set up the back-end server that serves up the index.html to generate that index.html dynamically, and inject the correct parameters.
It is worth getting used to the fact that APIs in development and APIs in test/production are going to be in different locations, so always write your API calls in this format:
getUser : String -> UserId -> Request User
postUser : String -> User -> Request User
deleteUser : String -> UserId -> Request ()
You can also easily write a default Config for development, that would supply “” for the API root locations.
Normally I create two main entries to my app main = Html.programWithFlags { init = init ... } that is used in Main.elm for production and the reactor = Html.program { init = init defaultFlags, ... } that is exposed as main in a Reactor.elm. That way you have the debug settings in elm-reactor and you can use the normal entry for production, this has zero overhead at least for me as a single person developing this
@arowM
I basically assume that web pages and API are different domains. Sometimes they are same but sometimes not. So I’m looking for some solution independent from which the case will be. Also, it could be better if teammates can easily set up that without polluting their environments.
@rupert
Yeah, I tried that in my previous project. But the reason I started this thread is that I don’t like to do that again
@mfeineis
The problem that I wanted to discuss was that “how to write less code to switch the behavior”. So I can pass the flags from the top but have to pass it hundreds of times.
In Ellie I write a variable with a string value that looks like "%API_BASE%" and then I use a string replacement plugin in my build to replace that string with whatever is in the process env