Using RequireJS with legacy code

2019-05-07 23:40发布

问题:

I'm working with a very large project that uses:

  1. Legacy JSP pages that includes javascript files with script tags
  2. Backbone models and views that uses other javascript modules without RequireJS

We now want to start using RequireJS with jQuery, BackboneJS and UnderscoreJS for everything we develop from now on, but we don't have the resources to rewrite all the legacy JSP pages. We may have time to rewrite the Backbone models and views we have already developed.

The problem is that for our legacy code (both 1 and 2 above) we include all our javascript files in a huge file and ship to the browsers. This huge file must be able to co-exist with our new RequireJS templates, but how can I e.g. separate certain parts of the huge file, so I can use them with the templates using RequireJS? Without having to rewrite all pages that uses this part of the file, or having duplicate code.

Thanks!

回答1:

I don't know if I fully grasp the problem at hand, but I think a the shim or map functions of RequireJS will help you out.

Extract the parts you want in a new module from your huge javascript file. Then tell RequireJS that your huge javascript file is a dependecy for this new module using shim. Something like:

requirejs.config({
    shim: {
        'new-module': {
            deps: ['huge-javascript-file'],
            exports: 'NewModule'
    }
});

Shim documentation: http://requirejs.org/docs/api.html#config-shim

The map function might be useful when only portions of your new code have to use your old huge file. Check out this documentation: http://requirejs.org/docs/api.html#config-map



回答2:

I don't think there is One True Way to achieve this, but I've approached a similar problem by defining module "facades" around the globally scoped code. Let's say your legacy scripts define a global variable called foo. You can define a AMD module and export that variable from it:

//foo.js
define(function() {
  return window.foo;
});

//bar.js
define(['foo'], function(foo) {
  //do something with foo
});

This way you only need to write a single-line facade every time you need to use a new piece of the existing, globally defined code, without breaking existing code which expects the same code to be globally defined. Over time you can move and refactor the actual implementation into the module without breaking consumer code.