For some of my components, I needed to write some javascript. Tell me everything I should know when it comes to optimising the JS that i've done.
For example, when not working with astro, in the index.html file, you had to either put the script tags outside the body (if I remember correctly) or at the top of body, with the attribute of defer.
#Optimising JS
13 messages · Page 1 of 1 (latest)
Hi @slender cave. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
In Astro, most of the “where do I put my <script> tag and should I use defer?” concerns are handled for you.
How Astro handles your <script> tags
In .astro files:
<h1>Welcome, world!</h1>
<script>
console.log('Welcome, browser console!');
</script>
By default, Astro:
- Processes and bundles these scripts (you can import local files or npm packages, and even use TypeScript).
- Outputs them as
type="module"scripts, which the browser treats as JavaScript modules. [Scripts guide]
Key optimization consequences:
- Non‑blocking by default: module scripts are always deferred. The browser keeps parsing HTML while they load and only executes them after the HTML is ready. You don’t need
deferorasync. [Scripts guide] - No “DOM ready” /
loadwait needed: the browser waits for HTML to be processed before executing module scripts. [Scripts guide] - Deduplication: if the same Astro component (with a processed
<script>) appears multiple times on a page, the script is only included once, which reduces duplicate JS. [Scripts guide]
Earlier docs stated that Astro injected these processed scripts into the page <head>, also as type="module", which is still non‑blocking and deferred, so the performance characteristics are the same from your perspective. [Scripts 2024]
When not to add async
Astro’s processed scripts are modules, so they already behave like deferred scripts. Adding async is usually a negative optimization:
asyncon a module script can make it run before the page has fully loaded, which often isn’t what you want (e.g. DOM not fully available, race conditions). [Scripts guide]
So, for “normal” component JS in Astro: just use <script> with no extra attributes.
When you want raw <script> tags
If you need a script to be emitted exactly as written (for example, a third‑party snippet where you control the loading attributes yourself):
<script is:inline>
// Will be rendered into the HTML exactly as written
</script>
Behavior and trade‑offs:
- Astro does not process or bundle this script:
- You cannot import local files or npm modules from it.
- If the component is reused on a page, the script will be repeated each time. [Scripts guide]
- Technically, any
<script>in Astro that hastype="module"or any attribute other thansrcis treated the same asis:inlineand is not processed. [Scripts 2024]
This is the situation where your “classic” HTML optimizations (placing tags, using defer/async) apply, because Astro is intentionally not helping you.
Practical optimization tips within Astro’s model
Within the limits of the docs you provided, here’s what you can safely do:
-
Prefer processed
<script>tags (no attributes) for your own component logic:- They are bundled, deduped, and loaded as
type="module"automatically. [Scripts guide]
- They are bundled, deduped, and loaded as
-
Keep inline, unprocessed scripts (
is:inline) only for special cases, like:- Copy‑pasted third‑party snippets that must stay verbatim.
- Scripts where you really need full manual control over attributes.
-
Don’t worry about placement or
deferin processed scripts:- Astro already gives you the “best practice” behavior you used to get by manually putting scripts at the end of
<body>withdefer. [Scripts guide]
- Astro already gives you the “best practice” behavior you used to get by manually putting scripts at the end of
Beyond this, the docs you shared don’t go into further JS‑specific micro‑optimizations (like splitting logic into smaller modules, avoiding heavy libraries, etc.), so I can’t cite official guidance there. If you want, you can share a specific component and I can help refactor its JS using only these documented behaviors.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@slender cave Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Should I include the dist folder in my gitignore or not? I shouldn't right, as when I'm importing my folder via github, the dist folder needs to be uploaded so I can import it???? @sly drum
Let me check the knowledge base for you again. One moment! :books:
You generally should ignore your build output (like dist/) in Git, and let your host build the site from source.
In the official GitLab Pages deployment guide, Astro’s default build folder is changed from dist/ to public/, and then that build folder is added to .gitignore:
# build output
dist/
public/
The guide explicitly says: “change dist/ to public/” in .gitignore, meaning the build output (whatever folder name you use) is intended not to be committed. [GitLab deploy guide]
Instead, Astro expects:
- You push source files (Astro components, config, etc.) to Git.
- Your hosting platform (e.g. GitLab CI, Netlify, etc.) runs
npm run build. - The generated folder (
dist/by default, orpublic/for GitLab Pages) is created during the CI build and used for deployment. [GitLab deploy guide]
So:
- Do put
dist/in.gitignorefor a normal Astro project. - The only time you’d upload the build folder is if your host cannot build from source and explicitly requires a prebuilt static folder; this kind of workflow is not described in the provided docs, so there’s no official guidance for that scenario.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@slender cave Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@sly drum So there no point of me actually doing npm run build if I have to ignore it before I upload to github, especially if Netlify will run npm run build itself?
Let me check the knowledge base for you again. One moment! :books:
For a Netlify deployment that builds from Git, you’re right: Netlify will run npm run build for you, so it’s not required that you run npm run build locally before every push.
From the Netlify guide:
- Netlify’s UI/CLI setup uses
astro build/npm run buildas the build command anddistas the publish directory. [Netlify deploy] - Once configured, “Any future changes to your source repository will trigger preview and production deploys based on your deployment configuration.” [Netlify deploy]
That means:
- You commit only source files (not
dist/). - Netlify pulls your repo, runs
npm run build, and serves the generateddist/.
So why ever run npm run build locally?
- To test the production build locally (e.g. check for build‑time errors, missing imports, etc.) before pushing.
- But this local
dist/is just for your own verification and can still be safely ignored in Git.
Therefore:
- Yes, keep
dist/in.gitignore. - No, you don’t need to build before every push for Netlify’s sake—only when you want to verify that the build succeeds locally.