In my web applications, I have many JS files that I include in the HTML body. They define many symbols that I can use directly in <script>
elements. Now, I need to use these applications inside a quite old web engine (the traditional MS WebView, which in practice means IE11), but my JS uses a lot of (relatively) new syntax (mainly arrow functions () =>
). I managed to configure Webpack and Babel to translate the code, but I lose visibility of symbols unless I explicitly add the export
keyword or assign them to corresponding members of the global window
object. Although it's a simple (and, I hope, harmless) code change, I would like to avoid it. Is there a way to instruct Webpack/Babel to preserve symbol visibility as it happens with plain JS scripts in HTML?
In short, not really.
I'll save you the "global variables are a bad idea" spiel and get straight to the technical aspects.
In order to define a globarl variable, you need to define it at the module level (among other requirements which I'm skipping).
However, in order to work, Webpack wraps every module in a big ol' function, which means that any declared variables are defined within a function scope, not the global scope.
For the vast majority of engineers, this behavior of Webpack is not just a side effect... it's a major reason to use a bundler in the first place.
As you've already noted, the way to sidestep this feature is to add properties to the window
object, e.g. window.myGlobal =
.
Now, there is actually one exception to all of this. If a module is defining a library which is intended to be "exported" as a global variable (for example, jQuery), you can use output: { library: "variableName" }
.
So, taking the example straight from the linked docs:
webpack.config.js
module.exports = {
// …
entry: './src/index.js',
output: {
library: 'MyLibrary',
},
};
src/index.js
export function hello(name) {
console.log(`hello ${name}`);
}
index.html
<script src="https://example.org/path/to/my-library.js"></script>
<script>
MyLibrary.hello('webpack');
</script>
If you have multiple modules like this, then you can return an array in your webpack.config.js
:
module.exports = [{
// …
entry: './src/lib/oneLib.js',
output: {
library: '$OneLib',
},
},{
// …
entry: './src/lib/twoLib.js',
output: {
library: '$TwoLib',
},
}];
index.html
<script src="https://example.org/path/to/oneLib.js"></script>
<script src="https://example.org/path/to/twoLib.js"></script>
<script>
$OneLib.foo();
$TwoLib.bar();
</script>
If you take this approach, then you'd probably want to avoid directly importing these libraries in your other modules, as this would cause code duplication. Just use them as globals (again, like jQuery).