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

3

8

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?

Goethe answered 3/8, 2018 at 10:49 Comment(3)
import './node_modules/mapbox-gl/dist/mapbox-gl.js'; should work, it will make the variable global tough...Udell
maybe import * as mapboxgl from ...?Bernstein
Both import 'module.js' and import * as mapboxgl from 'module.js' seem to do something more. However, the import now produces an Uncaught TypeError Cannot set property 'mapboxgl' of undefined. This seems to occur inside the library with expression window.mapboxgl = ... . The global window object is not available in E6-module scope, so I should probably give up and wait for the mapbox-gl library to support ES6-modules? See also #32961755Goethe
F
1

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)
})
Focus answered 21/9, 2018 at 4:19 Comment(0)
R
0

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

import mapboxgl from 'mapboxgl'
Rushy answered 28/9, 2019 at 13:49 Comment(0)
F
0

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
})
Frogman answered 7/4, 2021 at 10:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.