客户端上的JavaScript require()


Answers:




14

如果您想拥有Node.js样式require,可以使用以下代码:

var require = (function () {
    var cache = {};
    function loadScript(url) {
        var xhr = new XMLHttpRequest(),
            fnBody;
        xhr.open('get', url, false);
        xhr.send();
        if (xhr.status === 200 && xhr.getResponseHeader('Content-Type') === 'application/x-javascript') {
            fnBody = 'var exports = {};\n' + xhr.responseText + '\nreturn exports;';
            cache[url] = (new Function(fnBody)).call({});
        }
    }
    function resolve(module) {
        //TODO resolve urls
        return module;
    }
    function require(module) {
        var url = resolve(module);
        if (!Object.prototype.hasOwnProperty.call(cache, url)) {
            loadScript(url);
        }
        return cache[url];
    }
    require.cache = cache;
    require.resolve = resolve;
    return require;
}());

当心:此代码有效,但不完整(尤其是URL解析),并且未实现所有Node.js功能(我昨晚才将其组合在一起)。 您不应该在实际应用中使用此代码,但是它可以为您提供一个起点。我使用这个简单的模块对其进行了测试,并且可以正常工作:

function hello() {
    console.log('Hello world!');
}

exports.hello = hello;

3
我喜欢这个答案,因为它不是解决方案。当人们只是给出解决方案时,我真的很讨厌它。提供有助于他们下次找到解决方案的答案。做得好!
茉莉花2012年



7

我发现通常建议在编译时对脚本进行预处理,然后将它们捆绑在一个(或很少)包中,require并在编译时将其重写为某些“轻量级填充”。

我已经搜索了应该可以使用的“新”工具

而且已经提到的内容browserify也应该非常合适-http: //esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-loading-with-browserify/

什么是模块系统?


除了捆绑,它还允许从该捆绑中使用节点程序包吗?
eran otzap '16

4

您可以为DOM创建元素,以加载项目。

像这样:

var myScript = document.createElement('script'); // Create new script element
myScript.type = 'text/javascript'; // Set appropriate type
myScript.src = './js/myclass.js'; // Load javascript file

4

只需使用Browserify,这就像是编译器,可以在文件投入生产之前先处理文件,然后将文件打包成捆。

认为您有一个需要项目文件的main.js文件,当您在其中运行browserify时,它会简单地处理所有文件并创建包含所有文件的捆绑包,从而允许require在浏览器中同步使用调用,而无需HTTP请求和例如,在性能和捆绑包大小方面的开销很小。

有关更多信息,请参见链接:http : //browserify.org/


@dkastner早在2011年就提到过Browserify。我在答案中用Google搜索了一些替代方法,但我不知道排名第一的解决方案
xmojmr 2014年

2

已经有一些答案-但我想向您指出YUI3及其按需加载模块。它也可以在服务器(node.js)和客户端上使用-我有一个演示网站,该网站使用在客户端或服务器上运行的完全相同的JS代码来构建页面,但这是另一个主题。

YUI3:http//developer.yahoo.com/yui/3/

视频:http : //developer.yahoo.com/yui/theater/

例:

(前提:7k yui.js中的基本YUI3函数已加载)

YUI({
    //configuration for the loader
}).use('node','io','own-app-module1', function (Y) {
    //sandboxed application code
    //...

    //If you already have a "Y" instance you can use that instead
    //of creating a new (sandbox) Y:
    //  Y.use('moduleX','moduleY', function (Y) {
    //  });
    //difference to YUI().use(): uses the existing "Y"-sandbox
}

此代码加载YUI3模块“ node”和“ io”以及模块“ own-app-module1”,然后运行回调函数。创建具有所有YUI3和own-app-module1功能的新沙箱“ Y”。全局名称空间中没有任何内容。模块(.js文件)的加载由YUI3加载器处理。它还使用(可选,此处未显示)配置选择要加载的模块的-debug或-min(ified)版本。


1

这是采用不同方法的解决方案:将所有模块打包为JSON对象,并通过读取和执行文件内容来获得模块,而无需其他请求。

https://github.com/STRd6/require/blob/master/main.coffee.md

STRd6 / require取决于在运行时是否提供JSON包。该require函数是为该软件包生成的。该软件包包含您的应用可能需要的所有文件。由于该软件包捆绑了所有依赖项,因此不再发出http请求。这与客户端上所需的Node.js样式几乎一样。

软件包的结构如下:

entryPoint: "main"
distribution:
  main: 
    content: "alert(\"It worked!\")"
  ...
dependencies:
  <name>: <a package>

与Node不同,软件包不知道它的外部名称。取决于名称的依赖关系。这提供了完整的封装。

在完成所有设置后,这里提供了一个从包中加载文件的功能:

loadModule = (pkg, path) ->
  unless (file = pkg.distribution[path])
    throw "Could not find file at #{path} in #{pkg.name}" 

  program = file.content
  dirname = path.split(fileSeparator)[0...-1].join(fileSeparator)

  module =
    path: dirname
    exports: {}

  context =
    require: generateRequireFn(pkg, module)        
    global: global
    module: module
    exports: module.exports
    PACKAGE: pkg
    __filename: path
    __dirname: dirname

  args = Object.keys(context)
  values = args.map (name) -> context[name]

  Function(args..., program).apply(module, values)

  return module

该外部上下文提供了模块可以访问的一些变量。

一个require功能公开给模块,因此它们可能需要其他模块。

还公开了其他属性,例如对全局对象的引用和一些元数据。

最后,我们在模块和给定的上下文中执行程序。

对于希望在浏览器中具有同步node.js样式的require语句并且对远程脚本加载解决方案不感兴趣的人,此答案将最有帮助。



0

这是在Web客户端中使用需求和导出的轻量级方法。这是一个简单的包装程序,它创建一个“命名空间”全局变量,然后将您的CommonJS兼容代码包装在一个“定义”函数中,如下所示:

namespace.lookup('org.mydomain.mymodule').define(function (exports, require) {
    var extern = require('org.other.module');
    exports.foo = function foo() { ... };
});

此处有更多文档:

https://github.com/mckoss/namespace


0

客户机侧,需要库提供一个异步load()可用于加载任何JS文件或NPM模块(使用功能module.exports),任何.css文件,任何.json,任何.html,任何其他文件为文本。

例如, npm install clientside-require --save

<script src = '/node_modules/clientside-require/dist/bundle.js'></script>
<script>
load('color-name') // an npm module
   .then(color_name=>{
        console.log(color_name.blue); // outputs  [0, 0, 255]
   })
</script>

该项目的一个非常酷的部分是,任何load()ed脚本中,您都可以按照require()在node.js中期望的方式使用同步功能!

例如,

load('/path/to/functionality.js')

里面/path/to/functionality.js

var query_string = require("qs") // an npm module
module.exports = function(name){
    return qs.stringify({
         name:name,
         time:new Date()
    }
}

最后一部分,实现同步require()方法,使它能够利用为在服务器上运行而构建的NPM软件包。


该模块旨在require在浏览器中尽可能紧密地实现功能。免责声明:我已经编写了此模块。


某个地方有完整的工作示例吗?我试图在客户端加载我自己的类,它将无法正常工作。
jallmer

-4

是的,它非常易于使用,但是您需要通过脚本标记在浏览器中加载javascript文件

<script src="module.js"></script> 

然后用户在js文件中

var moduel = require('./module');

我正在使用电子制作应用程序,它可以按预期工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.