Integrating an external JavaScript library into the codebase

I created a web radio player using Vue Cli and now I need to incorporate a new feature with an external library, specifically designed for handling audio advertisements. The catch is that this library must be loaded from a remote server and cannot be simply downloaded and imported locally.

Initial Setup

Within my Vue App, I have various components and one of them includes an audio tag responsible for radio playback. My goal is to detect when the play button is clicked, load the advertisement, play it, and then resume regular radio playback.

Approaches I've Tried

  1. Initially, I attempted loading the external library in the index.html file. While this worked, I discovered that I couldn't interact with the player being loaded in Vue. For instance, trying to listen for the play event in the index.html file (
    audio.addEventListener("play", onPlay);
    ), resulted in receiving an error stating "audio not defined" in the web console.
  2. Subsequently, I tried loading the external library within the mounted() section of my component:
const triton = document.createElement('script')
triton.setAttribute('src', '//sdk.listenlive.co/web/2.9/td-sdk.min.js')
document.head.appendChild(triton)
this.initPlayerSDK()
triton.onload = () => {
  let player = new TDSdk(this.tdPlayerConfig)
  console.log(player)
}

The issue with this approach arose after running npm run serve, where I encountered the message 'TDSdk' is not defined . This makes sense as I am loading the external JS file, but webpack isn't interpreting its content since it's done at runtime. Adding the external library in my vue.config.js didn't resolve this either:

vue.config.js

const path = require('path')

module.exports = {
  publicPath: './',
  chainWebpack: config => {
    config.module
    .rule('images')
    .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
    .use('url-loader')
    .loader('file-loader') // not url-loader but file-loader !
    .tap((options) => { // not .option() but .tap(options...)
      // modify the options...
      options.name = 'img/[name].[ext]'
      return options
    }),
    config.externals([
      {
        'tdSdk': 'TDSdk'
      },
    ])
  },
  css: {
    loaderOptions: {
      sass: {
        sassOptions: {
        includePaths: [path.resolve(__dirname, './node_modules/compass-mixins/lib')]
        }
      }
    }
  },
  externals: {
    tdSdk: 'TDSdk'
  }
}

myComponent.vue

import tdSdk from 'tdSdk'

Answer №1

I came up with a solution by loading the library in the public/index.html file and then waiting for the DOM to be fully loaded. This way, I could add an event listener to the audio element that was already loaded:

