在 Electron 应用程序中使用 require(lib) 与 <script>

Posted

技术标签:

【中文标题】在 Electron 应用程序中使用 require(lib) 与 <script>【英文标题】:Use of require(lib) versus <script> in Electron apps 【发布时间】:2016-10-10 17:57:51 【问题描述】:

我不知道何时在 Electron 内容页面(例如 index.html)中使用 require('jslib')&lt;script src=""&gt;&lt;/script&gt;。使用jQuery,我发现需要按如下方式加载:

<script>window.$ = window.jQuery = require('./js/jquery-2.2.4.min.js');</script>

我需要开始使用其他一些库(例如 Handlebars、ds3.js、Bootstrap 等),我不确定是否应该使用 &lt;script&gt; 标记加载这些库,或者是否应该使用 require 它们。

【问题讨论】:

这完全取决于库。如果库可以通过 CommonJS (module.exports = ...) 公开,那么您将不得不 require 它。否则,一个简单的&lt;script src="..."&gt;&lt;/script&gt; 就可以了。 @MikeC 即使 JS 脚本文件不使用 CommonJS,require 似乎也可以工作。这是否意味着我通常可以使用require 代替&lt;script src="..."&gt;&lt;/script&gt;?尽管我问了这个问题,但我认为我应该查看 JS 文件以确定何时使用其中一个。 一般来说,你可以侥幸逃脱,是的。 @MikeCluck 为什么你说你必须要求它如果它是通过CommonJS公开的? &lt;script src="..."&gt;&lt;/script&gt; 不应该仍然有效吗?那么require 怎么能正常工作呢?这个问题值得回答…… 【参考方案1】:

一些库仅通过 CommonJS 接口公开其变量。其他的,比如 jQuery,也会将它们暴露为全局变量。

您不能只为仅通过 CommonJS 公开的库执行 &lt;script src="..."&gt;&lt;/script&gt; 的原因是它不会绑定到全局空间。

与 CommonJS 绑定

module.exports = myLibrary;

绑定到全局范围

window.myLibrary = myLibrary;

如果一个库只做前者,那么您将无法在不使用require 的情况下访问该值。如果图书馆只做后者,那么您将能够在const myLibrary = require('my-library') 的意义上使用require 访问它

一般来说,在全局变量上使用 CommonJS 是一个更好的主意。将变量添加到全局范围可能会导致名称冲突,并且直接加载依赖项可以让下一个人更容易判断该依赖项的来源。更不用说,CommonJS 允许静态分析工具更好地工作,因此您更有可能获得相关的代码完成和类型定义。

使用jQuery的例子,这样使用会更好。

// main.js
const $ = require('./js/jquery-2.2.4.min.js');
// could also be done like this if you install it as a Node dependency
// const $ = require('jquery');

$(document).ready(...);

<!-- index.html -->
...
<script src="main.js"></script>

TL;DR

尽可能使用require('my-library'),如果不是,则将它们作为全局变量加载。

【讨论】:

这是一篇很棒的帖子,但我认为它没有解决房间里的大象问题,这就是为什么 require 在 Electron 应用程序中完全可用?在任何普通的 Web 应用程序中,require 不存在,必须使用模块加载器/捆绑器来填充。在 Electron 应用程序中,您可以轻松使用本机 require @customcommander 我不认为这是一头大象,因为所有 Electron 文档都表明它可以让您以与 Node 相同的方式访问模块,即通过 CommonJS 格式。 好吧,你可能是对的。我只是认为值得一提,因为这个问题特别提到了电子上下文。谢谢你的澄清。【参考方案2】:

在模块捆绑器之前,库必须通过&lt;script&gt; 标签或模块加载器(例如RequireJS)导入。

现在更容易假设 CommonJS 环境并通过模块捆绑器获取所有内容,该模块捆绑器将在浏览器上下文中为您公开 require 函数。

在 Electron 应用程序的上下文中,所有这些都不是必需的:

在普通浏览器中,网页通常在沙盒环境中运行,并且不允许访问本机资源。但是,Electron 用户可以在网页中使用 Node.js API,从而实现较低级别的操作系统交互。

参见。 renderer process

这意味着原生 Node.js require 函数(除其他外)在您的渲染器进程中可用!

这是一个简单的 Electron 应用程序来证明这一点:

我的package.json


  "name": "foobar",
  "version": "1.0.0",
  "main": "main.js",
  "scripts": 
    "start": "electron ."
  ,
  "devDependencies": 
    "electron": "^3.0.7"
  ,
  "dependencies": 
    "the-answer": "^1.0.0"
  

我的main.js:(主进程)

const app, BrowserWindow = require('electron');

let mainWindow;

function createWindow () 
  mainWindow = new BrowserWindow(width: 800, height: 600)
  mainWindow.loadFile('index.html');


app.on('ready', createWindow);

我的index.html:(渲染器进程)

<!DOCTYPE html>
<html>
  <body>
    <script>
      const os = require('os'); // Standard Node.js module
      const answer= require('the-answer'); // An NPM package that returns the answer to everything.
    </script>
    <button onclick="alert(os.platform())">YOUR PLATFORM</button>
    <button onclick="alert(answer)">THE ANSWER</button>
  </body>
</html>

那么你应该使用哪种方法呢?

Electron 公开了原生 Node.js require 函数。不利用这一点将是一种耻辱:您可以按名称要求包,并将您的代码拆分为可重用的模块,就像在任何 Node.js 应用程序中所做的那样。

【讨论】:

这并不能解释为什么他们会在脚本标签上使用require,反之亦然。 公平。我提供了一些额外的信息。但是考虑到 OP 提到了 Electron,实际上很重要的是要提到本机 require 函数可用,并且某些模块加载器或捆绑器没有提供它。 进一步编辑此内容以阐明我对使用哪些方法的立场。

以上是关于在 Electron 应用程序中使用 require(lib) 与 <script>的主要内容,如果未能解决你的问题,请参考以下文章

将 node require 与 Electron 和 Webpack 一起使用

electron 中renderer.js中使用require('electron') 报错require is not defined

来自 Electron 渲染器进程的 require() 节点模块,通过 HTTP 提供服务

require 没有在带有 ipcRenderer.on 的 Electron-React-Webpack-Typescript 应用程序中定义

如何在 Electron 上使用带有 TypeScript 类型支持的 require 内部函数或条件?

在 Electron 应用程序中使用 console.log()