There are a total of 3 options available to achieve this:
- You can opt for the traditional jQuery style CDN import where the entire library is made accessible through a global object.
- You can utilize the ESM mode for importing dependencies.
- 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+.