Include packages from bower

What is the best way to include a bower package into my kotlin js project?

So far I’m only including external js libs that are distributed as single js files and this works fine. However, now I want to integrate the zib library pako. Pako is only available on bower and I can’t figure out how to integrate it into my project. I tried to simply use the pako.js that I downloaded with bower but this does not work. Is there a way to extract a bower package into a single file?

Update: I managed to load the pako.js from bower into a dummy html project using RequireJS. However, when I try to include the require.js file in my kotlin test I get the error:
Error: Mismatched anonymous define() module: function (_, Kotlin)
I think this is because kotlin interferes with require js. Any idea how to use require.js in a kotlin test (Karma/Mocha)?

Pako is only available on bower

Is this a different thing?

Error: Mismatched anonymous define() module: function (_, Kotlin)

Looks like this. Most likely this is due to the fact that we use anonymous AMD module definitions for portability reasons. That gives developers more flexibility, but it also requires some more configuration. Please refer to Kotlin AMD tutorial and require.js configuration options

Kotlin/JS should work with require.js just fine. That being said testing AMD modules is notoriously tricky, especially if you are trying to mix AMD and CommonJS together.

Thanks that helped. Now, I’m loading all modules and tests using requirejs. The only remaining problem is that karma does not wait for any tests / it is not aware that the tests are loaded asynchronously. This is only a problem when running karmaRun gradle task. When I debug my test in the browser I can see from the console output that the tests are executing. Is there a way to tell karma that the tests are loaded async and that it should wait for those tests?

Here is some pseudo code from my build.gradle file in case somebody has the same problem:

karma {
    dependencies(['mocha', 'karma-requirejs'])
    frameworks = ['mocha', 'requirejs']
    browsers = ['Firefox']

    files = [       
            // include require js
            "path/to/require/require.js",
            // load the tests:
            "test_main.js",

            // serve files but do not load them (they are loaded in main.js using requirejs)
            [pattern: "../path/to/pako.min.js", included: false],
            [pattern: "$libDir/*.js", included: false],
            [pattern: compileOutput, included: false],
            [pattern: testOutput, included: false],

            [pattern: "${projectDir}/build/classes/main/myLibJS.js.map", included: false],
            [pattern: "${projectDir}/build/classes/test/myLibJS_test.js.map", included: false],
    ]
}

and the test_main.js

requirejs.config({
    // path where all main libs are located, e.g. kotlin.js
    // "base" is the karma root directory as the browser sees it (also look at
    // the debug.html file in the browser debugger to see all served files)
    baseUrl: '/base/myLibJS/build/lib',

    paths: { // paths are relative to test_main.js
        'pako': '../relative/path/pako.min',
        'myLibJS': '../relative/path/build/classes/main/myLibJS',
        'myLibJS_test': '../relative/path/build/classes/test/myLibJS_test',
    },

    deps: ['pako', 'myLibJS_test'],

    // start tests when done
    callback: window.__karma__.start
});

I’ve just found Karma docs on how to use it with require.js

Your solution looks pretty close to what they are suggesting, except for a few details. Could you try:

  • moving "main.js" to the last position in files array
  • adding a 'requirejs' framework adapter (doesn’t look like it’s doing anything vital though)

and see if any of it helps. If not I’ll try reproducing.

My hunch is that you are telling Karma to load the main.js before any of the test files, and that causes problems.

Thanks again! Just including requirejs as a dependency and as a framework does the trick. I updated my previous post and added the changes there.

Congrats on making that work! =)

To support offline mode I tried to embed JS code right inside script tag but this didn’t work because Kotlin JS generates anonymous modules and require.js blows up in this case (Common Errors)

To make it work I had to patch all generated JS by adding module ID to define()

Is where an option to generate named modules?

p.s. “portability reasons” link doesn’t seem to work.

p.s. “portability reasons” link doesn’t seem to work.

Thanks, fixed.

Is where an option to generate named modules?

No, there is not. Let me explain.

To make it work I had to patch all generated JS by adding module ID to define()

That’s not how the documentation advises to develop AMD modules. Quote:

You should avoid naming modules yourself, and only place one module in a file while developing. However, for tooling and performance, a module solution needs a way to identify modules in built resources.

For your particular use case the common errors section you’ve linked contains the following suggestion:

If the problem is the use of loader plugins or anonymous modules but the RequireJS optimizer is not used for file bundling, use the RequireJS optimizer.

All in all it seems the solution to your use case is to use RequireJS optimizer to bundle the AMD modules together. The optimizer generates the module ID’s by itself when it packs modules into a single .js bundle, so your issues should go away. It can also integrate with minifiers, such as UglifyJs, and do other cool stuff, so it is worth checking it out anyway.

1 Like

Thanx! I’ll check it out.