Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of require(lib) versus <script> in Electron apps

I don't have a handle on when to use require('jslib') versus <script src=""></script> in Electron content pages (e.g. index.html). With jQuery, I discovered that it needs to be loaded as follows:

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

I need to start using some other libraries (e.g. Handlebars, ds3.js, Bootstrap, etc.) and I am not sure if I should be loading those with the <script> tag or if I should require them.

like image 618
Web User Avatar asked Jun 09 '16 21:06

Web User


People also ask

Is it safe to use require () in Electron apps?

I hope this answer gets some attention, because a large majority of answers here leave large security holes in your electron app. In fact this answer is essentially what you should be doing to use require () in your electron apps. (There is just a new electron API that makes it a little bit cleaner in v7).

Why can't I use renderer modules in electron?

This is not the case in Electron. Each Renderer process is isolated, and its modules will have their own state. In other words, you can’t use modules for sneaky inter-process communication (we have other things for that). The require ('electron') module is a built-in, but we can require local modules in the file system too.

Does electron search for modules in the file system?

The require ('electron') module is a built-in, but we can require local modules in the file system too. As far as I can tell, Electron searches for modules in the same way Node.js does. But relative to what starting filepath? If you use loadFile, modules seem to be resolved relative to the loaded file.

How to install electron on Linux?

Create a file called main.js under the public folder. Copy the code given below to the main.js file. We’ll come back to what it does in some time. With that done, open up your package.json file. Add the main entry that holds the path pointing to the main.js file, as shown below. Now we are ready to install Electron, open up the terminal, and run:


2 Answers

Some libraries only expose their variables through a CommonJS interface. Others, like jQuery, will also expose them as global variables.

The reason you can't just do <script src="..."></script> for a library that only exposes through CommonJS is that it won't bind to the global space.

Binding with CommonJS

module.exports = myLibrary;

Bindings to the global scope

window.myLibrary = myLibrary;

If a library only does the former then you will not be able to access the value without using require. If a library only does the latter, then you will not be able to access it with require in the sense of const myLibrary = require('my-library')

In general, it's a better idea to use CommonJS over global variables. Adding variables to the global scope can lead to name collisions and directly loading in your dependencies makes it easier for the next person to tell where that dependency came from. Not to mention, CommonJS allows static analysis tools to work better so you're more likely to get relevant code completions and type definitions.

Using the example of jQuery, it would be better to use it like this.

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

Use require('my-library') when possible, load them as globals when it is not.

like image 192
Mike Cluck Avatar answered Sep 23 '22 18:09

Mike Cluck


Before module bundlers, libraries would have to be imported either via a <script> tag or via module loaders such as RequireJS.

Now it's easier to assume a CommonJS environment and get everything through a module bundler which will expose a require function for you in a browser context.

All of this is not necessary in the context of an Electron app:

In normal browsers, web pages usually run in a sandboxed environment and are not allowed access to native resources. Electron users, however, have the power to use Node.js APIs in web pages allowing lower level operating system interactions.

Cf. renderer process

That means that the native Node.js require function (amongst other things) is available in your renderer process!

Here's a simple Electron app to prove it:

My 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"
  }
}

My main.js: (the main process)

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

let mainWindow;

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

app.on('ready', createWindow);

My index.html: (the renderer process)

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

enter image description here

So which method should you use?

Electron exposes the native Node.js require function. It would be a shame not to leverage this: you would be able to require packages by their names and split your code into reusable modules as you would do in any Node.js apps.

like image 36
customcommander Avatar answered Sep 26 '22 18:09

customcommander