Looking to better understand the way to approach my desired goal. Building an electron application that will perform processor intense tasks. I would like to utilize multithreaded design using the approach of creating a hidden BrowserWindow() for each task.
I am currently using electron-webpack and webpack-dev-serve for development. I am having limited success at the moment. What would be the best/cleanest way to have the following architecture that runs both in development and production mode.
Desired Architecture
I currently have main.js and renderer.js working well. Now I am attempting to run additional BrowserWindows that will perform more processor intensive task, but I am not sure on how to get this working. I did find a good example here of electron background processing, but this does not involve using electron-webpack and webpack-dev-serve.
I was thinking to have my src code like this
src/common/task1/
- task1.html
- task1.js
src/common/task2/
- task2.html
- task2.js
In my main.js (production) I would have:
let bg = new BrowserWindow({ show: false })
bg.loadURL(url.format({
pathname: path.join(__dirname, 'common/task1/task1.html'),
protocol: 'file',
slashes: true
}))
currently, I can see common/* bundled in my app.asar. However, it does not seem to load the task1.html file. I have the BrowserWindow set show: true. So I do see the window and I don't see any errors. However, my <h1> tag to prove the html is loaded is not showing in the window. I don't need any HTML to display, because the window should be hidden and I only wish to use the window to run processor intensive javascript code.
Related
To begin, I would just like to thank you for taking the time to read this post. I would also like to mention that I took the time to read and try to understand most of the exchanges that are made on the subject. Example here : I also took the time to read the "Ultimate Electron Guide" created by reZach at [https://www.debugandrelease.com/the-ultimate-electron-guide/]. I understand the theory behind "electron main process access to require, and anytime our renderer process needs to use require, marshal a request to the main process." ... I took the time to analyze several code examples, I took the time to read the tutorial on preload script here https://www.electronjs.org/docs/latest/tutorial/tutorial-preload but despite all that, I can't adjust an extremely simple code.
Here is my problem, very simple though, but I'm too stupid to find the solution ;). I had no problem to run this code with an Electron versions below v12, but since the adjustment of the security of the nodeintegration, I can't do it anymore. So basically,
in my main.js I create a "browserwindow", standard, with nothing spécial
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
}
});
in my html file, I simply have this line
<script src="js/client.js"></script>
in my client.js I have
let net;
net = require('net');
this.soc = new net.Socket();
How to make so that the module "net" is imported ? ... I know it should be simple though, but I tried a lot of things with a preload.js, a renderer.js, but no way i'm able to make this simple code work without the error "Electron require() is not defined". Someone would be kind enough to help me ? Everything works fine with versions below 12, but I want to adjust to new versions of Electron
I was trying to run some tests, but needed test data, so i created a generation file which created dummy html. When I attempt to run it though, it gives me a Reference Error: HTMLDivElement is not defined.
Is there something I need to import such that Node knows what HTMLDivElement is? I am not rendering anything, but just want correct data to pipe into follow on code.
I run my file through TSC, and then run it through node.
Sample Code:
const main = () => {
let root = new HTMLDivElement();
}
main();
Edit:
I was trying to just bypass it with: let root = document.createElement("div"); but node does not understand what document is, so I cant seem to get that running either as a fallback.
Indeed, Node.js doesn't come with a DOM implementation. If you want to run tests that use the DOM, you'll need to either load a Node.js-compatible DOM implementation such as jsdom, or if that doesn't meet your requirements, switch to a browser-based testing environment such as Selenium.
I am working on a very old Nodejs application which creates a new child process using forever-monitor. The logs of this child process are taken care by forever-monitor only. This is how the configuration looks like:
var child = new (forever.Monitor)(__dirname + '/../lib/childprocess.js', {
max: 3,
silent: true,
options: [program.port],
'errFile': __dirname + '/../childprocess_error.log',
'outFile': __dirname + '/../childprocess_output.log'
}
);
Everything is working fine in this setup. The new requirement is to rotate these logs every 12 hours. That is every 12 hours a new file will be created which will have all the content of this file childprocess_output.log and should be stored in some other directory. The new log file will obviously have the timestamp appended at the end of the name (eg: childprocess_output_1239484034.log).
And the original file childprocess_output.log should be reset, that is all its content should be deleted and it should start logging from fresh.
I am trying to understand which npm library should I used for this purpose. I googled a bit and found a few of the npm libraries which matches my requirement, but the number of downloads for these libraries was really small, so I doubt the reliability of those libraries.
Which library NodeJs developers use for log rotation?
Also, my last resort would be to use the Linux tool Logrotate if I couldn't find any appropriate library in Node. I am avoiding using Logroate because I want my application to handle the scenario and not depend on the instance configuration.
you can use :
fs (the file system library) handled with methods like statSync and renameSync coupled with try-catches block-codes.
I am currently building an electron app. I have a PDF on my local file system which I need to silently print out (on the default printer). I came across the node-printer library, but it doesn't seem to work for me. Is there an easy solution to achieve this?
Well first of all it is near impossible to understand what you mean with "silent" print. Because once you send a print order to your system printer it will be out of your hand to be silent at all. On Windows for example once the order was given, at least the systemtray icon will indicate that something is going on. That said, there are very good described features for printing with electron even "silent" is one of them:
You need to get all system printers if you do not want to use the default printer:
contents.getPrinters()
Which will return a PrinterInfo[] Object.
Here is an example how the object will look like from the electron PrtinerInfo Docs:
{
name: 'Zebra_LP2844',
description: 'Zebra LP2844',
status: 3,
isDefault: false,
options: {
copies: '1',
'device-uri': 'usb://Zebra/LP2844?location=14200000',
finishings: '3',
'job-cancel-after': '10800',
'job-hold-until': 'no-hold',
'job-priority': '50',
'job-sheets': 'none,none',
'marker-change-time': '0',
'number-up': '1',
'printer-commands': 'none',
'printer-info': 'Zebra LP2844',
'printer-is-accepting-jobs': 'true',
'printer-is-shared': 'true',
'printer-location': '',
'printer-make-and-model': 'Zebra EPL2 Label Printer',
'printer-state': '3',
'printer-state-change-time': '1484872644',
'printer-state-reasons': 'offline-report',
'printer-type': '36932',
'printer-uri-supported': 'ipp://localhost/printers/Zebra_LP2844',
system_driverinfo: 'Z'
}
}
To print your file you can do it with
contents.print([options])
The options are descriped in the docs for contents.print():
options Object (optional):
silent Boolean (optional) - Don’t ask user for print settings. Default is false.
printBackground Boolean (optional) - Also prints the background color and image of the web page. Default is false.
deviceName String (optional) - Set the printer device name to use. Default is ''.
Prints window’s web page. When silent is set to true, Electron will pick the system’s default printer if deviceName is empty and the default settings for printing.
Calling window.print() in web page is equivalent to calling webContents.print({silent: false, printBackground: false, deviceName: ''}).
Use page-break-before: always; CSS style to force to print to a new page.
So all you need is to load the PDF into a hidden window and then fire the print method implemented in electron with the flag set to silent.
// In the main process.
const {app, BrowserWindow} = require('electron');
let win = null;
app.on('ready', () => {
// Create window
win = new BrowserWindow({width: 800, height: 600, show: false });
// Could be redundant, try if you need this.
win.once('ready-to-show', () => win.hide())
// load PDF.
win.loadURL(`file://directory/to/pdf/document.pdf`);
// if pdf is loaded start printing.
win.webContents.on('did-finish-load', () => {
win.webContents.print({silent: true});
// close window after print order.
win = null;
});
});
However let me give you a little warning:
Once you start printing it can and will get frustrating because there are drivers out there which will interpret data in a slightly different way. Meaning that margins could be ignored and much more. Since you already have a PDF this problem will most likely not happen. But keep this in mind if you ever want to use this method for example contents.printToPDF(options, callback). That beeing said there are plently of options to avoid getting frustrated like using a predefined stylesheet like descriped in this question: Print: How to stick footer on every page to the bottom?
If you want to search for features in electron and you do not know where they could be hidden, all you have to do is to go to "all" docs and use your search function: https://electron.atom.io/docs/all/
regards,
Megajin
I recently published NPM package to print PDF files from Node.js and Electron. You can send a PDF file to the default printer or to a specific one. Works fine on Windows and Unix-like operating systems: https://github.com/artiebits/pdf-to-printer.
It's easy to install, just (if using yarn):
yarn add pdf-to-printer
or (if using npm):
npm install --save pdf-to-printer
Then, to silently print the file to the default printer you do:
import { print } from "pdf-to-printer";
print("assets/pdf-sample.pdf")
.then(console.log)
.catch(console.error);
To my knowledge there is currently no way to do this directly using Electron because while using contents.print([]) does allow for 'silently' printing HTML files, it isn't able to print PDF views. This is currently an open feature request: https://github.com/electron/electron/issues/9029
Edit: I managed to work around this by converting the PDF to a PNG and then using Electron's print functionality (which is able to print PNGs) to print the image based view. One of the major downsides to this is that all of the PDF to PNG/JPEG conversion libraries for NodeJS have a number of dependencies, meaning I had to implement them in an Express server and then have my Electron app send all PDFs to the server for conversion. It's not a great option, but it does work.
I'm new to web development and I'm currently in the process of building my own website for my portfolio. My app uses node, express, and Heroku to launch it online. However, the page isn't as smooth as I'd like it to be. It drops a lot of frames when scrolling and viewing animations. I'm wondering what I can do to make my app feel buttery smooth. I've looked all around for solutions but I'm too new to development to really understand what to do. I've attempted to use the inspector to see if the css or javascript files are slowing down the processes via the waterfall insepctor, but came up dry. So far, I've compressed the files and lowered the scale of all images. Also, the entire website is static content so I can't imagine why its running so slowly. Any help would be much appreciated.
The website in question
The "lag" could be caused by the ScrollFire plugin. Every time you call Materialize.scrollFire(..) you actually add a JavaScript listener for the "scroll" event. The way you use it, you call Materialize.scrollFire for each of your target objects, so you actually create multiple "scroll" listeners. But the scrollFire options is actually an array of targets, so you could get away with only initializing it once. Like so:
var options = [
{selector: '.iphone1', offset: 300, callback: function(el) {
$('.iphone1').css('visibility', 'visible');
$('.iphone1').addClass('animated slideInLeft');
}},
{selector: '#paragraph_intro', offset: 300, callback: function(el) {
$('#paragraph_intro').css('visibility', 'visible');
$('#paragraph_intro').addClass('animated slideInRight');
}},
// ... And so on
];
Materialize.scrollFire(options);
It could also be caused by your own scroll listener at:
$(window).on('scroll', function(){
updateNavigation();
changeNavColor();
changeHeaderColor();
});
I would consider adding some kind of throttling, so these functions are called less frequent while the user is scrolling.
These may not be the problem, or the whole problem, as I cannot see how the page would behave without it, but it could have an impact, so it's worth investigating.