浏览器内的javascript需要节点式吗?

Ale*_*ill 73 javascript load require scoping

是否存在任何用于浏览器内javascript的库,它们提供与Node相同的灵活性/模块性/易用性require

提供更多细节:原因require很好,它是:

  1. 允许从其他位置动态加载代码(在我看来,这比在HTML中链接所有代码更好)
  2. 它为构建模块提供了一致的界面
  3. 模块很容易依赖于其他模块(因此我可以编写一个需要jQuery的API,以便我可以使用 jQuery.ajax()
  4. 加载的javascript是作用域,这意味着我可以加载,var dsp = require("dsp.js");我将能够访问dsp.FFT,这不会干扰我的本地var FFT

我还没有找到一个能够有效地完成这项工作的库.我倾向于使用的解决方法是:

  • coffeescript-concat - 它很容易需要其他js,但你必须编译它,这意味着它不太适合快速开发(例如构建API in-test)

  • RequireJS - 它是流行的,直截了当的,并解决了1-3,但缺乏范围是一个真正的交易破坏者(我相信head.js是相似的,因为它缺乏范围,虽然我从来没有任何机会使用它.类似地,LABjs可以加载并.wait()确实缓解依赖性问题,但它仍然没有确定范围)

据我所知,似乎有许多解决方案用于javascript的动态和/或异步加载,但它们往往具有与从HTML加载js相同的范围问题.最重要的是,我想要一种加载不会污染全局命名空间的javascript的方法,但仍允许我加载和使用库(就像节点的要求一样).

编辑(我的答案):自写这篇文章以来,我已广泛使用RequireJS(现在有更清晰的文档).在我看来,RequireJS确实是正确的选择.我想澄清一下系统如何适用于那些和我一样困惑的人:

您可以require在日常开发中使用.模块可以是函数返回的任何内容(通常是对象或函数),并且作为参数确定范围.您还可以将项目编译为单个文件以进行部署r.js(实际上,这几乎总是更快,即使require可以并行加载脚本).

RequireJS和node-style之间的主要区别就像browserify(由tjameson建议的一个很酷的项目)使用的是模块的设计和要求:

  • RequireJS使用AMD(异步模块定义).在AMD中,require获取要加载的模块(javascript文件)列表和回调函数.当它加载了每个模块时,它会调用每个模块的回调作为回调的参数.因此,它是真正的异步,因此非常适合网络.
  • Node使用CommonJS.在CommonJS中,require是一个阻塞调用,它加载模块并将其作为对象返回.这适用于Node,因为文件从文件系统读取,这足够快,但在Web上运行不佳,因为同步加载文件可能需要更长的时间.

实际上,许多开发人员在看到AMD之前都使用过Node(因此也使用了CommonJS).此外,许多库/模块是为CommonJS编写的(通过向exports对象添加内容)而不是为AMD 编写(通过从define函数返回模块).因此,许多支持Node的Web开发人员希望在Web上使用CommonJS库.这是可能的,因为从<script>标签加载是阻塞的.像browserify这样的解决方案采用CommonJS(Node)模块并将它们包装起来,以便您可以将它们包含在脚本标记中.

因此,如果您正在为Web开发自己的多文件项目,我强烈推荐RequireJS,因为它确实是Web的模块系统(尽管在公平披露中,我发现AMD比CommonJS更自然).最近,区别变得不那么重要了,因为RequireJS现在允许您基本上使用CommonJS语法.另外,RequireJS可用于在Node中加载AMD模块(虽然我更喜欢node-amd-loader).

Ily*_*nov 16

我意识到可能有初学者希望组织他们的代码。这是2021 年,如果您正在考虑模块化 JS 应用程序,您应该立即开始使用npmWebpack

以下是一些简单的入门步骤:

  1. 在您的项目根目录中,运行npm init -y以初始化一个 npm 项目
  2. 下载 Webpack 模块打包器: npm install webpack webpack-cli
  3. 创建一个 index.html 文件:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>App</title>
</head>
<body>
    
    <script src="_bundle.js"></script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

特别注意_bundle.js文件——这将是webpack生成的最终JS文件,你不会直接修改它(继续阅读)。

  1. 创建一个<project-root>/app.js您将在其中导入其他模块的:
const printHello = require('./print-hello');

printHello();
Run Code Online (Sandbox Code Playgroud)
  1. 创建示例print-hello.js模块:
module.exports = function() {
    console.log('Hello World!');
}
Run Code Online (Sandbox Code Playgroud)
  1. 创建一个<project-root>/webpack.config.js并复制粘贴以下内容:
var path = require('path');

module.exports = {
  entry: './app.js',
  output: {
    path: path.resolve(__dirname),
    filename: '_bundle.js'
  }
};
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,有2点:

  • entryapp.js是您编写 JS 代码的地方。它将导入其他模块,如上所示。
  • output_bundle.js是由 webpack 生成的最终包。这就是您的 html 将在最后看到的内容。
  1. 打开您的package.json, 并替换scripts为以下命令:
  "scripts": {
    "start": "webpack --mode production -w"
  },
Run Code Online (Sandbox Code Playgroud)
  1. 最后运行脚本的手表app.js,并生成_bundle.js运行文件:npm start
  2. 享受编码!

  • 2020 年这应该被标记为正确答案 (3认同)

bea*_*mit 15

查看ender.它做了很多这个.

此外,browserify非常好.我使用过require-kiss,它很有效.可能还有其他人.

我不确定RequireJS.它与节点不同.从其他位置加载可能会遇到问题,但可能会有效.只要有提供方法或可以调用的东西.

TL; DR - 我建议使用browserify或者require-kiss.

更新:

require-kiss现在已经死了,作者已将其删除.我一直在使用RequireJS没有问题.require-kiss的作者写了pakmanagerpakman.完全披露,我与开发人员合作.

我个人更喜欢RequireJS.它更容易调试(您可以在开发中使用单独的文件,在生产中使用单个部署的文件)并且基于可靠的"标准".


Tor*_*ben 13

我写了一个小脚本,允许异步和同步加载Javascript文件,这可能在这里有用.它没有依赖关系,并且与Node.js和CommonJS兼容.您甚至可以将多个模块捆绑在一个文件中,以减少生产服务器上的HTTP请求.用法非常简单:

<script type="text/javascript" src="require.js"></script>
<script type="text/javascript">
    var ModuleA = require('modulea') // Sync loading of a script in the module directory
    ModuleA.funcA();

    require('./path/moduleb.js', callbackB); // Async loading of a script anywhere else
    function callbackB(ModuleB) {
        ModuleB.funcB();
    }
</script>
Run Code Online (Sandbox Code Playgroud)

更多详细信息和代码可以在我的博客上找到:http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/ 代码也是在GitHub上:https://开头的github的.com/letorbi /冰沙/斑点/主/独立/ require.js


Luc*_*ato 7

Ilya Kharlamov的一个变种很好的答案,有一些代码使它与chrome开发工具很好玩.

//
///- REQUIRE FN
// equivalent to require from node.js
function require(url){
    if (url.toLowerCase().substr(-3)!=='.js') url+='.js'; // to allow loading without js suffix;
    if (!require.cache) require.cache=[]; //init cache
    var exports=require.cache[url]; //get from cache
    if (!exports) { //not cached
            try {
                exports={};
                var X=new XMLHttpRequest();
                X.open("GET", url, 0); // sync
                X.send();
                if (X.status && X.status !== 200)  throw new Error(X.statusText);
                var source = X.responseText;
                // fix (if saved form for Chrome Dev Tools)
                if (source.substr(0,10)==="(function("){ 
                    var moduleStart = source.indexOf('{');
                    var moduleEnd = source.lastIndexOf('})');
                    var CDTcomment = source.indexOf('//@ ');
                    if (CDTcomment>-1 && CDTcomment<moduleStart+6) moduleStart = source.indexOf('\n',CDTcomment);
                    source = source.slice(moduleStart+1,moduleEnd-1); 
                } 
                // fix, add comment to show source on Chrome Dev Tools
                source="//@ sourceURL="+window.location.origin+url+"\n" + source;
                //------
                var module = { id: url, uri: url, exports:exports }; //according to node.js modules 
                var anonFn = new Function("require", "exports", "module", source); //create a Fn with module code, and 3 params: require, exports & module
                anonFn(require, exports, module); // call the Fn, Execute the module
                require.cache[url]  = exports = module.exports; //cache obj exported by module
            } catch (err) {
                throw new Error("Error loading module "+url+": "+err);
            }
    }
    return exports; //require returns object exported by module
}
///- END REQUIRE FN
Run Code Online (Sandbox Code Playgroud)


Ily*_*mov 5

(function () {
    // c is cache, the rest are the constants
    var c = {},s="status",t="Text",e="exports",E="Error",r="require",m="module",S=" ",w=window;
    w[r]=function R(url) {
        url+=/.js$/i.test(url) ? "" : ".js";// to allow loading without js suffix;
        var X=new XMLHttpRequest(),module = { id: url, uri: url }; //according to the modules 1.1 standard
        if (!c[url])
            try {
                X.open("GET", url, 0); // sync
                X.send();
                if (X[s] && X[s] != 200) 
                    throw X[s+t];
                Function(r, e, m, X['response'+t])(R, c[url]={}, module); // Execute the module
                module[e] && (c[url]=module[e]);
            } catch (x) {
                throw w[E](E+" in "+r+": Can't load "+m+S+url+":"+S+x);
            }
        return c[url];
    }
})();
Run Code Online (Sandbox Code Playgroud)

最好不要因为阻塞而在生产中使用.(在node.js中,require()是一个阻塞调用很好).