search
HomeWeb Front-endJS TutorialLeaving the pipeline visible to monitor blog deployment

One of the things that bothers me about Computaria is not being able to follow the deployment on the blog itself. So, since this bothers me, why not fix it?

The pipeline

Currently there are 2 ways to know if the deploy is running:

  • open the repository on the jobs/pipelines page and see the latest one running
  • open in the repository and scroll to README.md

Both solutions don't seem great to me. I would like something lighter in Computing itself.

The idea

After a brief consultation with Kauê I decided to follow his tip: post on /about.

In the first experiment:

Deixando a pipeline visível para acompanhar deploy do blog

Nah, it got ugly. I already know that I don't want this to appear by default. But to bring the information it is enough. I just need to hide what is ugly, and make it available even if ugly if explicitly requested.

Proof of concept: crashes unless specified

Well, the first thing to do is know if we should take any action. To this end, the presence of the query param status with the value true was defined as an API.

To get the URL, I used window.location. Inside the Location object there is the search field, which serves precisely to maintain the query params used to access the specific URL.

For example, for http://localhost:4000/blog/about?q=1 the value of window.location.search is ?q=1. To make it easier to deal with the content within the query params, there is an object of type URLSearchParams. As far as I could understand from the documentation, to instantiate URLSearchParams, I need the query string but without the ? of the prefix. I can achieve this with window.location.search.substring(1).

Now, with this object in hand, I can simply consult the value of any query param I want:

const queryParams = new URLSearchParams(window.location.search.substring(1));

if (queryParams.get("status") === "true") {
    console.log("oba, vamos exibir o pipeline!")
} else {
    console.log("nops, não vamos exibir nada")
}

With this in hand, I need to take the action of displaying the pipeline badge. For the sake of ease, I decided to put it as an includeable HTML snippet: _includes/pipeline.html. So, I have free HTML to manipulate as I see fit.

In the beginning, it was simply a

invisible:
<div>



<p>Para importar, no /about só precisei colocar {%include pipeline.html%} no começo do arquivo, o Jekyll se encarregou de montar tudo certo.</p>

<p>Ok, vamos por o script para detectar se deveria ou não exibir a tag:<br>
</p>

<pre class="brush:php;toolbar:false"><script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));

    if (queryParams.get("status") === "true") {
        console.log("oba, vamos exibir o pipeline!")
    } else {
        console.log("nops, não vamos exibir nada")
    }
</script>
<div>



<p>So far, so good. Agora, vamos mudar a exibição para display: block caso seja para exibir o pipeline, ou sumir logo de uma vez com a </p>
<div>. Pelo console da web, bastaria fazer algo nesse esquema:<br>


<pre class="brush:php;toolbar:false">const pipeline = document.getElementById("pipeline")

if (...) {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

Placing in the HTML fragment:

<script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));
    const pipeline = document.getElementById("pipeline")

    if (queryParams.get("status") === "true") {
        pipeline.style.display = "block"
    } else {
        pipeline.remove()
    }
</script>
<div>



<p>E... falhou. Por quê? Porque no momento que a função rodar ainda não tem definido quem é o elemento com id pipeline. Então preciso mudar o ciclo de vida para rodar o script apenas quando a página for carregada. Basta colocar o <script defer>, certo? Bem, não. Porque defer não funciona bem com inline, apenas com arquivo de source explícito. Veja a documentação.</script></p>

<p>Ou seja, precisei colocar o arquivo JavaScript explicitamente para o Computaria. Como a priori tudo que está solto na pasta do blog é colocado como asset disponível para o Jekyll publicar, criei o js/pipeline-loader.js:<br>
</p>

<pre class="brush:php;toolbar:false"><script src="%7B%7B%20" prepend: site.baseurl defer>
</script>
<div>



<p>E no script:<br>
</p>

<pre class="brush:php;toolbar:false">const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

Great, let's do something useful and post the image? To dynamically create an element, just use document.createElement. Then I put the badge URL:

const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"

    const pipelineImg = document.createElement("img")
    pipelineImg.src = "{{site.repository.base}}/badges/master/pipeline.svg"

    pipeline.appendChild(pipelineImg)
} else {
    pipeline.remove()
}

But it showed a broken image... hmmm, what is the message displayed on the console?

GET http://localhost:4000/blog/about/{{site.repository.base}}/badges/master/pipeline.svg [HTTP/1.1 404 Not Found 4ms]

