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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6971583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:02:57  来源:igfitidea点击:

Node-style require for in-browser javascript?

javascriptloadrequirescoping

提问by Alex Churchill

Are there any libraries for in-browser javascript that provide the same flexibility/modularity/ease of use as Node's require?

是否有任何可提供与 Node 相同的灵活性/模块化/易用性的浏览器内 JavaScript 库require

To provide more detail: the reason requireis so good is that it:

提供更多细节:原因require如此之好是因为它:

  1. Allows code to be dynamically loaded from other locations (which is stylistically better, in my opinion, than linking all your code in the HTML)
  2. It provides a consistent interface for building modules
  3. It is easy for modules to depend on other modules (so I could write, for instance, an API that requires jQuery so I can use jQuery.ajax()
  4. Loaded javascript is scoped, meaning I could load with var dsp = require("dsp.js");and I would be able to access dsp.FFT, which wouldn't interfere with my local var FFT
  1. 允许从其他位置动态加载代码(在我看来,这比在 HTML 中链接所有代码在风格上更好)
  2. 它为构建模块提供了一致的接口
  3. 模块很容易依赖其他模块(例如,我可以编写一个需要 jQuery 的 API,以便我可以使用 jQuery.ajax()
  4. 加载的 javascript 是有范围的,这意味着我可以加载var dsp = require("dsp.js");并且可以访问dsp.FFT,这不会干扰我的本地var FFT

I have yet to find a library that does this effectively. The workarounds I tend to use are:

我还没有找到一个有效地做到这一点的图书馆。我倾向于使用的解决方法是:

  • coffeescript-concat-- it's easy enough to require other js, but you have to compile it, which means it is less great for fast development (e.g. building APIs in-test)

  • RequireJS-- It's popular, straightforward, and solves 1-3, but lack of scoping is a real deal-breaker (I believe head.jsis similar in that it lacks scoping, though I've never had any occasion to use it. Similarly, LABjscan load and .wait()does mollify dependency issues, but it still doesn't do scoping)

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

  • RequireJS——它很流行,简单明了,可以解决 1-3,但缺乏范围界定是一个真正的交易破坏者(我相信head.js的相似之处在于它缺乏范围界定,尽管我从来没有机会使用它。类似地,LABjs可以加载并缓解.wait()依赖问题,但它仍然不进行范围界定)

As far as I can tell, there appear to be many solutions for dynamic and/or async loading of javascript, but they tend to have the same scoping issues as just loading the js from HTML. More than anything else, I would like a way to load javascript that does not pollute the global namespace at all, but still allows me to load and use libraries (just as node's require does).

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

EDIT (MY ANSWER):Since writing this, I have extensively used RequireJS(which now has much clearer documentation). RequireJS really was the right choice in my opinion. I'd like to clarify how the system works for people who are as confused as I was:

编辑(我的回答):自从写这篇文章以来,我广泛使用了RequireJS(现在有更清晰的文档)。在我看来,RequireJS 确实是正确的选择。我想澄清一下系统如何为和我一样困惑的人工作:

You can use requirein everyday development. A module can be anything returned by a function (typically an object or a function) and is scoped as a parameter. You can also compile your project into a single file for deployment using r.js(in practice this is almost always faster, even though requirecan load scripts in parallel).

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

The primary difference between RequireJS and node-style require like browserify (a cool project suggested by tjameson) uses is the way modules are designed and required:

RequireJS 和像 browserify(tjameson 推荐的一个很酷的项目)使用的 node-style require 之间的主要区别在于模块的设计和需要的方式:

  • RequireJS uses AMD (Async Module Definition). In AMD, requiretakes a list of modules (javascript files) to load and a callback function. When it has loaded each of the modules, it calls the callback with each module as a parameter to the callback. Thus it's truly asynchronous and therefore well-suited to the web.
  • Node uses CommonJS. In CommonJS, requireis a blocking call that loads a module and returns it as an object. This works fine for Node because files are read off the filesystem, which is fast enough, but works poorly on the web because loading files synchronously can take much longer.
  • RequireJS 使用 AMD(异步模块定义)。在 AMD 中,require需要加载一个模块列表(javascript 文件)和一个回调函数。当它加载了每个模块时,它会调用回调,并将每个模块作为回调的参数。因此它是真正异步的,因此非常适合网络。
  • Node 使用 CommonJS。在 CommonJS 中,require是一个阻塞调用,它加载一个模块并将其作为一个对象返回。这对 Node 很有效,因为文件是从文件系统读取的,这足够快,但在 web 上效果很差,因为同步加载文件可能需要更长的时间。

In practice, many developers have used Node (and therefore CommonJS) before they ever see AMD. In addition, many libraries/modules are written for CommonJS (by adding things to an exportsobject) rather than for AMD (by returning the module from the definefunction). Therefore, lots of Node-turned-web developers want to use CommonJS libraries on the web. This is possible, since loading from a <script>tag is blocking. Solutions like browserify take CommonJS (Node) modules and wrap them up so you can include them with script tags.

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

Therefore, if you are developing your own multi-file project for the web, I strongly recommend RequireJS, since it is truly a module system for the web (though in fair disclosure, I find AMD much more natural than CommonJS). Recently, the distinction has become less important, since RequireJS now allows you to essentially use CommonJS syntax. Additionally, RequireJS can be used to load AMD modules in Node (though I prefer node-amd-loader).

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

采纳答案by beatgammit

Check out ender. It does a lot of this.

检查ender。它做了很多这样的事情。

Also, browserifyis pretty good. I've used require-kissand it works. There are probably others.

此外,browserify非常好。我已经使用了require-kiss并且它有效。可能还有其他人。

I'm not sure about RequireJS. It's just not the same as node's. You may run into problems with loading from other locations, but it might work. As long as there's a provide method or something that can be called.

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

TL;DR- I'd recommend browserify or require-kiss.

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

Update:

更新:

require-kiss is now dead, and the author has removed it. I've since been using RequireJS without problems. The author of require-kiss wrote pakmanagerand pakman. Full disclosure, I work with the developer.

require-kiss 现在已死,作者已将其删除。从那以后,我一直在使用 RequireJS,没有任何问题。require-kiss 的作者写了pakmanagerpakman。完全披露,我与开发商合作。

Personally I like RequireJS better. It is much easier to debug (you can have separate files in development, and a single deployed file in production) and is built on a solid "standard".

我个人更喜欢 RequireJS。调试要容易得多(您可以在开发中使用单独的文件,在生产中使用单个部署的文件)并且构建在可靠的“标准”之上。

回答by Torben

I wrote a small script which allows asynchronous and synchronous loading of Javascript files, which might be of some use here. It has no dependencies and is compatible to Node.js & CommonJS. The usage is pretty easy:

我写了一个小脚本,它允许异步和同步加载 Javascript 文件,这可能在这里有用。它没有依赖项并且兼容 Node.js 和 CommonJS。用法很简单:

<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>

More details and the code can be found in my blog: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/The code is also on GitHub: https://github.com/letorbi/tarp.require

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

回答by Lucio M. Tato

A variation of Ilya Kharlamov great answer, with some code to make it play nice with chrome developer tools.

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

回答by Ilya Kharlamov

(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];
    }
})();

