“If you don’t understand the details of your business, you are going to fail “— Jeff Bezos
Today, it is difficult to imagine a world without internet.
The web browser is at the heart of how we experience the internet. Every day, millions visit websites via browsers. Five major browsers — Chrome, Firefox, Internet Explorer, Safari and Opera — account 95% of web traffic.
A major role of a web browser is to accept a web URL via an address bar, fetch resources, and display them on the screen.
Browsers functionality can be classified into four major sections and these include:
Each category defines a set of duties that browser has to execute and comprises of subsystems.
A major subsystem called network layer plays a vital role in fetching data from subsequent web servers via the internet.
Accepts URLs from the browser user interface and is responsible for making network calls to fetch resources via HTTP/FTP protocols.
It feeds data to the process subsystem called rendering engine as it becomes available and is usually done in byte size to improve performance.
If the requested website implements a cache, a copy of the data is made in App Cache or Service Workers for next time. Caches are great for their quick response times and saving network requests for regular visits.
The browser initially looks for any cache availability on local memory for requested URLs. Otherwise, the network layer creates an HTTP packet with a domain name for requesting a web resource over the internet.
The network layer plays a major role in the user experience. It can be a bottleneck in web performance, since browsers wait for remote data/content to arrive. Various techniques can be used to reduce this impact on the user’s experience.
This step involves accepting data from the network layer and feed the display subsystems. Render engine, JS engine and UI backend subsystems are part of the process.
WebKit Main Flow
The rendering engine subsystem processes data from the network layer and displays web content on the screen.
By default, it can process HTML, XML and Image files. However, it can be extended to accommodate various data types via extensions.
Many render engines are available, and are usually written in C++. Examples include:
With rendering engines, web resources are parsed. For example, a HTML parser converts a HTML template into an object called the DOM tree.
Stylesheets are parsed to generate style rules for both external and inline style elements.
A render tree is an object that combines both the parsed HTML and CSS. It is generated with visual instructions and attributes to render elements on the user’s screen.
Once the render tree is constructed, it undergoes layout and painting processes, and displays the output on the screen.
The layout process includes calculating dimensions and exact coordinates where each element should appear on the viewport.
The painting process includes filing the layout with style attributes like color, background and other CSS properties.
The rendering engine processes data in chunks and displays the content as soon as possible. It will not wait until the entire document content undergoes the layout and painting processes.
This is the subsystem for parsing JavaScript code to machine code and then executing it. These JS engines can be standard interpreters or JIT (just in time) compilers.
One of the most popular engines is the Google V8 engine. It is written in C++. Here are some examples that different browsers use:
JavaScript Engine
These engines include two components: the memory heap and the call stack.
The memory heap is where memory is allocated for variables, functions and other JS elements.
The call stack is simply a queue of stack frames or sequential steps executed by the browser.
JavaScript is a single-threaded process and each entry or execution step is a stack frame.
These engines have several threads internally to perform various tasks. Examples of such tasks include:
Google’s V8 engine uses a mark-and-sweep method to perform garbage collection in an incremental way. This makes use of the browser’s idle time and improves performance.
As of version 5.9 (early 2017), Ignition and Turbofan are the latest pipelines in the V8 engine.
NodeJS is a server-side JavaScript runtime built based on Google’s open source V8 engine. It is used to execute JavaScript on the server side.
As the name itself suggests, this relates presenting data to the users. User Interface and Browser Engine are responsible for data presentation and handling user navigation.
The visual appearance of the browser normally includes an address bar to accept web URLs, and navigation buttons such as a back, forward, refresh, and a home and bookmarks bar.
Along with these inputs and action buttons, we have the viewport (the main part of the screen) to display content fetched from websites.
The User Interface (UI) communicates with other subsystems within the browser to display content and act accordingly.
No specific standards are imposed on how the interface should look and feel. Instead, browser vendors have refined the UI as browsers have evolved over the years.
The browser engine is an embeddable subsystem that provides a high-level interface to the rendering engine.
It loads a given URL and supports primitive browsing actions such as navigating forward, back and reload.
It also provides hooks for viewing various aspects of the browsing session. For example, viewing current page load progress and JavaScript alerts.
The browser engine also allows for querying and manipulating the rendering engine settings.
Web browsers have a small amount of storage capacity in order perform few actions, cache data and store data over browser for perform kicks and other browser functionality.
Data persistence is achieved through various browser APIs. Some of them include:
Local storage and Session storage are key-value pairs that can store any JS objects and functions in the browser.
Session storage persists the data on the browser as long as a website session is active. Local storage is the memory on the browser. It persists data until it is cleared or altered explicitly by the user or JavaScript code.
These Session and Local web storage limits are 5MB per object, and 50MB per system.
Cookies are collections of key-pair data stored on the browser memory. They are sent back and forth between client and server.
These are expensive and are the least performant of the data persistence methods. However, they are very useful when privacy and security come into the picture.
WebSQL, IndexedDB, and FileSystem have the abilities to store data on browser depending on size, performance, and necessity.
App Cache was introduced in HTML5. It stores website static content and serves UI content during network downtime.
Service Workers are Google’s new way of caching website data for offline usage. It has significant features compared to App Cache. You can read more about Service Workers here.
All right, let’s do a quick recap now. All major web browsers comprise subsystems, along with other submodules to help with the process.
These systems are involved from accepting the web URLs, to displaying web content on the screen. They make network calls, fetch resources, parse HTML, CSS, and JavaScript files to create objects to render on the screen. These all combine to produce a wonderful website for the user.
You can read more at the resources linked below:
Thank you for reading 👍