Electron database handling - javascript

I am trying to write a small app with Electron that needs a database. Currently I'm testing PouchDB, but that shouldn't really matter.
For better code quality I created a class that is going to handle the common database requests - it should be the only way to access the db.
Not sure, if I understood the main/renderer process concept correctly, but I think the main process should take care about db access. So this is my current configuration:
main.js
import Database from './database'
export const myDB = new Database()
database.js (obviously only a stub)
export default class Database {
hello = () => {
console.log("Hello World")
}
}
Root.js (one of the ui components [using react])
const remote = require('electron').remote
const main = remote.require('./main.js')
...
<button onClick={() => main.myDB.hello()}>Test</button>
My question: Is this a feasible solution for code structuring or am I getting something completely wrong? My JS experiences are just using some jQuery effects and Node experience is missing completely. This is just a small hobby project, so I just wanted to start coding ;)

You have it at the right end, the database related code should be executed in the main process.
main.js is what would be the main process, but it seems to be missing the code that creates a browser window (which in turn creates the renderer process). Take a look at the example of Electron here, the magic happens at createWindow().
Root.js is executed in the renderer process, it can only communicate with the main process through 'remote' or 'ipcRenderer' - the latter being a bit more secure. A bit more information about remote can be found on electron.rocks. You are doing it the right way, in terms of code structure.
The main process is responsible for creating and managing BrowserWindow instances and various application events. It can also do things like register global shortcuts, create native menus and dialogs, respond to auto-update events, and more. Your app’s entry point will point to a JavaScript file that will be executed in the main process. A subset of Electron APIs (see graphic below) are available in the main process, as well as all node.js modules. The docs state: “The basic rule is: if a module is GUI or low-level system related, then it should be only available in the main process.”
^Quoted from somewhere

Related

How to share class definitions between Electron's main and renderer process?

I would like to optimize the inter process communication of my Electron application by using arguments based on classes. For example: I would like to tell the renderer process to display a certain image together with additional information that my main process has fetched from some file (or something like that). I would then create an instance of a class such as
class structuredArgument {
var base64image;
var additionalInformation1;
var additionalInformation2;
[...]
}
let instanceOfStructuredArgument = new structuredArgument();
I would then send that instance to the renderer process
event.reply('display-image', instanceOfStructuredArgument);
If I were able to share the class definition above between the main and the renderer process, I could create an instance of it in the renderer process like this
let instanceOfStructuredArgument = Object.assign(new structuredArgument(), arg);
This would allow me to check whether the argument is actually valid, to use the class' properties in a comfortable way, etc.
The problem is, however: I can include "classDefinitions.js" in the renderer process with a script tag in my index.html. Since the main process is "node based" I need to "export" my class definitions
module.exports.structuredArgument = structuredArgument, etc.)
Unfortunately, this "module.exports" statement is invalid from the renderer process' perspective ("Uncaught ReferenceError: module is not defined").
Is there a "right" and well working "best practice" way of purposely sharing class definitions by the main and the renderer process of an Electron app to avoid redundancy and ensure that both processes are using the same class definitions?
Thank you very much for your support!

Best way to organise back end (Node) processes and front end (Vue / Nuxt) that uses part of these processes

I have a few tiny node apps doing some basic stuff like checking things and filling my DB (triggered by CRON). In my Nuxt app I will need to use part of what is insinde these Node apps. What is the best way to organise it, do I keep them separated or do I fuse them with my Nuxt app ? Do I copy what I need from these node apps and adapt it in Nuxt, do I use the serverside middlewares to add those node apps inside my Nuxt project or do I create my Nuxt app with express and I use /server/index.js to add my node apps there in some way ?
Let's take an example. You have a node app that check very hour some data and fill a DB. In the Nuxt app you have a page showing the content of the DB but you want first to be sure that nothing new has to be added in the DB since the last hour. The code I would have to run in th every Nuxt page is the same code as the Node app (check and fill the DB). It looks a bit stupid (and hard to maintain and update) to have twice the same code at two places. But I 'm not sure how would I have this node app running every hour in my Nuxt app. Any advice would be greatly appreciated
Here is a control flow that may help your thinking about designing this CRON microservice. There are many ways to do this, and this may not be the best approach, but I think it will work for your use case.
Have a services directory in your server (can also be called middleware).
Include a cron.js file that contains the logic for the task runner.
Within cron.js, issue a scheduled response from node to Vue, such as a JSON keyword like res.JSON({message: 'checkNewData'}). This will be something called a "server sent event". A server sent event is simply an event that happens autonomously on a defined schedule within node environment.
In Vue, at the root level App.vue, use the created() hook to register an event listener that will listen for the server sent "checkNewData" JSON object. When this event listener hears the JSON response, it should trigger Vue to check the appropriate component, package up any new data, and send it down to the DB in a post or put http call, depending on whether you're adding new data, or replacing the old with the new.
This configuration would give you a closed-loop system for automatic updates. The next challenge would be making this operation client-specific, but that is something to worry about once you got this working. Again, others may have a different approach to this, but this is how I would handle the flow.

