Alexander Mills
Alexander Mills

Reputation: 100010

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.

Upvotes: 10

Views: 1211

Answers (1)

Alexander Mills
Alexander Mills

Reputation: 100010

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 :)

Upvotes: 1

Related Questions