leveraging parcel for importing typescript dependencies

I am currently using parcel to process typescript for a web extension. I have installed JQuery and its type definitions via npm. In my typescript file, I have the following at the top:

import $ from "jquery";
import "bootstrap";

However, when running runtime, Chrome gives an error that jquery is not defined. You can find a minimal example to reproduce this problem on git: https://github.com/lhk/parcel_jquery_bug_demo

git clone https://github.com/lhk/parcel_jquery_bug_demo
cd parcel_jquery_bug_demo
npm install
parcel build src/manifest.json

You can then open chrome and load the dist folder.

The github repository includes:

src/manifest.json

{
  "manifest_version": 2,
  "name": "pc",
  "version": "0.0.1",
  "description": "none",
  "author": "",
  "content_security_policy":"script-src 'self'; object-src 'self'",
  "content_scripts": [
    {
        "matches": ["<all_urls>"],
        "js": [
         "./content/index.ts"]
    }
  ]
}

src/content/index.ts

import $ from "jquery";
import "bootstrap";

$(function () {
  $('[data-toggle="popover"]').popover();
});

./package.json

{
  "name": "pc",
  "version": "0.1.0",
  "description": "",
  "author": "",
  "license": "",
  "devDependencies": {
    "parcel-plugin-web-extension": "^1.4.0",
    "typescript": "^3.1.3"
  },
  "dependencies": {
    "@types/bootstrap": "^3.3.7",
    "@types/jquery": "^3.3.10",
    "bootstrap": "^3.3.7",
    "jquery": "^3.3.1"
  }
}

Once you've loaded the extension in chrome, you can visit any website. The error message will be:

Uncaught ReferenceError: jQuery is not defined

I am using:

  • Parcel 1.10.1
  • Node v8.12.0
  • npm 6.4.1
  • ubuntu 18.04.1 64bit
  • chrome 70

I believe the issue lies in the import of bootstrap. The code below functions properly:

import $ from "jquery";

//import "bootstrap";

$(function () {
  //$('[data-toggle="popover"]').popover();
  $('[data-toggle="popover"]').click(function(){});
});

It seems that while parcel handles the dependencies for my typescript code, bootstrap requires jQuery separately, which is causing the error.

Answer №1

When dealing with the issue, Parcel actually plays no role in it. The main issue lies in jQuery/Bootstrap relying on the $ and jQuery functions being exposed in the global scope.

To address this, you can easily achieve it by following these steps (for JS only, as TypeScript will raise concerns about the window not having the $ and jQuery properties):

import jquery from "jquery";
window.$ = window.jQuery = jquery;
import "bootstrap";

However, if using TypeScript, additional steps are required to enable linting and intellisense support.

  1. Install the TypeScript definition files using
    npm install --save-dev @types/jquery @types/bootstrap
  2. Use import * as $ from 'jquery'; for importing.
  3. Configure the libs for the DOM api since they are not enabled by default in TypeScript. This will allow you to use window and document properly, but you need to change window to (<any> window)

    tsconfig.json

    {
      "compilerOptions": {
        //...
        "lib": ["dom"],
        //...
      },
    }  
    

Answer №2

I utilized a babel plugin called babel-plugin-auto-import by adding the following configuration to my .babelrc file:

  {
    "plugins": [[
      "auto-import", {
        "declarations": [
          { "anonymous": ["jQuery"], "path": "jquery" }
        ]
      }
    ]]
  }

So far, everything appears to be functioning as expected.

Here is the updated package.json with the relevant dependencies:

{
  "name": "pc",
  "version": "0.1.0",
  "description": "",
  "author": "",
  "license": "",
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-plugin-auto-import": "^0.9.3",
    "parcel-plugin-web-extension": "^1.4.0",
    "typescript": "^3.1.3"
  },
  "dependencies": {
    "@types/bootstrap": "^3.3.7",
    "@types/jquery": "^3.3.10",
    "bootstrap": "^3.3.7",
    "jquery": "^3.3.1"
  }
}

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

Tips on generating an HTML element using JavaScript and storing it in a MySQL database

