简体   繁体   English

客户端的JavaScript require()

[英]JavaScript require() on client side

Is it possible to use require() (or something similar) on client side? 是否可以在客户端使用require() (或类似的东西)?

Example

var myClass = require('./js/myclass.js');

您应该查看require.jshead.js。

I've been using browserify for that. 我一直在使用browserify It also lets me integrate Node.js modules into my client-side code. 它还允许我将Node.js模块集成到我的客户端代码中。

I blogged about it here: Add node.js/CommonJS style require() to client-side JavaScript with browserify 我在这里写博客:使用browserify将node.js / CommonJS样式require()添加到客户端JavaScript

If you want to have Node.js style require you can use something like this: 如果你想要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;
}());

Beware: this code works but is incomplete (especially url resolving) and does not implement all Node.js features (I just put this together last night). 注意:这段代码有效,但不完整(特别是url解析),并没有实现所有Node.js功能(我昨晚把它放在一起)。 YOU SHOULD NOT USE THIS CODE in real apps but it gives you a starting point. 你不应该在真正的应用程序中使用这个代码 ,但它为你提供了一个起点。 I tested it with this simple module and it works: 我用这个简单的模块测试它,它的工作原理:

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

exports.hello = hello;

I asked myself the very same questions. 我问自己同样的问题。 When I looked into it I found the choices overwhelming. 当我调查它时,我发现选择压倒性的。

Fortunately I found this excellent spreadsheet that helps you choice the best loader based on your requirements: 幸运的是,我发现这个优秀的电子表格可以帮助您根据自己的要求选择最好的装载机:

https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ

看看requirejs项目。

I have found that in general it is recommended to preprocess scripts at compile time and bundle them in one (or very few) packages with the require being rewritten to some "lightweight shim" also at compile time. 我发现一般情况下,建议在编译时预处理脚本,并将它们捆绑在一个(或很少)包中,并在编译时将require重写为一些“轻量级填充程序”。

I've Googled out following "new" tools that should be able to do it 我已经使用了应该能够执行此操作的“新”工具

And the already mentioned browserify should also fit quite well - http://esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-loading-with-browserify/ 而已经提到browserify也应该适应得不错- http://esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-loading-with-browserify/

What are the module systems all about? 什么是模块系统?

You can create elements to the DOM, which loads items. 您可以为DOM创建元素,这些元素会加载项目。

Like such: 像这样:

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

Simply use Browserify, what is something like a compiler that process your files before it go into production and packs the file in bundles. 只需使用Browserify,就像编译器在进入生产环境之前处理文件并将文件打包成捆绑包。

Think you have a main.js file that require the files of your project, when you run browserify in it, it simply process all and creates a bundle with all your files, allowing the use of the require calls synchronously in the browser without HTTP requests and with very little overhead for the performance and for the size of the bundle, for example. 认为你有一个需要项目文件的main.js文件,当你在其中运行browserify时,它只是处理所有文件并创建一个包含所有文件的包,允许在没有HTTP请求的情况下在浏览器中同步使用require调用例如,对于性能和捆绑的大小而言,开销很小。

See the link for more info: http://browserify.org/ 有关详细信息,请参阅链接: http//browserify.org/

Some answers already - but I would like to point you to YUI3 and its on-demand module loading. 一些答案已经 - 但我想指出YUI3及其按需模块加载。 It works on both server (node.js) and client, too - I have a demo website using the exact same JS code running on either client or server to build the pages, but that's another topic. 它也适用于服务器(node.js)和客户端 - 我有一个演示网站使用在客户端或服务器上运行的完全相同的JS代码来构建页面,但这是另一个主题。

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

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

Example: 例:

(precondition: the basic YUI3 functions in 7k yui.js have been loaded) (前提条件:已加载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
}

This code loads the YUI3 modules "node" and "io", and the module "own-app-module1", and then the callback function is run. 此代码加载YUI3模块“node”和“io”,以及模块“own-app-module1”,然后运行回调函数。 A new sandbox "Y" with all the YUI3 and own-app-module1 functions is created. 创建具有所有YUI3和own-app-module1函数的新沙箱“Y”。 Nothing appears in the global namespace. 全局命名空间中没有任何内容。 The loading of the modules (.js files) is handled by the YUI3 loader. 模块(.js文件)的加载由YUI3加载器处理。 It also uses (optional, not show here) configuration to select a -debug or -min(ified) version of the modules to load. 它还使用(可选,此处未显示)配置来选择要加载的模块的-debug或-min(ified)版本。