Strange, should he have gotten the cute rpository URL? Oh, I noticed. He didn't process Liquid at all. To deal with this I decided to follow the example in css/main.scss, an empty frontmatter.

const queryParams = new URLSearchParams(window.location.search.substring(1));

if (queryParams.get("status") === "true") {
    console.log("oba, vamos exibir o pipeline!")
} else {
    console.log("nops, não vamos exibir nada")
}

This gives an error message because frontmatter is not javascript, and the error is shown in the first const. Since this bothers me, the most direct way I thought of to deal with it was to create a "harmless error" earlier. I added a ; right after the frontmatter:

<div>



<p>Para importar, no /about só precisei colocar {%include pipeline.html%} no começo do arquivo, o Jekyll se encarregou de montar tudo certo.</p>

<p>Ok, vamos por o script para detectar se deveria ou não exibir a tag:<br>
</p>

<pre class="brush:php;toolbar:false"><script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));

    if (queryParams.get("status") === "true") {
        console.log("oba, vamos exibir o pipeline!")
    } else {
        console.log("nops, não vamos exibir nada")
    }
</script>
<div>



<p>So far, so good. Agora, vamos mudar a exibição para display: block caso seja para exibir o pipeline, ou sumir logo de uma vez com a </p>
<div>. Pelo console da web, bastaria fazer algo nesse esquema:<br>


<pre class="brush:php;toolbar:false">const pipeline = document.getElementById("pipeline")

if (...) {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

Annoyances...

As I continued testing, I noticed that a 308 constantly appeared in the network tab. But why did it appear? Well, because when expanding Liquid, it ended up with a double bar before badges.

I originally got this:

  • https://gitlab.com/computaria/blog//badges/master/pipeline.svg

With redirection to:

  • https://gitlab.com/computaria/blog/badges/master/pipeline.svg

And this started to bother me as I analyzed whether I was using cache or not. To solve this I should get rid of the double slash. I could just get rid of it by not putting the slash right after the Liquid value being expanded, because after all I could know a priori that the {{site.repository.base}} string ended with /. But, just in case, it doesn't realistically hurt to put that slash before /badges/master/pipeline.svg, it's even an indicator for myself as a reader.

But, since I don't want to rely on prior knowledge of whether or not this bar exists, I had two options for this:

  • treat the Liquid expansion level to remove the terminal slash
  • handle the creation of this string at a javascript level

The JavaScript side seemed easier to me. So just replace // with /, correct? Hmmm, no. Because the protocol appears before ://, so just making this crude substitution would result in the url starting like this: https:/computaria.gitlab.io. To get around this, I make the following substitution:

<script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));
    const pipeline = document.getElementById("pipeline")

    if (queryParams.get("status") === "true") {
        pipeline.style.display = "block"
    } else {
        pipeline.remove()
    }
</script>
<div>



<p>E... falhou. Por quê? Porque no momento que a função rodar ainda não tem definido quem é o elemento com id pipeline. Então preciso mudar o ciclo de vida para rodar o script apenas quando a página for carregada. Basta colocar o <script defer>, certo? Bem, não. Porque defer não funciona bem com inline, apenas com arquivo de source explícito. Veja a documentação.</script></p>

<p>Ou seja, precisei colocar o arquivo JavaScript explicitamente para o Computaria. Como a priori tudo que está solto na pasta do blog é colocado como asset disponível para o Jekyll publicar, criei o js/pipeline-loader.js:<br>
</p>

<pre class="brush:php;toolbar:false"><script src="%7B%7B%20" prepend: site.baseurl defer>
</script>
<div>



<p>E no script:<br>
</p>

<pre class="brush:php;toolbar:false">const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

Breaking it down:

  • in place of the replacement, put what was found in the "first group" followed by a slash
  • regex matches: anything other than : (in a group), slash, slash

With this change, https:// does not have match with ([^:])//, but all other occurrences of // in the path have a perfect match, as they will not be in front of one :. To be more strict, I could work to prevent the match from occurring in query param/fragment, but it seemed too overkill.

Proof of Concept: Cacheless Loading

Ok, having defined the details of where to place it and the locking mechanism, we need a reloading mechanism. First attempt: simply create a new image element. But still, how? The ideal would be "after some time". So this gives me two options, well to say:

  • setTimeout
  • setInterval

