Skip to content
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!

Post on X Share on LinkedIN Post on Reddit

© 2024 Raqueebuddin Aziz. All rights reserved.