Here's a solution that takes a very different approach: package up all the modules into a JSON object and require modules by reading and executing the file content without additional requests. 这是一个采用非常不同的方法的解决方案:将所有模块打包成JSON对象,并通过读取和执行文件内容而无需额外请求来获取模块。

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

STRd6/require depends on having a JSON package available at runtime. STRd6 / require取决于在运行时可用的JSON包。 The require function is generated for that package. 为该包生成require函数。 The package contains all the files your app could require. 该软件包包含您的应用可能需要的所有文件。 No further http requests are made because the package bundles all dependencies. 没有进一步的http请求,因为包捆绑了所有依赖项。 This is as close as one can get to the Node.js style require on the client. 这与客户端上的Node.js样式要求非常接近。

The structure of the package is as follows: 包的结构如下:

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

Unlike Node a package doesn't know it's external name. 与Node不同,包不知道它的外部名称。 It is up to the pacakge including the dependency to name it. 这取决于包括依赖命名的pacakge。 This provides complete encapsulation. 这提供了完整的封装。

Given all that setup here's a function that loads a file from within a package: 鉴于所有这些设置,这是一个从包中加载文件的函数:

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

This external context provides some variable that modules have access to. 此外部上下文提供了模块可以访问的一些变量。

A require function is exposed to modules so they may require other modules. require函数暴露给模块,因此它们可能需要其他模块。

Additional properties such as a reference to the global object and some metadata are also exposed. 还公开了其他属性,例如对全局对象的引用和一些元数据。

Finally we execute the program within the module and given context. 最后,我们在模块和给定的上下文中执行程序。

This answer will be most helpful to those who wish to have a synchronous node.js style require statement in the browser and are not interested in remote script loading solutions. 对于那些希望在浏览器中具有同步node.js style require语句并且对远程脚本加载解决方案不感兴趣的人来说,这个答案最有帮助。

I find the component project giving a much more streamlined workflow than other solutions (including require.js), so I'd advise checking out https://github.com/component/component . 我发现组件项目比其他解决方案(包括require.js)提供了更加简化的工作流程,因此我建议您查看https://github.com/component/component I know this is a bit late answer but may be useful to someone. 我知道这是一个迟到的答案,但可能对某人有用。

The clientside-require library provides an asynchronous load() function that can be used to load any JS file or NPM module (which uses module.exports ), any .css file, any .json , any .html , any any other file as text. clientside-require库提供了一个异步load()函数,可用于加载任何JS文件或NPM模块(使用module.exports ),任何.css文件,任何.json ,任何.html ,任何其他任何文件文本。

eg, npm install clientside-require --save 例如, 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>

A really cool part of this project is that inside of any load() ed script, you can use the synchronous require() function the same way you would expect in node.js! 这个项目的一个非常酷的部分是任何load() ed脚本中,你可以像在node.js中一样使用同步require()函数!

eg, 例如,

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

and inside /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()
    }
}

That last part, implementing the synchronous require() method, is what enables it to utilize NPM packages built to run on the server. 最后一部分,实现同步require()方法,使其能够利用构建在服务器上运行的NPM包。


This module was designed to implement the require functionality as closely as possible in the browser. 该模块旨在尽可能在浏览器中实现require功能。 Disclaimer: I have written this module. 免责声明:我已经写过这个模块。

Here's a light weight way to use require and exports in your web client. 这是在Web客户端中使用require和exports的轻量级方法。 It's a simple wrapper that creates a "namespace" global variable, and you wrap your CommonJS compatible code in a "define" function like this: 它是一个创建“命名空间”全局变量的简单包装器,您将CommonJS兼容代码包装在“define”函数中,如下所示:

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

More docs here: 更多文档:

https://github.com/mckoss/namespace https://github.com/mckoss/namespace

Yes it is very easy to use, but you need to load javascript file in browser by script tag 是的,它非常易于使用,但您需要通过脚本标记在浏览器中加载javascript文件

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

and then user in js file like 然后用户在js文件中

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

I am making a app using electron and it works as expected. 我正在使用电子制作应用程序,它按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM