Search code examples
javascripthtmlwebpackwebpack-2

How to do a synchronous require of Webpack build module, from *outside* of Webpack build


Say I have an HTML file like so:

<!DOCTYPE html>          
 <meta charset="UTF-8">
 <title>Suman tests</title>
 <head>
 <script src="../dist/suman.js"></script>   <-- webpack build here

    // how can I do a synchronous require() here, from something
    // inside the Webpack build?

 </script>
</head>
<body>
</body>
</html>

as the comment says in the script tag, I am trying to figure out: how I can import/require something from inside the Webpack build from just about any old JavaScript code?

Is it possible? How? ...I could set global variables in the build, but I am wondering if there is another better way.

Note:

I would be willing to use Browserify instead of Webpack to create the bundle/build, if that makes it easier to require modules from the build, from outside of the build.

I tried doing this with RequireJS and SystemJS - these two tools would make it much easier to do what I want to do. But apparently it's pretty hard to create deep builds from NPM packages with RequireJS or SystemJS, and in this case I need a deep build that includes many NPM deps. I even tried TypeScript transpiler to create a deep build, to no avail. So it seems like it's gotta be either Browserify or Webpack, but I am open to anything that might work.

Note that if we used AMD or SystemJS, this would be straightforward:

<head>
  <script src="../dist/suman-amd.js"></script>   <--AMD build here
  <script src="../dist/suman-system.js"></script>   <--SystemJS build here
  <script>

       // using AMD

        define(['/a-module-from-amd-build'], function(myMod){

            // my unique code goes here

        });

        // or with SystemJS 

       System.register('my-module', ['a-module-from-system-build'], function(myMod){

             // my unique code goes here

       });

  </script>
</head>

But using Webpack/Browserify makes it a little trickier to do what I want to do.


Solution

  • I think I have an answer to this question, pretty clever actually. The solution uses Webpack.

    Before building with Webpack, inside our backend code, we would do this:

    global.require = name => {        // global is window
     switch (name) { 
        case 'async': 
        return require('async');
        case 'bluebird': 
        return require('bluebird') 
        case 'socket.io': 
        return require('socket.io') 
         // etc etc
      } 
    }
    

    we need to use the full/actual paths, not dynamic paths, so that Webpack can do its thing.

    Webpack will include this code as part of the build and mangle the F out of it. But it won't matter because outside the bundle, we will have a way to require Webpack modules.

    <script src="../dist/suman.js"></script>   <-- webpack build here
    <script>
    
         // this will pull async from inside the Webpack build
         const async = window.require('async'); 
         const socketio = window.require('socket.io'); 
         const Promise = window.require('bluebird');  
    
    </script>
    

    This was actually pretty clever and I did not think of it :)