wungjyan

wungjyan

Understanding runtime and compile time in frontend frameworks

This article mainly explains the differences between runtime and compile time in front-end frameworks. First, it is mentioned that this article refers to the book "Vue.js Design and Implementation" and adds personal understanding. Please point out any errors.

Runtime#

Runtime refers to the stage when the code is actually executed. Front-end code is executed in the browser. In other words, if a framework's code can be directly executed in the browser, it is a pure runtime framework.

For example, let's say we design a framework that provides a Render function. When users use it, they provide a parameter object that describes the DOM tree structure to this function. Then, the Render function recursively renders the data into DOM elements based on this object. Let's assume the structure of the object is as follows:

const obj = {
  tag: "div",
  children: [
    {
      tag: "span",
      children: "hello world!",
    },
  ],
};

The object has two properties: tag represents the tag name, and children can be an array (representing child nodes) or text (representing text child nodes). Then, implement the Render function:

function Render(obj, root) {
  const el = document.createElement(obj.tag);
  if (typeof obj.children === "string") {
    const text = document.createTextNode(obj.children);
    el.appendChild(text);
  } else if (obj.children) {
    obj.children.forEach((child) => Render(child, el));
  }

  root.appendChild(el);
}

Now, the Render function can be called in the browser environment:

// Render to the body
Render(obj, document.body);

At this point, the expected result will be displayed. This is an example of a pure runtime framework because the browser can directly run JavaScript files without any conversion operations.

Compile Time#

Understanding runtime makes it easy to understand compile time, which refers to the stage of converting source code into executable code. In the front-end, the simplest example is converting advanced ES6 syntax into ES5 syntax that the browser can understand and execute. This process is also called compilation.

Let's use the code example above to explain how to transform it into a compile-time framework. But first, we need to know that we don't add compilation just for the sake of compilation, but to solve problems.

Let's look at what problems exist in the code of the runtime example above. Obviously, defining the DOM tree structure object is a bit cumbersome. If the DOM structure is complex, the object that needs to be defined will be deeply nested, making it abstract and not intuitive. So we think, can we directly declare UI like writing HTML? Yes, just like the template in Vue. First, we should know that the template part in a Vue file is not HTML. Although it looks similar, the browser cannot directly recognize them, so the template needs to be compiled. So what should it be compiled into?

The result of compilation is to make it executable by the browser. So let's say we write the template like this:

<div>
  <span>hello world!</span>
</div>

Remember, it is not an HTML file, so we need to compile it into imperative code:

const div = document.createElement("div");
const span = document.createElement("span");
span.innerText = "hello world!";
div.appendChild(span);
document.body.appendChild(div);

At this point, the browser can directly execute the code and achieve the expected result. We can encapsulate this process into a compiler, and all the user's code can only be executed after being compiled by the compiler. This is a pure compile-time framework, representing frameworks like Svelte.

Runtime + Compile Time#

It was mentioned earlier that the template in Vue needs to be compiled before it can be executed by the browser. So is Vue a compile-time framework? The answer is no.

Vue is a runtime + compile-time framework. This is mentioned in the official documentation Runtime vs. Compile-time Reactivity, which states:

Vue's reactivity system is mostly runtime-based. Tracking and triggering are done at runtime in the browser.

Let's go back to the example mentioned above. How can we implement a runtime + compile-time framework?

It's actually just adding a compiler, but instead of directly compiling it into imperative creation code, we compile the template into a DOM description object, and then pass the object to the renderer. Like this:

<div>
  <span>hello world!</span>
</div>

Compiles to ⬇️

const obj = {
  tag: "div",
  children: [
    {
      tag: "span",
      children: "hello world!",
    },
  ],
};

Then render:

Render(obj, document.body);

This is a runtime + compile-time process, or more accurately, a runtime compilation, which means compiling when the code is executed. In actual framework usage, we can perform compilation during the build process, so no compilation is needed during runtime, which improves performance.

At this point, we may wonder if this kind of runtime compilation is unnecessary. Isn't it more efficient to compile directly? Theoretically, pure compile-time performance will indeed be better because there is no runtime involvement. The code is directly compiled into executable JavaScript code. However, this also sacrifices some flexibility. The content provided by the user must be compiled before it can be used. In a pure runtime framework, without a compilation process, it is impossible to analyze the content provided by the user and make corresponding optimizations. In general, in a compiler, we can implement syntax analysis, optimization, and transformation, perform syntax error checking, module bundling, and code compression tasks. It can only be said that framework authors have their own trade-offs when designing frameworks, and it is not possible to directly judge which one is better.

Using Frameworks or Writing HTML Directly#

After seeing the analysis above, we can't help but think about abandoning frameworks and writing HTML directly, which seems more intuitive and convenient. But the fact is, using modern frameworks like Vue or React greatly increases our development efficiency. The reason is that these frameworks encapsulate the process of doing things for us. If we develop using traditional native HTML, we need to maintain the entire process of achieving the goal, including manually creating, updating, and deleting DOM elements. But frameworks allow us to only declare the UI for the result without worrying about the implementation process. This is the convenience of frameworks, and understanding runtime and compile time is also to better understand the implementation principles of frameworks.

Conclusion#

Finally, let's summarize runtime and compile time.

Runtime refers to the stage when the code is actually executed. In front-end frameworks, runtime usually refers to loading and executing pre-compiled code in the browser environment. This stage includes tasks such as parsing HTML structure, building the DOM tree, executing JavaScript code, and handling user interactions. During runtime, front-end frameworks use the compiled code to dynamically update and render the page, handle event and data changes, etc.

Compile time refers to the stage of converting the source code written by developers into executable code during the development process. For example, converting ES6 to ES5, compiling Vue templates into HTML, etc. During compile time, the compiler of the front-end framework analyzes, optimizes, and transforms the code to generate code that can be run in the browser. Tasks during compile time include syntax checking, module bundling, code compression, etc.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.