Skip to content
Click Here to get a free report on how to make your website faster
RSS
Svelte Context Module Scripts Explained

By

Raqueebuddin Aziz

August 4, 2023

Freelance Web Designer & Developer

Svelte Context Module Scripts Explained

This guide assumes you are familiar with how JS scopes and modules work and have completed the svelte tutorial.

The setup

This is a simple hello world svelte component that you and I will be walking through to see how script context=module works.

<!-- HelloWorld.svelte -->

<!-- OUTER SCOPE STARTS -->
<script context="module">
  import { writable } from 'svelte/store'

  let message = 'world!'
  const count = writable(0)

  setInterval(() => {
    count.update(c => c + 1)
  }, 1000)
</script>

<!-- INNER SCOPE STARTS -->
<script>
  $: console.log($count)
</script>

<p>hello {message}</p>
<button on:click={() => $count = 0}>Reset Count</button>
<!-- INNER SCOPE ENDS -->
<!-- OUTER SCOPE ENDS -->

What a svelte component file looks like in JS

Let’s see what a svelte component roughly would look like if it was written in JS to understand how context=module script works.

// HelloWorld.js

// OUTER SCOPE STARTS
import { writable } from 'svelte/store'

let message = 'world!'
const count = writable(0)

setInterval(() => {
	count.update((c) => c + 1)
}, 1000)

// @SVELTE-COMPILE
export const HelloWorld = () => {
	// INNER SCOPE STARTS
	$: console.log($count)

	return html`
		<p>hello ${message}</p>
		<button on:click="${() => ($count = 0)}">Reset Count</button>
	`
	// INNER SCOPE ENDS
}

export default HelloWorld
// OUTER SCOPE ENDS

What are the differences between context=module and non context=module script tags?

  • The code inside context=module scripts only runs once, no matter how many times you use a component.
  • You cannot use any variables/imports defined inside the normal script tag inside context=module script tag. You can do it the other way round though.
  • You cannot use svelte syntax including but not limited to dereferencing stores by prefixing $ to their name or creating reactive variables using let in context=module script tags.

Why does context=module code only runs once but normal script tags runs per component usage?

Because the global scope (context=module in svelte files) is only run on the first import of a module, but the component function (the normal script tag and the html) is executed every time a component is used.

Why can I not access non context=module script variables inside context=module script?

Look at the svelte example code above and then compare the scopes to the js example code above.

See how all the non context=module script variables are inside the inner scope aka inside the function thus variables defined inside a function cannot be used outside it.

The outside of the function in the .js file corresponding to the context=module script in the .svelte file.

Why does svelte syntax only work in non context=module scripts?

You would have noticed that you cannot use any svelte specific syntax in context=module scripts like $: console.log($count), setInterval(() => $count++, 1000). Instead we have to write pure JS inside context=module scripts.

The reason for this is everything inside the normal script tag inside a svelte component runs through the svelte compiler to transform the svelte specific syntax into pure JS syntax. Look at the @SVELTE-COMPILE line in js example code above. This compilation doesn’t happen for the context=module script.

The next question you might have is why not run the outer scope (context=module script) through a compiler too and let you use the svelte specific syntax in context=module scripts? Some of the reasons are

  • Svelte Syntax overrides some JS syntax, so if you do really want to use JS syntax then context=module not supporting svelte syntax is great. For e.g. if you want to define a variable that’s not reactive you can do that in context=module scripts using the let x = 1 syntax.
  • In the outer scope you can export variables and functions that other files can import. And analyzing svelte syntax across multiple files is extremely hard.

Conclusion

The context=module script tag is an escape hatch so you can break out into the global scope of the current module as with normal script tags you are contained within a function scope and cannot do things you can do in a global scope like exporting variables and functions, running code once per component and sharing state across multiple usage of the same component.

Leave a comment down below if you have any questions!

Tweet Share on LinkedIN Post on Reddit

Looking for a dev to help build an MVP for your tech startup?

Reach out to me.

Contact

We use cookies to enhance your browsing experience and analyze website traffic. By continuing to use our website, you consent to the use of cookies in accordance with our Privacy Policy.

Privacy Policy