Search code examples
javascriptwebpackbundlefrontend

Expose javascript globals bundled via webpack


The Problem

I feel like this should be more straightforward than it is. I need to access all my javascript libraries from the frontend and because I'm integrating it into an old system, I cannot call require("bundle.js"); from the frontend. Everything in the global scope of the bundled files must be accessible from the global scope of the frontend page importing them through the <script> tag.

So I need to change the old:

<script src="js/jquery.js"></script>
<script src="js/silly.js"></script>
<script>
    $(silly()); // Some function in silly.js's global scope
</script>

To the new:

<script src="js/bundle.js"></script>
<script>
    $(silly()); // Some function in silly.js's global scope
</script>

Things I've tried

  1. expose-loader: This would totally work if I didn't have 100 global variables that I don't want to explicitly tell it to look for.

  2. ProvidePlugin: Only really lets the libraries see the other libraries. I also cannot explicitly write all the globals I need with my current setup (More are added constantly).

What I need

So for more clarity, I need my webpack.config.js to look like one of these options:

// Everything is wrapped in module.exports and other irrelevant things
plugins: [
         new StaticLibraryMergerSuperNeatPlugin("js/*.js")
]
// ...

Or:

rules: [
        {
            test: /\.js$/,
            use: [
                "neat-merging-cool-loader",
                "babel-loader"]
            
        }
]
// ...

Am I going about this wrong?

Is there an obvious solution I am missing?

Tl;Dr: How do I make globals from my bundled js files, be exposed to the global scope when imported on a frontend html page via <script src="js/bundle.js"></script>?

Btw: If anyone is a webpack legend and knows why this is a bad approach, please post below with a brief explanation so I can fix my life.


Solution

  • Note: This is not the ideal scenario but because I have a constant amount of new globals being added, I needed to make a plugin to bundle my javascript for me.

    webpack-raw-bundler

    This simply stacks your code together to be included on the frontend. Here is my usage example:

    Usage

    From the old:

    <script src="js/jquery.js"></script>
    <script src="js/silly.js"></script>
    <script>
        $(silly()); // Some function in silly.js's global scope
    </script>
    

    To the new:

    <script src="js/bundle.js"></script>
    <script>
        $(silly()); // Some function in silly.js's global scope
    </script>
    

    Installing to the config

      var RawBundlerPlugin = require('webpack-raw-bundler');
    
      module.exports = {
        plugins: [
           new RawBundlerPlugin({
                 excludedFilenames: [/angulartics/],
                 readEncoding: "utf-8",
                 includeFilePathComments: false,
                 bundles: [ "vendor.js", "styles.css" ],
                 "vendor.js": [
                    'js/*.js'
                 ],
                 "styles.css": [
                    'css/bootstrap.css',
                    'css/edits.css'
                 ]
           })
        ]
     }
    

    A Fair Warning:

    This should not be your go-to solution, but I had a bad case that made this the easiest option. Using expose-loader and import or window['module'] = require('module.js') is much safer as that is what webpack was built around. However, if you are having some headaches and just want a simple bundler, feel free to use this plugin.