Creating separate versions (development and production) of JavaScript code: a step-by-step guide

I have been working on a small web application that is distributed in a Docker container, using an nginx image. This application consists of plain html and js code, without any frameworks.

Within the JS code, there is access to a remote host via WebSockets. The challenge arises from the difference in environments: when testing on localhost, it operates through http, but on the production server, it must use https. This means that the URL passed to WebSocket starts with either ws:// or wss://

What would be the most reliable solution for maintaining two versions of these URLs in the code, given my intention to have a single Docker image for both development and production, utilizing different Docker Compose configuration scripts?

Here is an example of how WebSockets are implemented:

// For testing in localhost environment
var urlLocal = "ws://" + window.location.host + window.location.pathname + "bridge/";
// For production environment
var urlProduction = "wss://" + window.location.host + window.location.pathname + "bridge/";
BRIDGE.socket = new WebSocket(url);

Answer №1

If you're looking for a more straightforward approach to "template substitution at runtime," here's an idea that may suit your needs.

Instead of reinventing the wheel, consider using the envsubst utility from the gettext package within the base nginx image on Docker Hub. This tool can perform variable substitutions within files by leveraging environment variables. By creating a simple shell script as an entrypoint, we can automate this process at runtime.

To get started, let's craft the entrypoint.sh script:

#!/bin/sh

if [ -n "$BASEURL" ]; then
  envsubst '$BASEURL' < /my.js.template > /my.js
  exec nginx -g "daemon off;"
else
  echo "Ensure that \$BASEURL is defined as an environment variable."
fi

This script will search for a file at /my.js.template, which might resemble something like:

var url = "$BASEURL" + window.location.pathname + "bridge/";

Now, it's time to bundle everything into a new Docker image based on the original nginx. Your Dockerfile should look similar to this:

FROM nginx
COPY entrypoint.sh /entrypoint.sh
COPY my.js.template /my.js.template
ENTRYPOINT ["/entrypoint.sh"]

Assuming that /my.js is the file you wish to modify with the URL based on the environment, launch this image like so:

docker run -d -e BASEURL=wss://myhost mynewnginximage

By providing the BASEURL environment variable, the template will be updated and written to

/my.js</code before executing <code>nginx
as PID 1, just like the original base image does.

In practice, you would need to adjust the paths in the shell script to match your specific setup. However, in essence, you now have the flexibility to use the same image while altering the BASEURL environment variable per deployment. With Docker Compose, you could define an empty environment variable like so:

environment:
  BASEURL:

This configuration will prompt docker-compose to draw on the local shell's setting for

BASEURL</code and pass it to the container when launching it with <code>docker-compose up
:

export BASEURL=ws://myhostfordev
docker-compose up

If any part of this explanation seems unclear, please don't hesitate to reach out for further clarification. For more advanced templating options beyond envsubst, tools such as confd by Kelsey Hightower offer additional functionality along with the ability to incorporate environment variables into templates.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Navigating through pages using Jquery's show and hide functionality