How to manage a fully separate context with nodejs?

I am writing a javascript test framework based on nodejs. My server reads javacript files, instruments them, then executes them in its own context.
It (very) basically looks like this:
const file = process.argv[2];
require('fs').readFile(
file,
'utf-8',
(error, data) => {
eval(data);
}
);
This is all working fine but I do not like mixing my server context with a test context. How can nodejs execute javascript code in a totally separate context?
Ideally, it would be something like this:
other_context.eval(data);
Many thanks for your help!
There are multiple ways of doing this. The easiest thing that you could try right now is to replace the file read with child_process#fork().
This means you are running in a totally separate process which is good and that you don't need eval() which is also very good.
Essentially:
const {
fork
} = require('child_process');
const child = fork(file);
child.on("message", m => console.log(m));
The main thing is to get the code that you are testing out of the server. I just think terrible things can happen if you leave it that way.
Another option that is too broad to cover is to leverage Docker. That way, the code that gets executed is not only in another process, it's (and this is painting really broadly) practically on another computer.
isolated-vm might fit the bill for you.
isolated-vm is a library for nodejs which gives you access to v8's Isolate interface. This allows you to create JavaScript environments which are completely isolated from each other. You might find this module useful if you need to run some untrusted code in a secure way. You may also find this module useful if you need to run some JavaScript simultaneously in multiple threads. You may find this project very useful if you need to do both at the same time!

Can I send a React component to the client while doing Server Side Rendering?

I have a Reactjs application built on a Node/Express server. I am doing server side rendering via something like:
route.js
var Group = require('./react/component/groups');
var props = {foo: 'bar'};
var groupHtml = React.renderToString(Group(props));
res.render('index.ejs', {
reactOutput: groupHtml,
jsonProps: JSON.stringify(props),
start: 'lessonlist'
});
index.ejs
<div id="react-main-mount"><%- reactOutput %></div>
<script id="props" type="application/json"><%- jsonProps %></script>
<script src="/js/<%= start %>.js"></script>
This works really great! But here is my problem:
One of my pages/components will have a child component. But this child component can be one of 50+ different components.
I assume I could Require every single component, even though only one will be used. This seems like a bad idea since my main.js file will be huge.
I tried sending it via a prop and JSON.stringify. This works on the server rendering to HTML, but this doesn't work on the client side because JSON.stringify can't stringify a react component.
I though I might be able to do an API call and return it, but same problem as above.
Is there any way to dynamically require something, say based off a variable like require('components/' + this.props.foo) after the I've browserified/reactified?
Any suggestions/answers would be greatly appreciated
Browserify had always been too bulky for me, so I did my research and found RequireJS. It allowed me to require other files on the client just like how Node does it.
It was difficult for me to get started with Require, but once I got it working, everything just seemed easier. See this example I wrote in CoffeeScript.
Remember to have below code at the top of every isomorphic component so you don't stumble upon the problem I had with Node not understanding the keyword define.
if typeof define != 'function'
define = require('amdefine')(module)
define (require) ->
Above code is written in coffeescript.
Let me know if more information is needed.
Webpack allows you to do asynchronous bundle loading. This is intended for single page applications, where you don't want to have to include all of your javascript files until the user actually navigates to the "page" where they're needed. This allows you to fetch javascript with ajax dynamically. Check out the section titled 9. Async loading in this wonderful guide to Webpack
The implementation looks something like this...
if (window.location.pathname === '/feed') {
showLoadingState();
require.ensure([], function() { // this syntax is weird but it works
hideLoadingState();
require('./feed').show(); // when this function is called, the module is guaranteed to be synchronously available.
});
} else if (window.location.pathname === '/profile') {
showLoadingState();
require.ensure([], function() {
hideLoadingState();
require('./profile').show();
});
}
If you don't want to use Webpack, you could potentially just fetch the components with ajax as plain text and eval it upon arrival. This is essentially what the browser is doing with script tags under the hood.

ReactJS server-side rendering vs client-side rendering

