How to export a require assigned to a variable? - javascript

I'm doing the following to make this require to become visible in <app></app>
index.html:
<script>
var electron = require('electron')
</script>
<app></app>
<script src="bundle.js"></script>
App.vue:
const ipc = electron.ipcRenderer
console.log(ipc)
But I get un-used and un-defined var errors with ESLint, so I decided to do this:
requires.js:
var electron = require('electron')
exports.electron = electron
index.html:
<script src="requires.js"></script>
</head>
<body>
<app></app>
<script src="bundle.js"></script>
But now I get this error: requires.js:3 Uncaught ReferenceError: exports is not defined.
What the correct way to export and import the electron require?
Note: requiring electron directly in App.vue doesn't work. You can only require electron in index.html
Full example: https://github.com/alexcheninfo/vue-electron-simple

What you seem to be trying to do here is define electron as a global variable; for that to work you can set window.electron = require('electron') in your index.html in the first example. (It will be available in you bundle.js)
However, using globals for this bad practice and not necessary. What you should do, is just use require in your code. You say this doesn't work: the reason why it doesn't is probably that you're using webpack or something similar to create bundle.js. Furthermore, you probably run the bundling process in Node and not in Electron, therefore require('electron') does not work as expected. Note that it works in your index.html which is not part of the bundle.
If you want to continue to use this setup, you could rename Electron's require to distinguish between the require resolved during bundling and the require resolved at runtime. In other words, window.electronRequire = require in the script tag of index.html and then use electronRequire('electron') in your code.
Having said that, why bundle everything in the first place? Electron has full Node integration so you can use regular Node modules; the files are not sent via HTTP either so there is little to gain from bundling everything into one file.

Related

In nwjs DOM seems to be empty when accessed from another module

I want to use modules in my nwjs app that use document, but it seems that they cannot properly access DOM of the main page.
Below you can find a simple test that shows the problem.
I have next files:
package.json
...
"main": "index.html"
...
index.html
<html>
<head>
<meta charset="utf-8" />
<title>test</title>
</head>
<body>
<div id="container_model_view" class="brd"></div>
<script>let exports = {};</script>
<script src="./main.js"></script>
</body>
</html>
main.ts (compiled into main.js before run)
import {getEl} from './mod_test';
console.log(document.getElementById("container_model_view"));
console.log(getEl());
mod_test.ts
export function getEl() {
return document.getElementById("container_model_view");
}
Output:
div#container_model_view.brd //access from main.ts - ok
null //access from mod_test.ts - fail
I found that I can bundle my main.js with rollup or webpack then it will work because the main module and the 'mod_test' module are merged into a single file. But I don't like that approach as I afraid it would impact the performance, not to mention it seems to be really unnecessary additional step in the assembling.
As it turned out, document pointing to the main page of the app exists only in browser context. require() loads modules in node context. Apparently, there's no way to specify in what context you want to load your module, it always will be node. Some ways to stay in browser context while loading module are described in the docs as follow:
Scripts loaded or embedded by traditional web ways, such as using
<script> element or jQuery’s $.getScript() or RequireJS, are running
in browser context.
Unfortunately I couldn't find a way to use any of the above natively with typescript.
Try mixing your contexts, so you can access DOM elements from server context:
Type this in package.json:
"chromium-args": "--mixed-context"

How to compile require statements?

