reference function from TypeScript in HTML

Viewed 919

Seems like my web-days are too long away. When I started programming we referenced a script using a <script>-tag:

<html>
<head>
  <script src="lealet.js"></script> <!-- I know the path isn´t correct, I just reference leaflet -->
  <script src="myscript.js"></script>
</head>
<body><script>myFunction()</script></body>
</html>

where myScript is this:

function myFunction() { var map = new L.Map(...); }

which just creates a leaflet-map. Now I wanted to migrate this to some statically-typed TypScript. Instead of referencing leaflet from within my HTML-file, I used this in mScript.ts:

import * as L from 'leafet';
function myFunction() { var map = L.Map(...); }

I compiled that to JS. However when running my site in the browser using the HTML from above I get this:

Uncaught SyntaxError: Cannot use import statement outside a module

I´m targeting ES6 with modulekind ES6.

1 Answers

You can either try to use your compiled JavaScript as a native ESM module, or use a module bundling solution.

Modern browsers support JavaScript imports out of the box, if you specify type="module" on the script tag.

// main.mjs
import * as L from 'https://unpkg.com/browse/leaflet@1.6.0/dist/leaflet-src.esm.js';

function myFunction() {
  const map = new L.Map(...);
}

// if you need to access myFunction from an inline script tag, export it to window :
window.myFunction = myFunction;
// index.html
<script type="module" src="main.mjs"></script>

To get this working, you should specify a target newer than ES5 in your tsconfig.json. ES6 should work. Use something newer like ES2020 if you need more recent JavaScript features.

Something to keep in mind with this approach is that ancient browsers like IE11 will not load any module type JavaScript at all. Also, the library you want to use needs to use the ESM module syntax, importing CommonJS style libraries don't work out of the box without any module bundling solution. In my example, I used the .esm.js version of Leaflet. Also, the esm.js of leaflet currently has no default import, so you have to use the * as syntax.

Another option is to use a module bundler that transpiles your code plus your used libraries into a single bundle.js file. Popular bundlers are

If the above options don't work for your project, a third approach is to remove the library import from your main TypeScript file, load the library via a separate <script src="leaflet.js"></script> and then use the globally exported window.L object.

Related