4

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.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • You cannot just reference a TS file. You have to compile TS to JS, then rederence that. – Jonas Wilms Mar 01 '20 at 11:51
  • @JonasWilms I´m aware of that. The JS-file already was compiled. It contains this line: `import * as L from 'leaflet';`. which seems what my browser is complaining about – MakePeaceGreatAgain Mar 01 '20 at 11:53

1 Answers1

2

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.

Lea Rosema
  • 1,100
  • 16
  • 31
  • 1
    And do I really need **two** such files? The one that defines the `Library` and the other one that uses is? Can´t I use it directly in my HTML? – MakePeaceGreatAgain Mar 01 '20 at 12:12
  • @HimBromBeere https://stackoverflow.com/questions/57492546/what-is-the-difference-between-js-and-mjs-files – tevemadar Mar 01 '20 at 12:13
  • @HimBromBeere the Library file was just an example for the library to be used in the project. – Lea Rosema Mar 01 '20 at 12:16
  • I don´t have NodeJS. It´s a pure client-application. – MakePeaceGreatAgain Mar 01 '20 at 12:16
  • I also tend to use the `.mjs` extension on the browser side when I work with ESM modules. It's my personal preference to also use this convention on the browser side to distinct module type js from js. – Lea Rosema Mar 01 '20 at 12:21
  • 1
    Can´t I call my function directly within my HTML? So define the dependecy within my head-tag and call one of its function within the body? – MakePeaceGreatAgain Mar 01 '20 at 13:26
  • @HimBromBeere for calling it directly from within your html, you need to specify the tslint.config target to `ES5`. Export your function from within the TypeScript file, eg via default export: `export default function myFunction() {}` – Lea Rosema Mar 01 '20 at 13:37