Okay, let's go with what does this do? setTimeout receives a command that will be executed after a time interval AND also the given interval. It gives you back an ID that you can remove using clearTimeout. To repeat the call, setTimeout needs to be called again at the end.

setInterval is almost the same thing, only it will always execute the command after the time interval. The return should be an ID that you would call clearInterval to remove, but according to the documentation it works with clearTimeout too (just in case, don't trust it, use the one with correct semantics).

Using setTimeout

Shall we create a loop call with setTimeout? How about printing the word pumpkin 5 times in a text field? I'll put a textarea for this experiment:

const queryParams = new URLSearchParams(window.location.search.substring(1));

if (queryParams.get("status") === "true") {
    console.log("oba, vamos exibir o pipeline!")
} else {
    console.log("nops, não vamos exibir nada")
}

Ok, I have 3 functions that I would like to be reachable by HTML. And they divide (even if very slightly) a state. I'm a sucker for hiding things, so I don't want this state to be visible outside the <script> tag.</script>

My most obvious solution is to leave it under a block, so, when leaving the block, the variables inside will be invisible outside:

<div>



<p>Para importar, no /about só precisei colocar {%include pipeline.html%} no começo do arquivo, o Jekyll se encarregou de montar tudo certo.</p>

<p>Ok, vamos por o script para detectar se deveria ou não exibir a tag:<br>
</p>

<pre class="brush:php;toolbar:false"><script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));

    if (queryParams.get("status") === "true") {
        console.log("oba, vamos exibir o pipeline!")
    } else {
        console.log("nops, não vamos exibir nada")
    }
</script>
<div>



<p>So far, so good. Agora, vamos mudar a exibição para display: block caso seja para exibir o pipeline, ou sumir logo de uma vez com a </p>
<div>. Pelo console da web, bastaria fazer algo nesse esquema:<br>


<pre class="brush:php;toolbar:false">const pipeline = document.getElementById("pipeline")

if (...) {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

Okay, but how do you make the functions visible? Well, experimenting I found a way: function escapes scope. And as local variables do not exceed the limits of the block, I can still place some auxiliary functions inside the block so that they have no meaning outside. Something like this:

<script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));
    const pipeline = document.getElementById("pipeline")

    if (queryParams.get("status") === "true") {
        pipeline.style.display = "block"
    } else {
        pipeline.remove()
    }
</script>
<div>



<p>E... falhou. Por quê? Porque no momento que a função rodar ainda não tem definido quem é o elemento com id pipeline. Então preciso mudar o ciclo de vida para rodar o script apenas quando a página for carregada. Basta colocar o <script defer>, certo? Bem, não. Porque defer não funciona bem com inline, apenas com arquivo de source explícito. Veja a documentação.</script></p>

<p>Ou seja, precisei colocar o arquivo JavaScript explicitamente para o Computaria. Como a priori tudo que está solto na pasta do blog é colocado como asset disponível para o Jekyll publicar, criei o js/pipeline-loader.js:<br>
</p>

<pre class="brush:php;toolbar:false"><script src="%7B%7B%20" prepend: site.baseurl defer>
</script>
<div>



<p>E no script:<br>
</p>

<pre class="brush:php;toolbar:false">const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

Okay, now I need to deal with timeout calls. My idea is to execute a step and, when this step is completed, register the next timeout, calling the same step. And just to avoid limiting this step to a few times forever.

So, if there wasn't the timeout issue, what would it be like? A recursive call:

const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"

    const pipelineImg = document.createElement("img")
    pipelineImg.src = "{{site.repository.base}}/badges/master/pipeline.svg"

    pipeline.appendChild(pipelineImg)
} else {
    pipeline.remove()
}

It looks good, what about adding the timeout? Well, inside the body of the step, so calling step is setting the timeout. For a good timeout, I need the time:

GET http://localhost:4000/blog/about/{{site.repository.base}}/badges/master/pipeline.svg [HTTP/1.1 404 Not Found 4ms]

Ok, all that’s left to do is save the timeout identifier and we’re ready. I place this step inside the exposed public function and we are ready:

---
# frontmatter vazio para fazer o parse do liquid
---

const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"

    const pipelineImg = document.createElement("img")
    pipelineImg.src = "{{site.repository.base}}/badges/master/pipeline.svg"

    pipeline.appendChild(pipelineImg)
} else {
    pipeline.remove()
}

