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

新手上路,请多包涵

是否有任何用于浏览器内 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)

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

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

2020 年更新: 模块 现在是 ES6 中的标准,到 2020 年年中, 大多数浏览器 都原生支持模块。模块支持同步和异步(使用 Promise)加载。我目前的建议是,大多数新项目应该使用 ES6 模块,并使用转译器为旧版浏览器回退到单个 JS 文件。

作为一般原则,今天的带宽通常也比我最初问这个问题时宽得多。所以在实践中,你可能会合理地选择始终使用带有 ES6 模块的转译器,并将你的精力集中在代码效率而不是网络上。

之前的编辑(或者如果你不喜欢 ES6 模块): 自从写这篇文章以来,我广泛使用了 RequireJS (现在有更清晰的文档)。在我看来,RequireJS 确实是正确的选择。我想为那些和我一样困惑的人澄清一下这个系统是如何工作的:

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

RequireJS 和像 browserify(tjameson 建议的一个很酷的项目)这样的节点式 require 之间的主要区别在于模块的设计和需求方式:

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

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

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

原文由 Alex Churchill 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 913
2 个回答

查看 安德。它做了很多这样的事情。

另外, browserify 也很不错。我用过 require-kiss ¹ 并且有效。可能还有其他人。

我不确定 RequireJS。它与节点的不一样。您可能会遇到从其他位置加载的问题,但它可能会起作用。只要有provide方法什么的可以调用。

TL;DR - 我推荐 browserify 或 require-kiss。


更新:

1: require-kiss 现在已经死了,作者已经删除了它。从那以后,我一直在毫无问题地使用 RequireJS。 require-kiss 的作者写了 pakmanagerpakman 。完全披露,我与开发人员合作。

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

原文由 beatgammit 发布,翻译遵循 CC BY-SA 4.0 许可协议

我意识到可能有初学者希望组织他们的代码。现在是 2022 年,如果你正在考虑模块化 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>

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

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

printHello();

  1. 创建示例 print-hello.js 模块:
 module.exports = function() {
    console.log('Hello World!');
}

  1. 创建一个 <project-root>/webpack.config.js 并复制粘贴以下内容:
 var path = require('path');

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

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

  • 条目 app.js 是您编写 JS 代码的地方。它将导入其他模块,如上所示。
  • 输出 _bundle.js 是 webpack 生成的最终包。这是您的 html 最后将看到的内容。
  1. 打开你的 package.json ,并用以下命令替换 scripts
   "scripts": {
    "start": "webpack --mode production -w"
  },

  1. 最后运行脚本 watch app.js 并通过运行生成 _bundle.js 文件: npm start
  2. 享受编码!

原文由 Ilyas Assainov 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