I have the following require statements in my .js file which gets transpiled from ES2017, however, the browser still does not recognize these commands (require is not defined). How can I solve this?
this.e = require('../../e.js'),
this.a = require('../../a.js'),
this.cb = require('../../cb.js'),
Transpiling your code is not enough to make it work in a browser. You will need a build system like webpack to bundle your code into one (or multiple) files that you can include in your web app.
For example webpack can first transpile your code using babel and then bundle your whole app into 1 file which will run in the browser without a problem (as it won't have any require anymore).
Another solution you can use is type="module" in your script tag:
<script type="module" src="/my/app.js"></script>
app.js
import a from "../../a.js";
...

Require is not working for node-opcua

I want to load a local version of node-opcua with 'require' inside a HTML file, but it does not really work. The code snippet is the following:
<script type="text/javascript" src="path_to_require.js"></script>
<script>
var opcua = require(["path_to_node-opcua"]); <!-- Yes, the path is correct >
var client = new opcua.OPCUAClient();
...
When I execute the script I get the following error in the console:
Uncaught TypeError: opcua.OPCUAClient is not a constructor
Hence, var opcua is loaded correctly, but OPCUACluent is not, although the class is declared in a file that is present in the node-opcua folder called opcua_client.js under node-opcua\lib\client\
Sources:
The 'require' script from http://requirejs.org/docs/download.html#requirejs.
The node-opcua folder with the console command
npm install node-opcua.
node-opcua is not intended to run inside a browser as it relies on nodejs specific features such as filesystem access, crypto and so on.
You need to use browserify if you want to use that module in client. You will also need to look at how to use browserify with file system access (it can be done if paths are known ahead of time).

sharing code from a browserify file

I have a JavaScript library that is using Browserify to keep the code modular.
The library itself uses basic Browserify functionality to require other JS files.
myLibrary.js
var utils = require('helpers/utils.js')
console.log("Hello, I am logging from myLibrary")
function my_api(){
utils.someFn()
}
I'm using Gulp to browserify myLibrary.js and it is being built correctly, I've put several logs into myLibrary.js and when I load the file in an example html file I can see the logs.
I have an example index.html file that uses myLibrary.js and I expect my_api to be accessible from index.html.
index.html
<script src="my_url/myLibrary.js"></script>
<script src="app.js"></script>
app.js
my_api()
Chrome console
Hello I am logging from myLibrary (myLibrary.js)
Uncaught ReferenceError: my_api is not defined (app.js)
I've tried to defer the loading of app.js until myLibrary.js was ready but I'm beginning that that is not the problem.
You need to export your public functions.
module.exports = {my_api: my_api};
The solution I ended up using was to expose one global object that contains all the methods I want to expose through myLibrary using the window object.
myLibrary.js is requiring a utility function file and using them as helpers in the methods that I want to expose.
myLibrary.js
var util = require("utils.js")
window.myGlobalObjWithAUniqueName = {
myFn: function(){
util.someHelper()
}
}
Then I use Browserify to create the new browserified_myLibrary.js and use its methods in any file I want to load it in.
index.html
<script src="browserified_myLibrary.js"></script>
<script src="app.js"></script>
app.js
myGlobalObjWithAUniqueName.myFn()
Not sure if this is the best way of doing this but this seems to suit my need to modularize a client side library and use it without having to use Browserify every time I use it.
You may also want to look into the --standalone option exposed by browserify:
When opts.standalone is a non-empty string, a standalone module is created with that name and a umd wrapper. You can use namespaces in the standalone global export using a . in the string name as a separator, for example 'A.B.C'. The global export will be sanitized and camel cased.
From https://github.com/substack/node-browserify#usage

Basic requirejs concept needed to make work musicjson package

I'd like to use the musicjson.js package that helps to convert musicXML files into json notation, looking if it's a good way to import for example exported musicXML Finale scores into a browser playing with the Fermata/VexFlow class.
https://github.com/saebekassebil/musicjson
The thing is that this module works with require (calling for
nodes packages like fs) and I'm just a newbee in requirejs...Even if I spent few time in understanding the tutorial in the website, I don't still get how to solve this kind of basic problem when the dependencies of my musicjson.js need to be called like :
var xmldom = require('flat-xmldom'),
fs = require('fs'),
path = require('path'),
util = require('util');
My index.php page does the classic require call:
<!DOCTYPE html>
<head>
<!-- javascript head -->
<!-- REQUIRE -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
</head>
<body>
</body>
</html>
In my scripts/main.js, I'd like to do simply what it is told from musicjon :
var music = require('musicjson');
music.musicJSON(xml, function(err, json) {
// Do something with the MusicJSON data
});
I putted also, in the same directory scripts/, the flat-xmldom folder, fs.js, path.js, util.js
When I do this, I've just obtain this classic error of :
*Error: Module name "musicjson" has not been loaded yet for context: _. Use require([])*
...That looks like a common error referenced in the requirejs website,
but if I try things that I guess it should be written, I get a bit lost to determine where is the fundamental conceptual mistake here :
require.config({
baseUrl: '/scripts/',
paths: {
flatxmldom:'./flat-xmldom/__package__',
fs: 'fs',
path:'path',
util:'util',
musicjson: 'musicjson'
}
});
require(['flatxmldom','fs','path','util','musicjson'],function(flatxmldom,fs,path,util,musicjson){})
Error returned in this case for example :
*Module name "fs" has not been loaded yet for context: _. Use require([])*
Thanks a lot for your attention.
So, this is not a RequireJS problem per-se. The package you want to use is a Node.js package. It is intended to run in node (a server/desktop execution environment for JavaScript). It cannot/will not run in web page in a browser.
The packages it is trying to use (fs in particular) provide access to system resources such as the file system. Node provides these packages as part of its core libraries to any package that runs in node. A browser is specifically designed for security reasons never to allow direct access to such resources to any code that run in the browser because who knows where it came from or might try to do.
I haven't really tried to do this myself, but browserify (alternative to requirejs) claims that it will allow you to use any node package in your application.
If musicjson is at the heart of what your app should achieve and requirejs is a small step on the way to getting there, you could try your luck with browserify instead.

Categories

Resources