Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 501
anneb Avatar asked Aug 03 '18 10:08

anneb


People also ask

Can I use import in node?

Node js doesn't support ES6 import directly. If we try to use import for importing modules directly in node js it will throw out the error. For example, if we try to import express module by writing import express from 'express' node js will throw an error as follows: Node has experimental support for ES modules.

What is module type in Javascript?

A module is a function or group of similar functions. They are grouped together within a file and contain the code to execute a specific task when called into a larger application. You create modules to better organize and structure your codebase.


1 Answers

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)
})
like image 73
Akivamu Avatar answered Oct 05 '22 20:10

Akivamu