最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - RequireJS load string - Stack Overflow

programmeradmin2浏览0评论

In my app there are dynamic parts that are loaded from database as string that looks like:

"define(['dependency1', 'dependency2'], function(){"+
"   // function body" +
"})"

which is just a simple requireJS module, as a string. I want to lazy load the script above using async require call. So, my main requireJS script looks like:

require(["jquery"], function($){        
    $(document).ready(function(){
        // logic to load specific script from database
        var scriptString = functionToLoadTheStringAbove();

        // ideally i would like to call it like this            
        require([scriptString], function(){
           // scriptString, dependency1, dependency2 are loaded
        }
    });
});

How do I load those string in requireJS? I know about text plugin, but it only allow loading from files. I tried eval but it doesn't resolve dependencies correctly.

In my app there are dynamic parts that are loaded from database as string that looks like:

"define(['dependency1', 'dependency2'], function(){"+
"   // function body" +
"})"

which is just a simple requireJS module, as a string. I want to lazy load the script above using async require call. So, my main requireJS script looks like:

require(["jquery"], function($){        
    $(document).ready(function(){
        // logic to load specific script from database
        var scriptString = functionToLoadTheStringAbove();

        // ideally i would like to call it like this            
        require([scriptString], function(){
           // scriptString, dependency1, dependency2 are loaded
        }
    });
});

How do I load those string in requireJS? I know about text plugin, but it only allow loading from files. I tried eval but it doesn't resolve dependencies correctly.

Share Improve this question edited Apr 26, 2013 at 4:25 bradnoriega asked Apr 26, 2013 at 3:35 bradnoriegabradnoriega 1632 silver badges8 bronze badges 3
  • please be clear while asking any question. Please refeame your question. – Nikhil Agrawal Commented Apr 26, 2013 at 3:55
  • Oh my, are you really storing evaluable code in database like this? – Tomáš Zato Commented Oct 26, 2015 at 2:06
  • Yes. In my case it was in browser extension. So, no choice of creating REST endpoint / saving dynamic code in filesystem. – bradnoriega Commented Mar 4, 2016 at 3:42
Add a ment  | 

3 Answers 3

Reset to default 6

This is quite late, but I just post my solution here in case anyone needs.

So I ended up asking in requireJS forum and examining the source of text! plugin and json! plugin. The cleanest way to load module from String in RequireJS is by making your own plugin to load the String, and then use onLoad.fromText() that will eval your String and resolve all dependencies.

Example of my plugin (let's call it db! plugin):

define([], function(){
    var db = new Database(); // string is loaded from LocalStorage
    return {
        load: function(name, req, onLoad, reqConfig){
            db.get(name, function(err, scriptString){
                if (err) onLoad(err);
                else onLoad.fromText(scriptString);
            });  
         }
    }
});

You can then use the plugin like:

require(["jquery", "db!myScript"], function($, myScript){        
    // jQuery, myScript and its dependencies are loaded from database
});

Note:

  1. There's no way to require() from String without eval. This is what onLoad.fromText() does internally. Since eval is evil, you should only use it if you know what String you're going to eval(). If you're using it in browser extension, you might want to relax the CSP policy.
  2. To name your String module, you can use explicit naming syntax. This way, your module will always have the same absolute name.

To answer the question a little more directly, create a plugin like so:

define("load-string",[], function(){
    var strings=[],
        re_package_name = /^string_module_(\d+)$/;
    return {
        normalize: function(name, _){
            if(re_package_name.test(name)){
                return name
            }
            var nml = "string_module_" + (strings.push(name)-1);
            return nml;
        },
        load: function(name, _, onLoad, config){
            if(re_package_name.test(name)){
                onLoad.fromText(strings[name.match(re_package_name)[1]]);
            }else{
                onLoad.error("Invalid package name: ",name);
            }
        }  
    }
});

and use it like so:

var world_module = "define([],function(){return 'world!'})";

require(["load-string!" + world_module],
    function(x){
        console.log("Hello "+x);
    })

You should be able to do :

require(["jquery"], function($){        
    $(document).ready(function(){
        // logic to load specific script from database
        var scriptString = functionToLoadTheStringAbove();

        var olddefine = define; // require js define 
        var runme; // capture function 
        define = function (args,func){
             runme = func; 
        }
        eval(scriptString);
        runme(); // run the function in current scope
        define = olddefine; // restore requirejs function 

        // dependency1, dependency2 are loaded        
    });
});
发布评论

评论列表(0)

  1. 暂无评论