Is it possible to utilize the Lit javascript module from a CDN without including the bundled Lit dependencies?

Is there a method to distribute a Lit element created from TypeScript without including the Lit dependencies in the web component bundle?

For instance, we can serve the rollup bundle as mentioned here from Unpkg. However, I am curious if it's possible to load the Lit dependencies and the element separately via a CDN and still have everything function properly.

Instead of following the approach outlined in the provided example:

  "main": "fs-gist.bundle.js",
  "module": "fs-gist.js",
  "types": "fs-gist.d.ts",
  "type": "module",

We could try this instead:

  "main": "fs-gist.js",
  "module": "fs-gist.js",
  "types": "fs-gist.d.ts",
  "type": "module",

Then, when utilizing the element, we would first load the Lit dependencies somehow...

    <script
      type="module"
      src="https://unpkg.com/@lit/lit"></script>

    <script
      type="module"
      src="https://unpkg.com/@fireflysemantics/fs-gist"></script>

This approach would ensure that multiple elements loaded will all use the same version of Lit.

Answer №1

There are a total of 3 options available to achieve this:

  1. You can opt for the traditional jQuery style CDN import where the entire library is made accessible through a global object.
  2. You can utilize the ESM mode for importing dependencies.
  3. You can also make use of an ESM aware CDN like ESM.sh, as mentioned by Augustine in the comment.

In the first option, you would rely on bundlers like Webpack to exclude specific dependencies by specifying that a certain import should be treated as a global variable. This approach is commonly used in React, where 'React' and 'ReactDOM' are exposed as global variables. However, this method is not applicable to Lit since it provides only prebundled-ESM libraries, meaning there are no global variables.

The third option offers a ready-to-use solution but requires significant changes in how your application or library is delivered. This represents the future of loading applications in browsers. Nevertheless, with larger applications, using multiple external libraries could result in numerous network requests (each new import translates into a network request).

Here is where the second option becomes relevant. With this approach, some dependencies are bundled while others are loaded using ESM. This method assumes that you are utilizing a bundler or compiler.

To externalize a library, follow these steps:

  • Use the ESM version of the library (ensuring it does not contain further imports). Lit already provides a pre-bundled ESM module.
  • Utilize import maps for clean imports (and implement necessary hacks).
  • Configure TypeScript appropriately during development.
  • Select a bundler that generates ESM output.

For this illustration, Vite is being utilized.

Step 1: Create an ESM file (optionally including TypeScript):

// main.ts

import { LitElement } from 'https://lit';

console.log(LitElement);

The reason behind using https:// is that Vite automatically excludes such imports from the bundle. Choosing a different name would result in Vite bundling it. (Note: Vite currently lacks understanding of import-maps).

Step 2: Establish import map

In the HTML file serving as the entry point for your application, set up the import map:

<html lang="en">
  <head>
    <script type="importmap">
      {
        "imports": {
          "https://lit": "https://cdn.jsdelivr.net/gh/lit/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f094998384b0c3dec1dec4">[email protected]</a>/all/lit-all.min.js"
        }
      }
    </script>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./src/main2.js"></script>
  </body>
</html>

Whenever the browser encounters https://lit, it will fetch the required dependency from the specified CDN path. The file lit-all.min.js has been pre-bundled by the Lit team encompassing everything from lit-element, lit-html, to @lit/reactive-element. No additional imports are needed.

Step 3: Configure TypeScript

{
  "compilerOptions": {
    "baseUrl": ".",
    "module": "ESNext",
    "moduleResolution": "Bundler",

    "paths": {
      "https://lit": ["./node_modules/lit/index.d.ts"],
    }
  }
}

This configuration enables autocomplete/intellisense functionalities. To extend this to plain JS files as well, activate the checkJs flag.

Step 4: Generate ESM output

If using Vite, ensure that your target output is either modules or esnext. Standalone library bundling likely comes with predefined settings. A similar feature should be available in Webpack 5+.

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

SignalR Negotiate in AspNetCore 2.2 with Angular consistently triggers a 404 error indicating page not found

I am currently using: AspNetCore 2.2 Web Application Angular CLI: 8.3.3 Node: 10.16.0 OS: Windows 32-bit x64 Angular: 6.1.10 services.AddSignalR(); app.UseSignalR(config => { config.MapHub<NotificationHub>("/notify"); }); this.hubConnection.st ...

The term 'required' is not recognized as an identifier. There is no member by the name of '__type' in the definition

When working on my HTML template in the visual code editor, I encountered the need to declare a variable with type any? https://i.stack.imgur.com/Jq5az.png product-form.component.html <div class="row"> <div class="col-md-6"> <for ...

What is the method to adjust the anchor point for a MUI popover?