I need help with saving a created element to the database so that it remains on the page even after refreshing. Any assistance would be greatly appreciated. Thank you. document.getElementById("insert").onclick = function(){ if(document.getElementById( ...

Advancing through time with progress

How can I display a progress indicator for events in fullcalendar based on the current time by changing their color dynamically in HTML? Thank you for your help! ...

Steps to create a thumbnail image following the insertion of an image into an input type="file" within a form, and subsequently submitting both elements on the form together

Currently, I am working on a form that enables users to upload images. Once the user submits the form, my goal is to create thumbnails for each image on the front-end and save them on the server afterwards. Due to security restrictions, changing the value ...

Enhance jQuery with additional features using Bootstrap

My website utilizes Bootstrap 4, which comes with the slim version of jQuery that does not include effects. I attempted to add the normal version of jQuery alongside the slim version in order to access the effects, but it was unsuccessful. I even tried r ...

Is there a way to create an X shape by rotating two divs when I click on the container div?

I currently have this setup: code Below is the HTML code: <div id="box"> <div id="line1" class="line"></div> <div id="line2" class="line"></div> <div id="line3" class="line"></div> </div> My go ...

What is the reason that setTimeout does not delay calling a function?

I am looking to develop a straightforward game where a div is duplicated recursively after a short interval. Each new div should have a unique ID (ID+i). The concept is to continuously generate divs that the user must click on to remove before reaching a ...

Difficulty in implementing Handlebars handler for dropdown onchange event

Currently, I am implementing Express alongside Handlebars for the front-end of my project. My aim is to trigger an event and read the value of the selected option in the dropdown within 'home.handlebars' when it changes, through 'index.js&ap ...

Encountering difficulties in accessing state while utilizing async callback functions in React.js

After finding this function on Stack Overflow, I decided to use it in order to update a database and profile information immediately after a user signs up. The function is working as expected, but I am encountering an issue where I can no longer access the ...

The issue of asynchronous behavior causing malfunctioning of the PayPal button

import { PayPalButton } from 'react-paypal-button-v2' <PayPalButton amount={total} onSuccess={tranSuccess} /> const tranSuccess = async(payment) => { c ...

Issue with Chart JS: Firefox is reporting that the 'Chart' is not defined

As a newcomer to Chart JS, I am currently utilizing it in Angular JS version 1.5.3 with Chart JS version 2.1.4. Below is the code snippet I am working with: var myChart = new Chart(ctx, { type: 'line', data: { labels: dates, datasets: [{ ...

Typescript - Iterating through CSV columns with precision

I am currently facing a challenge in TypeScript where I need to read a CSV file column by column. Here is an example of the CSV data: Prefix,Suffix Mr,Jr Mrs,Sr After researching on various Stack Overflow questions and reading through TypeScript document ...

From jQuery to HTML to PHP, then back to HTML from PHP through jQuery

Hey, I have a code snippet that I'm working on: <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script> <script type="text/javascript"> function get() { $.post(' ...

Ways to retrieve a value from the column within the editor's template of a Kendo.Grid when it loses focus or onblur()?

I'm working with a grid that has an editor template in my HTML setup. Whenever I click on a column, it switches to edit mode, enabling me to modify the value in the textbox. My specific query is, how can I retrieve the value of $50.00 using jQuery up ...

Assigning objects in Vue.js methods

I am working on a Vue component where I need to select a specific value from an array of objects and then copy certain fields from that value into Vue data. <div class="container"> <h4>Add Item</h4> <form @submit.prevent="ad ...

What causes tests to fail with an error message SyntaxError: Unexpected token {?

Hey there! I'm encountering an issue with webpack 5 and babel while trying to run tests that were previously written. Despite following the jest documentation for configuration, I haven't been able to find a solution after exploring various forum ...

Testing Async operations in the browser with Mocha and Chai

I'm having trouble running async tests with mocha. Below is the snippet of my code: describe('Brightcove Wrapper',function(){ describe("#init()", function() { it("Should inject the brightcove javascript", function(callback){ ...

Run JavaScript code to retrieve the console log using Selenium WebDriver or WatiN

(Apologies for the detailed explanation) I am looking to ensure a page loads entirely before proceeding, but it seems browsers have varied responses when attempting to use readyState or onLoad. In the application I am currently developing, a specific l ...

Creating interactive popups using Web Map Service (WMS) with the

I am looking for a way to make a leaflet map loaded from a geoserver interactive by displaying popups with information. Can someone provide a solution using jsfiddle to help me understand? I am struggling to figure out how to achieve this. Essentially, I w ...

The element is inferred to have an 'any' type due to the fact that a 'string' type expression cannot be used to access elements in the type '{ Categories: Element; Admin: Element; }'

As someone who is new to TypeScript, I am trying to understand why I am encountering a type error in the code below (simplified): "use client"; import { ArrowDownWideNarrow, Settings } from "lucide-react"; interface LinkItemProps { ...

What could be the reason for receiving an undefined value when trying to determine the size of the Set

Within one of my functions, I am encountering the following code: this.personService.getPersonInfo(this.personId).subscribe((res => { let response = res.body; let num = response.personList.size; ... })) Here is what the expe ...