Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using non-npm(legacy) javascript library with Jspm

I'm trying to integrate this library which is non-npm. I failed many times already as I always thrive for using some modern framework which makes it impossible for me to integrate.

I tried backbone.js with require.js, even Dart and now I'm stubbornly trying to achieve the same using gulp, jspm, aurelia. The problem is that this library probably doesn't follow the module concept. I had lot of problems with initialization of this lib, made a lot of shimming.

So the question is how can I use such kind of libraries. Using in the same time modern ways to build javascript applications.

like image 462
Zveratko Avatar asked Mar 09 '16 10:03

Zveratko


2 Answers

For older libraries that don't follow modern module patterns the approach is usually to shim them.

  • If you're using webpack, you can shim modules by declaring imports and exports.

  • RequireJS has a similar shim config, but needs more wiring to declare dependencies. I'd strongly recommend webpack over Grunt/gulp/RequireJS.

However, looking at the mapy.cz library you linked, it dynamically loads many other assets by writing script tags to the page. I can see how that's hard to work with.

I think your options are really:

  • If the licence is a friendly open-source one, fork it and expose it in a more modern module format that can be easily imported via npm. Check out the UMD style - you can write a declaration that'll export the module in a format usable by most module systems (AMD, CommonJS, etc). The webpack library and externals page has some guidelines for writing modules in a format that others can use.

  • If it's not an open-source licence, you could get in touch with the author(s) to ask them to change how the library is bundled and loaded. It should be an easy sell: an npm module would allow more people to use their code, and would be easier to work with - especially if they started versioning it. You could offer to do it for them, or just do it as an example they can copy from.

They have a page detailing terms and conditions, as well as a 'contact us' button - I'd start there: http://napoveda.seznam.cz/cz/mapy/mapy-licencni-podminky/licencni-podminky-mapovych-podkladu/

like image 166
Alex T Avatar answered Sep 28 '22 12:09

Alex T


After looking at the code, I got it working (I used require.js, but you can use whatever you like):

// main.js
////////////////
require(['mapy-loader'], function (Loader) {
    // load mapy async and wait for it to finish
    Loader.async = true;
    Loader.load(null, null, function () {
        var stred = SMap.Coords.fromWGS84(14.41, 50.08);
        var mapa = new SMap(JAK.gel("mapa"), stred, 10);
        mapa.addDefaultLayer(SMap.DEF_BASE).enable();
        mapa.addDefaultControls();
    });
});
<!doctype html>
<html>
<head>
    <script data-main="main.js" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"></script>
    <script>
        requirejs.config({
            paths: {
                "mapy-loader": "//api.mapy.cz/loader"
            },
            shim: {
                'mapy-loader': {exports: 'Loader'}
            }
        });
    </script>
</head>

<body>
<div id="mapa" style="width:600px; height:400px;"></div>
</body>
</html>

(It won't run in the snippet here, since the JavaScript should be placed in a file named main.js)


EDIT:

Adding jspm / System.js snippet:
(main.js is unchanged)

// main.js
////////////////
define(['mapy-loader'], function (Loader) {
    // load it async and wait for it to finish!
    Loader.async = true;
    Loader.load(null, null, function () {
        var stred = SMap.Coords.fromWGS84(14.41, 50.08);
        var mapa = new SMap(JAK.gel("mapa"), stred, 10);
        mapa.addDefaultLayer(SMap.DEF_BASE).enable();
        mapa.addDefaultControls();
    });
});
<!doctype html>
<html>
<head>
    <script src="jspm_packages/system.js"></script>
    <script>
        System.config({
            baseURL: "/",
            defaultJSExtensions: true,
            transpiler: "babel",
            paths: {
                "mapy-loader": "//api.mapy.cz/loader"
            },
            meta: {
                'mapy-loader': {
                    format: 'global',
                    exports: 'Loader'
                }
            }
        });
    </script>
    <script>
        System.import('main.js');
    </script>
    Run
</head>

<body>
<div id="mapa" style="width:600px; height:400px;"></div>
</body>
</html>
like image 39
Yoav Aharoni Avatar answered Sep 28 '22 13:09

Yoav Aharoni