How come my item is not returning? I used the .show() method on the item. <div id="back">< back</div> <div class="item">item</div> <div class="content">My content</div> $(function(){ $('.item').on(&apo ...

Improving Vue Method with Lodash?

In one of my Vue components, I have implemented logic in the watch prop that allows for sequential switching between elements when the down arrow key (key code 40) is pressed. While it is not too messy right now, there is a concern that it may become highl ...

Issues with the functionality of the submit button (html, js, php)

Seeking assistance with a submit button functionality issue - I have a simple submit button that allows visitors to enter their email address. Upon clicking the button, it should add their email to a CSV file and display a pop-up thank you message. The pr ...

What could be causing the Angular router outlet to not route properly?

Check out this demo showcasing 2 outlets (Defined in app.module.ts): <router-outlet></router-outlet> <router-outlet name="b"></router-outlet> The specified routes are: const routes: Routes = [ { path: 'a', com ...

NodeJS CORS functionality failing to function properly in the Google Chrome browser

In my nodejs script, I have implemented CORS as shown below: var express = require('express') , cors = require('cors') , app = express(); app.use(cors()); To fetch JSON data from another domain, I am using an AJAX request. While ...

Google Chrome successfully transmits two variables with AJAX, whereas Mozilla Firefox does not send them

Having an issue with sending two values through ajax - currently only one value is being sent in Mozilla browser. Ajax script: $('#post_submit').click(function() { event.preventDefault(); var great_id = $("#post_container_supreme:first").attr(" ...

Angular: displaying dates in a specific format while disregarding time zones

Is there a way to format date-time in Angular using DatePipe.format() without converting timezones, regardless of location? For instance, for various examples worldwide (ignoring time differences) I would like to obtain 07/06/2022: console.log('2022-0 ...

Creating a data visualization in JavaScript or jQuery without relying on pre-built graph libraries

Hey there, I could really use some assistance. Does anyone know if it's possible to create a line graph in JavaScript or jQuery without relying on any external libraries? It doesn't have to be visually stunning, just functional. If you have any i ...

Is it possible to integrate a GWT library into Dart programming?

Considering migrating to Dart, but unsure of its maturity. Can a library originally written in GWT be used in Dart? ...

Counting gettext values up to a specified number of occurrences

When clicking a button, the elements within this div receive number values. If a specific pattern is reached in the text of these elements, the test should be ended. For instance, if there are 5 elements under the "someelement" div and three of them conta ...

Choose a specific example using the class name in nicEdit

Is there a way to select an instance using nicEdit based on its class name rather than just its id? For example: <div class="myInstance1"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed magna dolor, faucibus ac, iaculis non, cursus et ...

Conceal user input field in React using a hook

I am looking for assistance with a form that has 4 input fields: username, password, email, and mobile. My goal is for the email field to disappear if an '@' symbol is typed in the username field, and for the mobile field to disappear if any digi ...

Tips for persisting objects created in PHP while utilizing XMLHttpRequest

Currently, I am working on a web page with the index.php file structured as shown below: include('UserClass.php'); include('html/top.php'); $user = new User(); if (isset($_POST['user'], $_POST['pass'])) { $user-& ...

I have a specific resolution in mind where I want to run jQuery code during window scrolling

I have a jQuery code that I want to run only when the resolution is greater than 950px. If not, I risk losing the responsive logo. My goal is to create a navigation bar similar to the one on the Lenovo homepage. $(document).ready(function(){ //left ...

Tips on implementing a circular progress bar with locomotive scroll functionality

Can anyone help me integrate progress functionality with Locomotive Scroll using JavaScript? Link to CodePen for reference Check out this code snippet from Locomotive Scroll that calculates the percentage of pages scrolled: const scroller = new Locomotiv ...

React Modals: Only the modal component triggered by the first click will open, with no other modals opening

As a newcomer to StackOverflow, I apologize if my problem description is not clear. I am currently learning React and working on a course-search app as a project. The app filters courses based on user input from a JSON file and displays them in cards with ...

Every time $injector.get is invoked, it triggers the run() method of the Angular module

I find myself in a situation where I need to manually retrieve objects from the Angular $injector. Up until now, I have been using the following approach: var injector = angular.injector(['app.service', 'ng']); var myService = injecto ...

Unable to sign up for WordPress function

I'm having trouble getting my function registered properly in WordPress, no matter how many times I try. So far, here's what I've done: Inserted code into themes functions.php function test_my_script() { wp_register_script( 'custom-s ...

Tips for managing image uploads while incorporating pre-set error detection into a form

I'm facing a challenge with integrating an optional image upload feature into my express app. The issue seems to be related to the way I've structured the app, as it appears to be trying to pass the image name from the body instead of utilizing t ...

Create a regular expression that permits a sequence of numbers (either integer or decimal) arranged in groups of up to five, with each

Is it possible to create a regular expression that allows integers and decimals? var reg = /^((\s*)|([0-9]\d{0,9}(\.\d{1,3})?%?$))$/.; How can users input 0 to 5 groups of integers and decimals separated by |? Updated: This regex sh ...