Okay, we have room for fun now:

See on Fiddle https://jsfiddle.net/jeffque/5Lrasyqk/

Using setInterval

The use of setInterval is very similar, but the "recall" step is implicit. If I want to stop the loop, I need to explicitly cancel the registered setInterval.

Well, how about starting like the example above? But with a different scratch area ID:

---
# frontmatter vazio para fazer o parse do liquid
---
;

const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"

    const pipelineImg = document.createElement("img")
    pipelineImg.src = "{{site.repository.base}}/badges/master/pipeline.svg"

    pipeline.appendChild(pipelineImg)
} else {
    pipeline.remove()
}

See on Fiddle https://jsfiddle.net/jeffque/5Lrasyqk/

Reload attempts

With the repeat timing mechanism defined, it is now a matter of defining how to reload the image. First, analyze the headers that GitLab returns when searching for the badge: https://gitlab.com/computaria/blog//badges/master/pipeline.svg:

const queryParams = new URLSearchParams(window.location.search.substring(1));

if (queryParams.get("status") === "true") {
    console.log("oba, vamos exibir o pipeline!")
} else {
    console.log("nops, não vamos exibir nada")
}

Comparing multiple etags from different requests just in case:

<div>



<p>Para importar, no /about só precisei colocar {%include pipeline.html%} no começo do arquivo, o Jekyll se encarregou de montar tudo certo.</p>

<p>Ok, vamos por o script para detectar se deveria ou não exibir a tag:<br>
</p>

<pre class="brush:php;toolbar:false"><script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));

    if (queryParams.get("status") === "true") {
        console.log("oba, vamos exibir o pipeline!")
    } else {
        console.log("nops, não vamos exibir nada")
    }
</script>
<div>



<p>So far, so good. Agora, vamos mudar a exibição para display: block caso seja para exibir o pipeline, ou sumir logo de uma vez com a </p>
<div>. Pelo console da web, bastaria fazer algo nesse esquema:<br>


<pre class="brush:php;toolbar:false">const pipeline = document.getElementById("pipeline")

if (...) {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

Well, the etag was always the same, indicating that it's the same resource. The cache-control: no-store strongly tells me that it is not for storing the cache. The expires pointing to the past strongly indicates that it was intended to indicate that this resource should not be considered for caching. Until proven otherwise, cf-cache-status: MISS only indicated that it did not hit Cloudflare's cache.

Finally, strict-transport-security. What does this mean? What does this have to do with the resource itself?

Well, it has nothing to do with the resource being accessed. But it is an indicator that the site should only be accessed with HTTPS.

Okay, all this indicates that the image should not be curly. An F5 always causes it to be downloaded again, as expected. This for me is a very strong indicator that if I have a problem with the cache, it will not be on the server or on the network, but something at the browser level.

First attempt: create a new img element and throw the previous one away.

For convenience, there's nothing like having a function that returns the element:

<script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));
    const pipeline = document.getElementById("pipeline")

    if (queryParams.get("status") === "true") {
        pipeline.style.display = "block"
    } else {
        pipeline.remove()
    }
</script>
<div>



<p>E... falhou. Por quê? Porque no momento que a função rodar ainda não tem definido quem é o elemento com id pipeline. Então preciso mudar o ciclo de vida para rodar o script apenas quando a página for carregada. Basta colocar o <script defer>, certo? Bem, não. Porque defer não funciona bem com inline, apenas com arquivo de source explícito. Veja a documentação.</script></p>

<p>Ou seja, precisei colocar o arquivo JavaScript explicitamente para o Computaria. Como a priori tudo que está solto na pasta do blog é colocado como asset disponível para o Jekyll publicar, criei o js/pipeline-loader.js:<br>
</p>

<pre class="brush:php;toolbar:false"><script src="%7B%7B%20" prepend: site.baseurl defer>
</script>
<div>



<p>E no script:<br>
</p>

<pre class="brush:php;toolbar:false">const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

And in setTimeout I need to remove the #pipeline children and insert the new image. The options I found with actions from the father are:

  • removeChild
  • replaceChild
  • replaceChildren

Well, removeChild and replaceChild involve knowing how to save the old element to request its removal. ReplaceChildren, on the other hand, doesn't have any drama, it just passes the new element and that's good:

