Search code examples
javascriptnode.jswebpack

Is there a way to prepend external JS tools in Node/Webpack?


I'm using Vue.js to build my frontend app, and in that page, I have (too many) Javascript external resources : Google Analytics, Typekit, Google Charts, Intercom, Raven, etc.

Is there a way to configure my Webpack config file and tell it to download the links that are in the index.html (even by adding the urls in the specific file) that would then be appended to my generated js.

The aim here is to reduce the load of JS files, and avoid issues (like not loaded libraries).


Solution

  • Although it may sound like a straightforward improvement (less requests -> faster page load) it's generally not a good idea to combine all of your scripts into one bundle.

    There are plenty of reasons:

    1. CDN's are fast. Unless your bundle is also served via CDN, merging these scripts would be counterproductive.

    2. With even the smallest code fix You have to force the client to invalidate the cache and download the whole bundle again.

    3. Popular scripts (like GA) might have been already cached by user's browser, so they won't be downloaded at all.

    4. Third party scripts have a tendency to a) be updated b) load other scripts. So if you bundle one specific version of such a script, it could become broken the moment after.

    What can be done

    Most of these scripts are not crucial to the page render, so you could

    1. Load the scripts in a non-blocking manner.
    2. Load the scripts after the page is fully rendered.

    I understand the consequences, but I really need to bundle those scripts!

    Apparently, you could not bundle remote script with webpack:

    webpack is a module bundler not a javascript loader. It package files from local disk and don't load files from the web (except its own chunks).

    Use a javascript loader, i. e. script.js.

    var $script = require("scriptjs");
    
    $script("//ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js", function() {
        // ...
    });
    

    However, You can prepend your bundle with external scripts using some kind of task runner, like gulp or grunt.

    var gulp = require('gulp');
    var source = require('vinyl-source-stream');
    var request = require('request');
    var merge = require('merge2');
    var concat = require('gulp-concat');
    var buffer = require('gulp-buffer');
    
    gulp.task('js', function() {
      var jquery = request('http://code.jquery.com/jquery-latest.js').pipe(source('jquery.js'));
      var main = gulp.src('main.js');
    
      return merge(jquery, main)
        .pipe(buffer())
        .pipe(concat('concat.js'))
        .pipe(gulp.dest('dist'));
    });
    

    Since You could integrate webpack into your building pipeline, it seems like a fairy decent approach.