1

I have a simple Typescript web app with Webpack and I am trying to include a plain javascript library that doesn't export any modules/functions. The instructions require you to add a Script tag and this adds objects and functions into Globals which can be used throughout the application. Rather than doing this I would like to use webpack to bundle it up in the final javascript bundle and also make it's exposed objects and functions available in globals (so it can be used in the same way intended).

So far the only way I can get webpack to include the javascript in the bundle is by adding the following into my index.ts:

require("./lib/exolve-m")

Whilst this packages the javascript, it's wrapping it (as it should) in a function which exposes the exports. However this package doesn't use the export keyword and also they aren't loaded into the global namespace. So I'm left with bundled code that I can't access.

What's the right way to do this please?

sarin
  • 5,227
  • 3
  • 34
  • 63

1 Answers1

1

TL;DR: This library is not compatible with js/ts module systems. You will have to modify it.


It claims the following:

 * The Exolve code creates only the following names at global scope:
 *
 * - Exolve
 * - createExolve
 * - createPuzzle (deprecated).
 * - exolvePuzzles

But the way it does this is is to declare variables at the root file scope. When a web browser directly includes this file via <script> tag, this technique creates global variables.

// Run this in your browser console:
var foo = 123
console.log(window.foo) // returns: 123

This is typically considered a bad practice, and before bundlers like Webpack it was common practice to wrap your code in a function to prevent this behavior and avoid polluting the global scope.

(function() {
  var bar = 123;
  console.log(window.bar); // returns undefined
})()

But, sadly, this is the behaviour that the exolve library depends on this method of creating globals to work.


However, this all changes when you use a bundler. Bundlers wrap all imported files in functions that can be called to get the contents of that file. This completely breaks this method of creating globals because the var statements are no longer at the global scope.

So when you import this as a module, it creates a bunch of local variables internal to that module, exports nothing, and leave the global scope unmodified. So there is no way at all to access the code in the library.

This means this library is not compatible with being imported as a module.


I think your best bet is to modify the library. Simply add an export to the declarations you want to use. For example, replace:

function Exolve(puzzleText,
                containerId="",
                customizer=null,
                addStateToUrl=true,
                visTop=0,
                maxDim=0)

with

export function Exolve(puzzleText,
                containerId="",
                customizer=null,
                addStateToUrl=true,
                visTop=0,
                maxDim=0)

And now you import items like any other module:

import { Exolve } from "./exolve-m";

Working example here

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • I thought as much. I didn't really want to edit their package. Perhaps I will get webpack to bundle and output the file and I will reference it straight in a script tag – sarin Nov 25 '20 at 19:57