document.addEventListener('DOMContentLoaded', function() {
var playControl = document.getElementById('playIcon');
playControl.addEventListener("click", onPlay);
}

In order to access the variables defined in the javascript located in the index.html within my Vuex store, I needed to make window.adState (the variable I'm using) a global variable in my store file:

Vuex.Store.prototype.$adState = window.adState

Lastly, in my actions/mutations, I utilized this.$adState to examine its contents:

playPause ({ commit, dispatch }) {
console.log('AdState', this.$adState)
(...)
}

This answer was provided on behalf of the original poster.

Answer №2

When evaluating the script, the import cannot be resolved because the global TDSdk is not available. Any script dynamically added to the head will be loaded asynchronously, leading to a potential race condition.

If there is dynamic behavior involved or if a developer lacks control over the page layout, <script> needs to be added dynamically. For static scripts in a Vue CLI project's public index.html, modifications can be made:

  <body>
    <div id="app"></div>
    <script src="//sdk.listenlive.co/web/2.9/td-sdk.min.js"></script>
    <!-- built files will be auto injected -->
  </body>

The application bundle is evaluated after the script, so the global should be available at that point.

Externals are often used for packages that have been replaced by externally loaded ones, typically from a CDN. Since tdSdk is not an actual package and is unlikely to be swapped out, it is best to use it as the TDSdk global within the application instead of mapping and importing it.

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

Despite passing the same dependency to other services, the dependencies in the constructor of an Angular2 Service are still undefined

To successfully integrate the "org-agents-service" into the "org-agents-component," I need to resolve some dependencies related to the required api-service. Other components and services in the hierarchy are also utilizing this api-service, which acts as a ...

The ajax success error function does not trigger in jQuery

Hey, check out my code below: <html> <head> <script src="http://code.jquery.com/jquery-1.8.0.min.js"> </script> </head> <body> <form id="foo"> <label for="bar">A bar</label> <input id ...

Does the Mirage addon work effectively in the ember.js tutorial?

Following the ember.js tutorial, I'm facing a roadblock at this particular stage: (especially when implementing the Mirage add-on). I've made changes to the mirage/config.js file as advised but still unable to display the Mirage data. Despite ...

Angular's radio button is set to "checked" on a pre-configured model

Looking for help with customizing alignment of images in a bootstrap/angular template? Check out the code snippet below: <div ng-repeat="a in attributes"> <div class="btn-group" data-toggle="buttons"> <label class="btn btn-white ...

I'm having some trouble with my jQuery.get() function in the javascript Saturday(), can anyone help me figure out what I'm doing wrong?

Can anyone help me troubleshoot my jQuery.get() method in the saturday() JavaScript function? Here is the code snippet I have been working on. This is what I have in my index.html file: <html> <head> <title>jVectorMap demo</title> ...

The functionality of Angular/Typescript class.name appears to fail during a production build

Using Angular 5, I encountered an unusual problem with the class.name property. We have a TypeScript function as shown below: export class ApiService { public list<T>(c: new(values: Object)=> T) { var cname = c.name; .... } } When ...

The main content will be displayed on the sub-routes of the child

I'm feeling uncertain about the routes for children. For example, I have an 'About' route with 'me' as a sub-route: { path: '/about', name: 'About', component: About, children: [ { ...

Nuxt failing to generate dist folder

Using docker-compose, I am building and running an SSR Nuxt.JS application with the web server being nginx. The issue arises when attempting to use nginx reverse proxy because the directory dist is not created in /app/. Below is my Dockerfile: FROM node:1 ...

Troubleshooting a Laravel 5.2 modal popup issue for password recovery, experiencing a 500 internal server error with the Ajax function execution

Is there a way to check if an email exists in order to send a reset password link using an AJAX function? I keep encountering a 500 internal server error before the AJAX runs. I understand that a 500 error is usually due to a token mismatch, but do I actua ...

Is it possible to determine if jQuery find returns true or false?

Snippet of HTML Code <div class="container1"> <div class="box1">Box 1</div> <div class="box2">Box 2</div> <div class="box3">Box 3</div> </div> <div clas ...

Searching for specific values within data attributes using jQuery wildcards

I am currently utilizing the data_attribute on this page and have the following elements with data attributes. No. 1.<div class="row hidden" data-party-registration-source-type-id="1"> 2.<div class="row hidden" data-party-registration-source- ...

Guide to attaching and displaying an image on a Three.js map

Currently, I have a 3D map loaded with three.js that includes mouse interaction. I've managed to place an image on the map using absolute positioning, but unfortunately, as I move the map around, the image stays stationary. Does anyone know how I can ...

Is there a way to incorporate the ACE code editor into a Vue project without relying on its built-in Vue

Just starting out with Vue and I'm looking to incorporate the ace code editor (this package) into my project. However, I want to avoid using the vue2-component & vue3-component versions for learning purposes. How can I achieve this? What's t ...

Attempting to utilize a for loop in JavaScript to condense code, however encountering a "not defined" error

I'm relatively new to working with javascript and currently attempting to enhance the following code snippet (which has been tested and is functioning correctly): // snail 1 // var s1 = document.createElement("div"); s1.id = snail1.id; s1.className = ...

Having difficulty choosing an element with protractor's virtual repeat functionality

Initially, I successfully used ng-repeat to select an element. However, the developers have since implemented virtual repeat which has caused the following code to stop working: expect(stores.listStores(0).getText()).toContain('Prahran'); expect ...

Implement a dynamic table in real-time with jQuery AJAX by fetching data from JSON or HTML files

Hey @SOF, I'm trying to add an auto-update feature to my school grades webpage using jquery and ajax to refresh the data when new information is available. I also want to create a "single view" for classes. The challenge I'm facing is getting t ...

How can VueX be leveraged to add an item to an array and also delete an item from the same array?

https://stackblitz.com/edit/vue-script-setup-with-vuex-gfjaff?file=src/components/UserProfile.vue I'm currently working on a feature where I can input a name into a dispatch function and have it added to an array. Eventually, I plan to include a text ...

AngularJS Treeview - Rearranging tree nodes

My journey with Angular is just beginning, and I managed to create a treeview following this example: jsfiddle.net/eu81273/8LWUc/18/ The data structure I've adopted looks like this: treeview1 = [ { roleName: "User ...

How come I am receiving a null value for isMatch from bcrypt compare even though the two password strings match exactly?

Currently, I am attempting to authenticate a user based on a password. My approach involves using bcrypt compare to check if the user's requested password matches one stored in a MongoDB database. Despite the passwords being identical, I keep receivin ...

In JavaScript, not all elements are removed in a single iteration, even if the condition is consistently met

I'm currently attempting to compare two arrays containing multiple objects and remove elements based on a condition. To my surprise, while testing in Chrome's console, I noticed that the first array (arr1) is not being emptied even though I am us ...