const queryParams = new URLSearchParams(window.location.search.substring(1));
const pipeline = document.getElementById("pipeline")

if (queryParams.get("status") === "true") {
    pipeline.style.display = "block"

    const pipelineImg = document.createElement("img")
    pipelineImg.src = "{{site.repository.base}}/badges/master/pipeline.svg"

    pipeline.appendChild(pipelineImg)
} else {
    pipeline.remove()
}

that alone makes the magic. So, how does it behave anyway?

Deixando a pipeline visível para acompanhar deploy do blog

Creating the new img was not enough.

Another alternative I found was to set the variable value again. With this, there is no longer a need to have the function that generates identical elements, I will just "modify" the URL that the img points to. And, well, that's how I discovered that the same asset used in several places on the same page can suffer some kind of caching...

Ok, what if each repetition is added a ' ' at the end of the URL to try to trick GitLab? Well, gitlab realized I was up to no good...

What if it's a queryParam passed with an argument or its iterator?

Deixando a pipeline visível para acompanhar deploy do blog

But, at what cost?

Ok, with that out of the question because it's a workaround, let's try to fetch it? And after giving fetch, think about how to replace the image?

const queryParams = new URLSearchParams(window.location.search.substring(1));

if (queryParams.get("status") === "true") {
    console.log("oba, vamos exibir o pipeline!")
} else {
    console.log("nops, não vamos exibir nada")
}

Hmm, error, from CORS. And since I have no control over GitLab, what else can I do?

The Leaving the pipeline visible to monitor blog deployment there is no reload, but the

Ok, new experiment: create /assets/pipeline.html simply with the img tag and point to it from an iframe. For the force reload operation I used the same as the Stack Overflow answer:

<div>



<p>Para importar, no /about só precisei colocar {%include pipeline.html%} no começo do arquivo, o Jekyll se encarregou de montar tudo certo.</p>

<p>Ok, vamos por o script para detectar se deveria ou não exibir a tag:<br>
</p>

<pre class="brush:php;toolbar:false"><script>
    const queryParams = new URLSearchParams(window.location.search.substring(1));

    if (queryParams.get("status") === "true") {
        console.log("oba, vamos exibir o pipeline!")
    } else {
        console.log("nops, não vamos exibir nada")
    }
</script>
<div>



<p>So far, so good. Agora, vamos mudar a exibição para display: block caso seja para exibir o pipeline, ou sumir logo de uma vez com a </p>
<div>. Pelo console da web, bastaria fazer algo nesse esquema:<br>


<pre class="brush:php;toolbar:false">const pipeline = document.getElementById("pipeline")

if (...) {
    pipeline.style.display = "block"
} else {
    pipeline.remove()
}

To HTML

And, go there! It worked!

Deixando a pipeline visível para acompanhar deploy do blog

Now, adjustments to make it suitable:

  • stop/restart control for badge recharging
  • in the iframe: follow the tips from Editing SVG by hand to order coffee to deal with the iframe
  • inside the document: remove margins from the body to only have space for the badge

By making these adjustments, you can get out of this

Deixando a pipeline visível para acompanhar deploy do blog

for this

Deixando a pipeline visível para acompanhar deploy do blog

You can check the files used here:

  • /about.md
  • /_includes/pipeline.html
  • /assets/pipeline-badge.html
  • /js/pipeline-loader.js

The above is the detailed content of Leaving the pipeline visible to monitor blog deployment. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Python vs. JavaScript: A Comparative Analysis for DevelopersPython vs. JavaScript: A Comparative Analysis for DevelopersMay 09, 2025 am 12:22 AM

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Python vs. JavaScript: Choosing the Right Tool for the JobPython vs. JavaScript: Choosing the Right Tool for the JobMay 08, 2025 am 12:10 AM

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript: Understanding the Strengths of EachPython and JavaScript: Understanding the Strengths of EachMay 06, 2025 am 12:15 AM

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScript's Core: Is It Built on C or C  ?JavaScript's Core: Is It Built on C or C ?May 05, 2025 am 12:07 AM

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

JavaScript Frameworks: Powering Modern Web DevelopmentJavaScript Frameworks: Powering Modern Web DevelopmentMay 02, 2025 am 12:04 AM

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

The Relationship Between JavaScript, C  , and BrowsersThe Relationship Between JavaScript, C , and BrowsersMay 01, 2025 am 12:06 AM

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version