I currently have the following code for handling a popover: const [open, setOpen] = useState(false); const anchorRef = createRef() const handleClose = () => { setOpen(false); }; const handleClick = useCallback( (event: MouseEvent<H ...

When the mouse hovers over the slider, the final image jumps into view

After successfully building an image slider that displays 2 partial images and 1 full image on hover, I encountered a bug when setting the last image to its full width by default. This caused a temporary gap in the slider as the other images were hovered o ...

What is the best way to retrieve data from a fetch request within a GET function?

It seems like a simple issue, but I'm struggling to retrieve information from my "body" when utilizing the get method. I've experimented with various approaches to extract the data, but nothing seems to work. Any guidance would be greatly appreci ...

AngularJS and adding to an array in the routing process

I'm currently working on creating a contact list with two different views. One view displays all the contacts and includes an option to add a new contact, which is represented by a button rather than a space to input information directly. The other vi ...

Images and CSS are failing to load on Magento2

After downloading and installing Magento 2, I encountered a 404 error for scripts and css. A specific example of my image path is: I attempted to address this issue with the following solution: By opening up app/etc/di.xml and locating the virtualType ...

Tips for transferring a jQuery array to PHP

I am encountering an issue when trying to send a jQuery array to PHP. Initially, I have one form in HTML and upon clicking 'add', I end up with two forms. Afterwards, I input data into the form which is then stored in a jQuery array. However, I a ...

Incorporate functionality into a button using jQuery

I am working on a table that displays data in different levels (Parent, Child, Grandson). When I click on the parent row, it expands to show new rows related to the child level. Similarly, clicking on a child row reveals a third level known as the grandson ...

Verify if the nested arrays within the object consist of any empty elements

Take a look at the object below: { "params": { "time_to_diagnosis": [ { "field": "date_of_diagnosis", "value": "" }, { "field": "date_of_symptom_onset", "value": "2019-09-01" } ], "time ...

Utilizing NestJS: Integrating Mongoose Schema Custom Validation with Service Methods

Presently, I am managing two different modules: First Module: courses -courses.module.ts -courses.services.ts -courses.schema.ts -courses.controller.ts Second Module: groups -groups.module.ts -groups.services.ts -groups.schema.ts -groups.controller.ts ...

Strategies for Sorting Nested Arrays in JavaScript

Here is the JSON data I have: { "list": [ { "deviceId": "2a-d539-4031-9bfc-4a42f2f765cf", "versions": [ { "id": "764c20-a213-9235f4b553b3", "createdTime": 1590361208034, "files": [ { ...

Issue with Jquery - navigation menu scrolling

I'm struggling to understand why the second gallery isn't scrolling like the first one Check it out here: Here's the jQuery code that's responsible for making it work: $(function(){ var state = 0; var maxState = 7; var winWidth = $(&a ...

Error: The function "validate" is not recognized (jQuery validation)

Whenever I try to run the script, I encounter this error that prevents it from working properly. An error occured: Uncaught ReferenceError: validate is not defined I attempted to call the function onsubmit from the tag and even experimented with placi ...

Is it possible that VS Code can't recognize 'ngbNavItem' as a valid property of 'li'?

The current situation: Our Angular app is in production and utilizes various libraries such as ng-select, angular-fontawesome, ng2-charts, ngx-quill, ng-bootstrap, and others. Everything seems normal with these libraries except for ng-bootstrap, which alo ...

A guide on how to efficiently retrieve a string within a function in a native module in a React Native

I'm currently tackling a function related to the native elements of iOS that is coded in Objective-C, My goal is to create a method that will output a string in Objective-C, However, I've hit a roadblock while trying to implement this method: T ...

Ensuring the protection of API requests in a Phonegap/Cordova application

As I work on developing a Phonegap application that requests data from my server via API, I want to ensure that only authorized users are able to access this data. To achieve this, I have implemented HTTP basic authentication. This method involves includi ...

Modifying the attribute of an element inside an array

Presented below is an object: { "_id" : ObjectId("5a8d83d5d5048f1c9ae877a8"), "websites" : [ "", "", "" ], "keys" : [ { "_id" : ObjectId("5a8d83d5d5048f1c9ae877af"), "name ...

Utilizing Ionic with every Firebase observable

Can someone help me with looping through each object? I am trying to monitor changes in Firebase, and while it detects if there is a push from Firebase, I am facing issues displaying it in the HTML. Where am I going wrong? Thank you! ping-list.ts p ...

Unable to execute commitlint in husky along with a different custom command

Is it possible to set up two precommit hooks with husky? Specifically, I want to integrate commitlint along with a custom script specified in my package.json. After installing husky and creating a pre-commit script in the .husky folder, here is what I have ...