anneb
anneb

Reputation: 5768

How to import non-module(!) JavaScript into Polymer 3.0

Polymer 3 uses import to load external Javascript. For example

import {GoogleCharts} from 'google-charts';

However, it seems for this to work, the external library should use exports.

I am trying to use mapbox-gl.js library. This library, installed with:

npm install mapbox-gl

does not seem to export anything.

In HTML5, you can use mapbox-gl as follows:

<script src="node_modules/mapbox-gl/dist/mapbox-gl.js"></script>
<link href="node_modules/mapbox-gl/dist/mapbox-gl.css" rel="stylesheet" />
<script>
   const options = {...}
   const map = new mapboxgl.Map(options);
</script>

I tried to use 'import' to load mapbox-gl:

import {mapboxgl} from './node_modules/mapbox-gl/dist/mapbox-gl.js';
import mapboxgl from './node_modules/mapbox-gl/dist/mapbox-gl.js';

This doesn't work:

Uncaught SyntaxError: The requested module './node_modules/mapbox-gl/dist/mapbox-gl.js' does not provide an export named 'mapboxgl'
Uncaught SyntaxError: The requested module './node_modules/mapbox-gl/dist/mapbox-gl.js' does not provide an export named 'default'

So, then I tried to add the script and css to document.head from inside the module javascript (<script type="module">..</script>):

// load external mapbox-gl.js script
const mapboxgljs = document.createElement('script');
mapboxgljs.setAttribute('src', 'node_modules/mapbox-gl/dist/mapbox-gl.js');
document.head.appendChild(mapboxgljs);
// load external mapbox-gl.css 
const mapboxcss = document.createElement('link');
mapboxcss.setAttribute('href', 'node_modules/mapbox-gl/dist/mapbox-gl.css');
mapboxcss.setAttribute('rel', 'stylesheet');
document.head.appendChild(mapboxcss);

This does not seem to work either. If I try to use mapbox as follows:

const map = new mapboxgl.Map(options)

I am getting:

Uncaught ReferenceError: mapboxgl is not defined

Edit:

Commenters @Salketer and @barbsan showed correct import syntax for this kind of library:

import 'node_modules/mapbox-gl/dist/mapbox-gl.js';

or

import * as mapboxgl from 'node_modules/mapbox-gl/dist/mapbox-gl.js';

Both now result in the following error message:

Uncaught TypeError: Cannot set property 'mapboxgl' of undefined

This means the mapbox-gl library now gets loaded and interpreted. However, the mapbox-gl code contains the line:

window.mapboxgl = something;

ES6-module scope does not have access to the browser 'window' object, so the code fails. See also Is there an es6 module-scope equivalent to `window`?.

For now, I am adding the HTML5 <script></script> and <link /> tags (see above) to the index.html of my project. This works, but the idea of components and modules is to load dependencies from inside those components and modules?

Upvotes: 8

Views: 2326

Answers (3)

User Rebo
User Rebo

Reputation: 4660

Just do:

import("node_modules/mapbox-gl/dist/mapbox-gl");

// do my stuff with global dependency

or if import is slower than the code to be execute

import("node_modules/mapbox-gl/dist/mapbox-gl").then(() => {
    // do my stuff with global dependency
})

Upvotes: 0

Java wanna bee
Java wanna bee

Reputation: 3107

For me the solution was to define the import without mustasch {}:

import mapboxgl from 'mapboxgl'

Upvotes: 0

Akivamu
Akivamu

Reputation: 588

You are close.

With your original code to load script:

// load external mapbox-gl.js script
const mapboxgljs = document.createElement('script');
mapboxgljs.setAttribute('src', 'node_modules/mapbox-gl/dist/mapbox-gl.js');
document.head.appendChild(mapboxgljs);

At this moment, if you use the instance provided by the script: const map = new mapboxgl.Map(options)

You will get error: Uncaught ReferenceError: mapboxgl is not defined

Reason: the script isn't loaded yet, so the instance window.mapboxgl is undefined.

Solution: You have to wait until the script finished loading, using event listener. Add this code into your loading script code:

mapboxgljs.addEventListener('load', function() {
  // mapboxgl is available here, do whatever you want
  const map = new mapboxgl.Map(options)
})

Upvotes: 1

Related Questions