I just have began to study ReactJS and found that it gives you 2 ways to render pages: server-side and client-side. But, I can't understand how to use it together. Is it 2 separate ways to build the application, or can they be used together?
If we can use it together, how to do it - do we need to duplicate the same elements on the server side and client side? Or, can we just build the static parts of our application on the server, and the dynamic parts on the client side, without any connection to the server side that was already pre-rendered?
For a given website / web-application, you can use react either client-side, server-side or both.
Client-Side
Over here, you are completely running ReactJS on the browser. This is the simplest setup and includes most examples (including the ones on http://reactjs.org). The initial HTML rendered by the server is a placeholder and the entire UI is rendered in the browser once all your scripts load.
Server-Side
Think of ReactJS as a server-side templating engine here (like jade, handlebars, etc...). The HTML rendered by the server contains the UI as it should be and you do not wait for any scripts to load. Your page can be indexed by a search engine (if one does not execute any javascript).
Since the UI is rendered on the server, none of your event handlers would work and there's no interactivity (you have a static page).
Both
Here, the initial render is on the server. Hence, the HTML received by the browser has the UI as it should be. Once the scripts are loaded, the virtual DOM is re-rendered once again to set up your components' event handlers.
Over here, you need to make sure that you re-render the exact same virtual DOM (root ReactJS component) with the same props that you used to render on the server. Otherwise, ReactJS will complain that the server-side and client-side virtual DOMs don't match.
Since ReactJS diffs the virtual DOMs between re-renders, the real DOM is not mutated. Only the event handlers are bound to the real DOM elements.
Image source: Walmart Labs Engineering Blog
NB: SSR (Server Side Rendering), CSR (Client Side Rendering).
The main difference being that with SSR, the servers response to the clients browser, includes the HTML of the page to be rendered.
It is also important to note that although, with SSR, the page renders quicker. The page will not be ready for user interaction until JS files have been downloaded and the browser has executed React.
One downside is that the SSR TTFB (Time to First Byte) can be slightly longer. Understandably so, because the server takes some time creating the HTML document, which in turn increases the servers response size.
I was actually wondering the same researching quite a bit and while the answer you are looking for was given in the comments but I feel it should be more prominent hence I'm writing this post (which I will update once I can come up with a better way as I find the solution architecturally at least questionable).
You would need to write your components with both ways in mind thus basically putting if switches everywhere to determine whether you are on the client or the server and then do either as DB query (or whatever appropriate on the server) or a REST call (on the client). Then you would have to write endpoints which generate your data and expose it to the client and there you go.
Again, happy to learn about a cleaner solution.
Is it 2 separate ways to build the application, or can they be used together?
They can be used together.
If we can use it together, how to do it - do we need to duplicate the
same elements on the server side and client side? Or, can we just
build the static parts of our application on the server, and the
dynamic parts on the client side, without any connection to the server
side that was already pre-rendered?
It's better to have the same layout being rendered to avoid reflow and repaint operations, less flicker / blinks, your page will be smoother. However, it's not a limitation. You could very well cache the SSR html (something Electrode does to cut down response time) / send a static html which gets overwritten by the CSR (client side render).
If you're just starting with SSR, I would recommend start simple, SSR can get very complex very quickly. To build html on the server means losing access to objects like window, document (you have these on the client), losing ability to incorporate async operations (out of the box), and generally lots of code edits to get your code SSR compatible (since you'll have to use webpack to pack your bundle.js). Things like CSS imports, require vs import suddenly start biting you (this is not the case in default React app without webpack).
The general pattern of SSR looks like this. An Express server serving requests:
const app = Express();
const port = 8092;
// This is fired every time the server side receives a request
app.use(handleRender);
function handleRender(req, res) {
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
console.log('fullUrl: ', fullUrl);
console.log('req.url: ', req.url);
// Create a new Redux store instance
const store = createStore(reducerFn);
const urlToRender = req.url;
// Render the component to a string
const html = renderToString(
<Provider store={store}>
<StaticRouter location={urlToRender} context={{}}>
{routes}
</StaticRouter>
</Provider>
);
const helmet = Helmet.renderStatic();
// Grab the initial state from our Redux store
const preloadedState = store.getState();
// Send the rendered page back to the client
res.send(renderFullPage(helmet, html, preloadedState));
}
My suggestion to folks starting out with SSR would be to serve out static html. You can get the static html by running the CSR SPA app:
document.getElementById('root').innerHTML
Don't forget, the only reasons to use SSR should be:
SEO
Faster loads (I would discount this)
Hack : https://medium.com/#gagan_goku/react-and-server-side-rendering-ssr-444d8c48abfc

Categories