Wednesday, September 16, 2020

Built a Desktop App with HTML, CSS and Javascript

 


Can HTML, CSS and Javascript really be used to build Desktop Applications?

The Answer is Yes 😄

In this Article we will be focussing mainly on how Electron can be used to create desktop applications with Web Technologies like HTML, CSS and Javascript



Electron

Electron can be used to build Desktop Apps with HTML, CSS and Javascript. Also these apps work for multiple platforms like Windows, Mac, Linux and so on.

Electron Combines Chromium and NodeJS into a single Runtime. This enables Us to run the HTML, CSS and Javascript Code as a desktop application.

Electron Forge

If Electron is used directly, then some manual setup is needed before building your application. Also if you want to use angular, react, vue or any other framework or library, you will need to manually configure for that.

Electron Forge makes the above things much easier.

It provides template applications with angular, react, vue and other frameworks. This avoids the extra manual setups needed.

Also it provides an easy way to build and package the application. It also provides many other features which can be found in their documentation.

Pre-requisites

Ensure you have NodeJS installed. It can be installed from here

Install Electron Forge Globally using the following command

npm install -g electron-forge

Let’s get started with the application

Use the following command to create your application

electron-forge init simple-desktop-app-electronjs

simple-desktop-app-electronjs is the name of the application

The above command will take some time to run.

Once it finishes running, Start the application using the following commands

cd simple-desktop-app-electronjs
npm start

This should open up a window like the one shown below



Understanding the Existing Folder Structure and Code

The application created has a folder structure. Here I will be mentioning some of the important things in this folder structure

package.json

It has information about the application you are creating, it has all the dependencies needed for the app and also it has some scripts. Some of the scripts are already pre configured and you can add new scripts as well.

The config.forge path has all the configurations which are specific to ElectronJS. For example make-targets is used specify the target make files for various platforms like Windows, Mac or Linux.

Also package.json has "main": "src/index.js" which indicates that src/index.js is the starting point of the application

src/index.js

According to package.json, index.js is the main script. The process which runs the main script is known as the Main Process. So Main Process runs the index.js script.

The main process is used to display GUI elements. It does this by creating Web Pages.

Each Web page created runs in a process called as renderer process

Main Process and Renderer process

The purpose of the Main Process is to create web pages using a Browser WindowInstance.

The BrowserWindow Instance uses a renderer process to run each Web page.

Each App can have only one Main Process but can have many renderer processes

It is possible to communicate between the main and the renderer process as well. This will not be covered in this article.


abcd.html is shown as a second webpage in the above architecture. But in our code we won’t be having a second web page.

src/index.html

index.js loads the index.html file into a new BrowerWindow Instance.

What this basically means is that, index.js creates a new GUI Window, and loads it with index.html web page. The index.html web page runs in its own renderer process.

Code in index.js explained

Most of the code created in index.js has good comments explaining what it does. Here I will mention a few key points to note in index.js

mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
  });

  // and load the index.html of the app.
  mainWindow.loadURL(`file://${__dirname}/index.html`);

The above code snippet basically creates a BrowserWindow Instance and loads index.html into the BrowserWindow.

You would see app used often in the code. For example take the below code snippet.

app.on('ready', createWindow);

app is used to control the applications’s event life cycle.

The above code snippet says that when the application is ready, load the first window.

Similarily app can be used to perform other actions on various events. For example it can be used to perform some action right before the application closes and so on.

Let’s create a Temperature Converter Desktop Application

Writing the Code

Let us use the same application we used before and modify it slightly to create a temperature converter application.

First Let us install Bootstrap. Install bootstrap using the following command

npm install bootstrap --save

Copy the following code into src/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Temperature Converter</title>
    <link rel="stylesheet" type="text/css" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">

  </head>
  <body>
    <h1>Temperature Converter</h1>
    <div class="form-group col-md-3">
      <label for="usr">Celcius:</label>
      <input type="text" class="form-control" id="celcius" onkeyup="celciusToFahrenheit()">
    </div>
    <div class="form-group col-md-3">
      <label for="pwd">Fahrenheit:</label>
      <input type="text" class="form-control" id="fahrenheit" onkeyup="fahrenheitToCelcius()">
    </div>
    <script src='./renderer.js'></script>
  </body>
  </body>
</html>

The above code does the following

  1. Creates a text box with id celcius. whenever anything is typed in this textbox, celciusToFahrenheit() function is called.
  2. Creates a text box with id fahrenheit. whenever anything is typed in this textbox, fahrenheitToCelcius() function is called.
  3. Whenever a new value is typed in celcius text box, the value in the fahrenheit text box displays the same temperature in fahrenheit
  4. Whenever a new value is typed in fahrenheit text box, the value in the celcius text box displays the same temperature in celcius

The 2 functions which do the temperature conversion are present in renderer.js

Create a file called renderer.js inside src. Copy the following code into it.

function celciusToFahrenheit(){
    let celcius = document.getElementById('celcius').value;
    let fahrenheit = (celcius* 9/5) + 32;
    document.getElementById('fahrenheit').value = fahrenheit;

}

function fahrenheitToCelcius(){
    let fahrenheit = document.getElementById('fahrenheit').value;
    let celcius = (fahrenheit - 32) * 5/9
    document.getElementById('celcius').value = celcius;
}

celciusToFahrenheit() function reads the value in celcius text box, converts it to fahrenheit and writes the new temperature into fahrenheit text box.

fahrenheitToCelcius() function does the exact opposite of this.

Running the application

Run the application using the following command

npm start

This should display the following window. Try it out with different values.

default result


Packaging the application

The command to package the application is

npm run package

