Search code examples
visual-studioember.jsember-cli

altering ember baseURL at deploy- or runtime


I'm a back end dev working on a project which includes an ember front end. Our project is unusual in that we have no production access; we write the code and deliver to client. The client is only comfortable/willing to use the Microsoft web stack, so we build the ember project, wrap the resulting contents into a simple Visual Studio project, and hand it over for deployment.

This client has unfortunately put us in a position that is apparently unusual in the ember world:

  • Client is unwilling to install or execute any of the ember-cli tools or commands
  • Client uses different directory structures for test and production sites (i.e. "http://staging.example.com/project" vs. "http://project.example.com/")
  • To honor the above requirements, we have been shipping separate builds for the two different environments. But this is also considered unacceptable in the long term.

Obviously, this is a situation that no one would have chosen with perfect foresight. Most of these restrictions were not made explicit until it was too late, but realistically the client will not be changing them. I am looking for a technical solution that looks like this:

  1. We develop in ember
  2. We use ember-cli tools (or equivalent) to build front-end
  3. We package results into one visual studio project, which may include web.config for client's test environments
  4. Zip up and deliver to client
  5. Based on settings in web.config, our ember project configures itself to:
    • set baseURL to appropriate value
    • connect to our REST API located at environment-specific URL

In order to solve the problem, I have been reviewing the following:

Unfortunately, I am personally unfamiliar with ember. So I don't understand how baseURL is really used yet, and why it seems to be so awkward to parameterize ember at deploy- or runtime. Where can I go to learn how to mash our work into an acceptable deployment process?

Is it possible to send values for baseURL or ourBackendApiURL to ember by putting META tags onto the index.html that loads the site?


Solution

  • Here's what ultimately solved it. Basically, we took the index.html which was created by "ember build", and found the meta tag which was passing in the values from environment.js to our javascript at runtime. By generating that meta tag in index.cshtml, we were able to use values specified in web.config.

    Now when we build the app to hand off, we simply ignore the index.html that it generates, but add the rest of the assets to a pre-made visual studio web project. That project may be configured for testing or production.

    First, I created an empty web application in visual studio. In web.config, I added this:

    <appSettings>
      <add key="hostName" value="https://apps.example.com/" />
      <add key="baseURL" value="/projectDir/" />
      <add key="serverNamespace" value="api" />
      <add key="imgSrc" value="https://images.example.com" />
    </appSettings>    
    

    and then index.cshtml was written to make use of those values:

    @{
        if (!Request.Url.AbsoluteUri.EndsWith("/"))
        {
            Response.Redirect(Request.Url.AbsoluteUri + "/");
        }    
    
        var configStr = @"{{
        ""modulePrefix"": ""foo-bar"",
        ""podModulePrefix"": ""foo-bar/pods"",
        ""environment"": ""production"",
        ""baseURL"": ""{3}"",
        ""locationType"": ""hash"",
        ""namespace"": ""{0}"",
        ""host"": ""{1}"",
        ""foo-auth-host"": ""{1}"",
        ""APP"": {{
            ""name"": ""foo-bar"",
            ""version"": ""0.0.0""
        }},
        ""contentSecurityPolicy"": {{
            ""default-src"": ""'none'"",
            ""script-src"": ""'self'"",
            ""font-src"": ""'self'"",
            ""img-src"": ""'self' {2}"",
            ""style-src"": ""'self'"",
            ""media-src"": ""'self'"",
            ""connect-src"": ""'self' {1}""
        }},
        ""simple-auth"": {{
            ""authorizer"": ""authorizer:foo"",
            ""routeAfterAuthentication"": ""/"",
            ""store"": ""simple-auth-session-store:local-storage""
        }},
        ""contentSecurityPolicyHeader"": ""Content-Security-Policy-Report-Only"",
        ""exportApplicationGlobal"": false
    }}";
        var serverNamespace = System.Web.Configuration.WebConfigurationManager.AppSettings["serverNamespace"];
        var hostName = System.Web.Configuration.WebConfigurationManager.AppSettings["hostName"];
        var imgSrc = System.Web.Configuration.WebConfigurationManager.AppSettings["imgSrc"];
        var baseUrl = System.Web.Configuration.WebConfigurationManager.AppSettings["baseURL"];
    
        var configStrPopulated = string.Format(configStr, serverNamespace, hostName, imgSrc, baseUrl);
        var configStrCompacted = System.Text.RegularExpressions.Regex.Replace(configStrPopulated, @"\s+", "");
        var configStrEncoded = HttpUtility.UrlEncode(configStrCompacted);
    }<!DOCTYPE html>
    <html>
    <head>
        ... 
        <meta name="foo-bar/config/environment" content="@configStrEncoded" />
        ... 
    </head>
    <body>
        <script src="assets/vendor.js"></script>
        <script src="assets/foo-bar.js"></script>
    </body>
    </html>