Better not to be used in production because of the blocking. (In node.js, require() is a blocking call is well).

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

回答by Ilyas Assainov

I realize there may be beginners looking to organize their code. This is 2020, and if you're considering a modular JS app, you should get started with npmand Webpackright now.

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

Here are a few simple steps to get started:

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

  1. In your project root, run npm init -yto initialize an npm project
  2. Download the Webpack module bundler: npm install webpack webpack-cli
  3. Create an index.html file:
  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>

Pay special attention to _bundle.jsfile - this will be a final JS file generated by webpack, you will not modify it directly (keep reading).

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

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

printHello();
  1. Create a sample print-hello.jsmodule:
  1. 创建示例print-hello.js模块:
module.exports = function() {
    console.log('Hello World!');
}
  1. Create a <project-root>/webpack.config.jsand copy-paste the following:
  1. 创建一个<project-root>/webpack.config.js并复制粘贴以下内容:
var path = require('path');

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

In the code above, there are 2 points:

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

  • entry app.jsis where you will write your JS code. It will import other modules as shown above.
  • output _bundle.jsis your final bundle generated by webpack. This is what your html will see at the end.
  • entryapp.js是您编写 JS 代码的地方。它将导入其他模块,如上所示。
  • output_bundle.js是由 webpack 生成的最终包。这就是您的 html 将在最后看到的内容。

-7. Open your package.js, and replace scriptswith the following command:

-7. 打开您的package.js, 并替换scripts为以下命令:

  "scripts": {
    "start": "webpack --mode production -w"
  },
  1. And finally run the script watch app.jsand generate the _bundle.jsfile by running: npm start.
  2. Enjoy coding!
  1. 最后运行脚本的手表app.js,并生成_bundle.js运行文件:npm start
  2. 享受编码!

回答by dy_

Require-stub— provides node-compliant requirein browser, resolves both modules and relative paths. Uses technic similar to TKRequire (XMLHttpRequest). Resulting code is fully browserifyable, in that require-stubcan serve as a replacement for watchify.

Require-stubrequire在浏览器中提供节点兼容,解析模块和相对路径。使用类似于 TKRequire (XMLHttpRequest) 的技术。生成的代码是完全可浏览的,因为它require-stub可以替代watchify.

回答by Mariusz Nowak

Webmakebundles Node-style modules to Browser, give it a try.

Webmake 将Node 风格的模块捆绑到浏览器中,试一试。

回答by Trausti Kristjansson

Here is an extension to Lucio M. Tato's fantastic answer that allows for recursive loading of modules with relative paths.

这是 Lucio M. Tato 出色答案的扩展,它允许递归加载具有相对路径的模块。

Here is a github project to house the solutionand an example of how to use it:

这是一个包含解决方案github 项目以及如何使用它的示例:

https://github.com/trausti/TKRequire.js

https://github.com/trausti/TKRequire.js

To use TKRequire.js, include the following line in your header

要使用 TKRequire.js,请在标题中包含以下行

<script type="text/javascript" src="./TKRequire.js"></script>

<script type="text/javascript" src="./TKRequire.js"></script>

Then load modules just like in node.js:

然后像在 node.js 中一样加载模块:

var MyModule = require("./relative/path/to/MyModule.js");

var MyModule = require("./relative/path/to/MyModule.js");