This command will take some time to run. Once it finishes check the out folder within the project folder.

I tested this in a windows machine. This creates a folder called simple-desktop-app-electronjs-win32-x64 inside out folder

So in the out/simple-desktop-app-electronjs-win32-x64 folder, the command creates an .exe file for this application. Clicking on the exe file automatically starts the desktop application.

The folder name simple-desktop-app-electronjs-win32-x64 can be broken down as appname-platform-architecture where

  • appname = simple-desktop-app-electronjs
  • platform = win32
  • architecture = x64

When you run this command without any parameters, by default it packages for the platform which you are using for development

Let’s say you want to package for a different platform and architecture. Then you can use the following syntax

npm run package -- --platform=<platform> arch=<architecture>

For example, in order to package for linux you can use the following command

npm run package -- --platform=linux --arch=x64

This will create a folder called as simple-desktop-app-electronjs-linux-x64 inside out folder.

Creating a make File

In order to create a make file or an installer for the application, use the following command

npm run make

This command will take some time to run. Once it finishes check the out folder within the project folder.

The out/make folder will have a windows installer for the desktop application.

When you run this command without any parameters, by default it creates the installer for the platform which you are using for development

Code

The code for this desktop application is available in my github repo

https://github.com/siddharthverma-1607/simple-desktop-app-alectronjs

Congrats 😄

You now know how to create desktop applications using HTML, CSS and Javascript.

This article covered very basic concepts of electron and electron-forge.

To know more about them, you can checkout their documentation.

Thursday, July 9, 2020

My website now loads in less than 2 sec! Here's how I did it! ⚡


Cover image for My website now loads in less than 2 sec! Here's how I did it! ⚡



hash tags






Hi there!


The reason why you're here is probably because you wanna know what I did to load my portfolio website in just 1.8 seconds and achieved a performance score of 94 on lighthouse.


Link to my portfolio website is at the bottom.


I will lay out all my tips and tricks over here, which I implemented to achieve this! Let's get this thing started! 🤘


Tip #1

Don't use a large DOM tree.

My portfolio contains 440 DOM elements with a maximum DOM depth of 13 and a maximum of 23 child elements.


 

If your DOM tree is very large, then it will slow down the performance of your webpage:


  • Memory performance

Using general query selectors such as document.querySelectorAll('li'), stores references to a multiple nodes which can consume the memory capabilities of the device.

  • Network efficiency and load performance

A big DOM tree has many nodes (not visible in first load), which slows down load time and increases data costs for your users.

  • Runtime performance Whenever a user/ script interacts with your webpage, the browser needs to recompute the position and styling of nodes. having complicated style rules can slow down the rendering.

Tip #2

Don't use enormous network payloads.

The total payload size of your website should be below 1600 KB.
To keep it low, you can do the following:

  1. Defer requests until they're needed.
  2. Minify and compress network payloads.
  3. Set the compression level of JPEG images to 85.


Tip #3

Don't use GIFs.


Rather use PNG/ WebP format for dispalying static images. But if you want to display animated content then instead of using large GIFs (inefficient & pixelated) consider using MPEG4/ WebM video format.

Now, you will say what if I want their features like:

  • Automatic play.
  • Continuous loop.
  • No audio.

Tip #4

Preload key requests

Suppose your page is loading a JS file which fetched another JS and a CSS file, the page won't appear completely until both of those resources are downloaded, parsed, and executed.


If the browser would be able to start the requests earlier, then there would be much time saving. Luckily, you can do so by declaring preload links.


<link rel="preload" href="style.css" as="style">



Tip #5

Don't try multiple page redirects.

Redirecting slows down the load speed of your webpage. When a browser requests a resource that has been redirected, the server returns an HTTP response. The browser must then make another HTTP request at the new location to retrieve that resource. This additional trip across the network can delay the loading of the resource by hundreds of milliseconds.


If you want to divert your mobile users to the mobile version of your webpage, consider redesigning your website to make it responsive.



Tip #6

Preconnect to required origins.

Using the keyword preconnect gives a signal to the bowser to establish early connections to important third-party origins.


<link rel="preconnect" href="https://www.google.com">


Doing so establishes a connection to the origin, and that informs the bowser that you want the process to start ASAP.



Tip #7

Encode your images efficiently.

A compression level of 85 is considerd good enough for JPEG images. You can optimize your images in many ways:

  • Compressing images.
  • Using image CDNs.
  • Avoiding GIFs.
  • Serving responsive images.
  • Lazy loading images.


Tip #8

Minify your JavaScript files.

Minification is the process of removing whitespace and any code that is not necessary to create a smaller but perfectly valid code file.


By minifying your JavaScript files, you can reduce the payload size and parsing time for the script.


I use JavaScript Minifier for the same.




Tip #9

Minify your CSS files.

CSS files occupy more whitespace than any other file. By minifying them, we can save some bytes for sure!


Do you know that you can evem change a color value to its shorthand equivalent, like #000000 can be reduced to #000, and will work just fine!


I use CSS Minifier for the same.



Tip #10

Resize your images.

I can bet this is the most given advice when it comes to webperf because the size of images is far far far greater than any text script file, so an oversized image might be an overkill.


You should never upload images that are larger than what's rendered on the screen, that will do no good.


You can either just simply resize your image dimensions or use:

  • Responsive images.
  • Image CDNs.
  • SVG instead of icons.

Thank you for reading so far! 😄
Hope you learned something new from this! 😃

Here's the link to my portfolio website 👉 artistwhocode

Check it out and do let me know your views! Eager to hear your opinion. 😁


Feel free to share your portfolio link in the comments below. I would be very happy to have a look at them. 😊


Happy Coding! 👨‍💻