Search code examples
javascriptmergemodulerequirejsbundle

Merging requirejs and plain js file together


I'm developping a small website, and the main HTML page basically looks like this:

<html lang="en">
  <head>
    <script src="ace.js" type="text/javascript"><script>
    <script src="ext-language_tools.js" type="textjavascript"></script>
    <script src="mode-mongo.js" type="text/javascript"></script>
    <script src="playground.js" type="text/javascript"></script>
    <script type="text/javascript">
    
      window.onload = function() {
    
        ace.config.setModuleUrl("ace/mode/mongo", "mode-mongo.js")
    
        configEditor = ace.edit(document.getElementById("editor"), {
            "mode": "ace/mode/mongo",
            "useWorker": false
        })
      }
    </script>
  </head>
  <body>
    <div class="editor">
  </body>
</html>

( real one is visible here ).

Here are the unminified files:

The first 3 js files use requirejs, the 4th is just plain js

Is there a way to merge those 4 files into a single file in order to have something like this in my HTML instead ?

<html lang="en">
  <head>
    <script src="bundle.js" type="text/javascript"><script>
    <script type="text/javascript">
    
      window.onload = function() {

        configEditor = ace.edit(document.getElementById("editor"), {
            "mode": "ace/mode/mongo",
            "useWorker": false
        })
      }
    </script>
  </head>
  <body>
    <div class="editor">
  </body>
</html>

Edit

My goal is to load all this js code at once in a single HTTP request


Solution

  • This is an interesting question, since there are a bunch of potential solutions that span a few eras and philosophies in JavaScript and Web development. I'll talk about about the easiest and oldest, file concatenation, and briefly touch upon RequireJS, and more modern approaches of using dedicated web bundlers. There's also the unstated, underlying assumption of why you feel you need to bundle it-- there might be some assumptions of file loading which might not be true, particularly with HTTP/2.

    The Quick Way

    If you want something quick, easy, and old school, you can just combine (concatenate) all of your JavaScript files together. That's essentially what's happening in your initial web page: the browser downloads all of the JavaScript files and runs them in order.

    To concatenate using Unix/Linux/OS X:

    cat path/to/ace.js  <(echo) \
      path/to/ext-language_tools.js  <(echo) \
      path/to/mode-mongo.js  <(echo) \
      path/to/playground.js \
      > path/to/bundle.js
    

    (You can combine them all on one line if you remove the \s. You can also omit the <(echo) if you know the file ends with a new line)

    Alternatively, you can manually copy and paste the files into one big file.

    The RequireJS Way

    It bears mentioning the RequireJS way of doing things, that uses require statements, since that's the philosophy that ace.js is developed under. Using this philosophy, files are intended to stay separated as modules and are loaded as needed. Other answers explain this approach in more detail, though I'll add that bundling doesn't seem to be the idiomatic way to use RequireJS-- the library originally intended (though doesn't require) modules to be split into different files.

    The Web Bundler Way

    In recent years, people have adopted web bundlers-- like webpack, parcel, rollup, and more -- to manage multiple files and dependencies. These tools are intended to output a single web bundle and have a lot of nice, customizable features for that. They might need a bit of work to get up and running, and need to use a CommonJS plugin to get require working. For instance, see here to get ace working with webpack.

    Do you need to bundle?

    Depending on your concerns and situation, bundling might not need be an optimization you need. Historically, bundling was used as a way to minimize network requests, since the number of network connections was limited, and sometimes files requested other files, leading to loading in serial. Many of these concerns were addressed with HTTP/2. Just make sure that your web server supports HTTP/2 and that you're serving all the files on that server. For more information about this, see this question. You probably care most of how it operates in practice, so you'd probably want to benchmark it either way, but you might not be gaining much.