diff --git a/site/content/examples/00-introduction/00-hello-world/meta.json b/site/content/examples/00-introduction/00-hello-world/meta.json index 2f47184710..6cf02c2ed1 100644 --- a/site/content/examples/00-introduction/00-hello-world/meta.json +++ b/site/content/examples/00-introduction/00-hello-world/meta.json @@ -1,3 +1,3 @@ { - "title": "Adding data" + "title": "Hello world" } \ No newline at end of file diff --git a/site/content/examples/11-svg/05-svg-transitions/App.svelte b/site/content/examples/11-svg/05-svg-transitions/App.svelte index 485bbf2558..6059b3645f 100644 --- a/site/content/examples/11-svg/05-svg-transitions/App.svelte +++ b/site/content/examples/11-svg/05-svg-transitions/App.svelte @@ -1,7 +1,7 @@ + + + +
+ +
\ No newline at end of file diff --git a/site/src/components/Lazy.svelte b/site/src/components/Lazy.svelte new file mode 100644 index 0000000000..ef81d68f00 --- /dev/null +++ b/site/src/components/Lazy.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/site/src/components/Repl/Bundler.js b/site/src/components/Repl/Bundler.js new file mode 100644 index 0000000000..ddde546e7f --- /dev/null +++ b/site/src/components/Repl/Bundler.js @@ -0,0 +1,44 @@ +const workers = new Map(); + +let uid = 1; + +export default class Bundler { + constructor(version) { + if (!workers.has(version)) { + const worker = new Worker('/workers/bundler.js'); + worker.postMessage({ type: 'init', version }); + workers.set(version, worker); + } + + this.worker = workers.get(version); + + this.handlers = new Map(); + + this.worker.addEventListener('message', event => { + const handler = this.handlers.get(event.data.id); + + if (handler) { // if no handler, was meant for a different REPL + handler(event.data); + this.handlers.delete(event.data.id); + } + }); + } + + bundle(components) { + return new Promise(fulfil => { + const id = uid++; + + this.handlers.set(id, fulfil); + + this.worker.postMessage({ + id, + type: 'bundle', + components + }); + }); + } + + destroy() { + this.worker.terminate(); + } +} \ No newline at end of file diff --git a/site/src/components/Repl/CodeMirror.svelte b/site/src/components/Repl/CodeMirror.svelte index e9519e516e..a1a92fe344 100644 --- a/site/src/components/Repl/CodeMirror.svelte +++ b/site/src/components/Repl/CodeMirror.svelte @@ -33,9 +33,9 @@ // than making this state-driven through props, // because it's difficult to update an editor // without resetting scroll otherwise - export function set(new_code, new_mode) { + export async function set(new_code, new_mode) { if (new_mode !== mode) { - createEditor(mode = new_mode); + await createEditor(mode = new_mode); } code = new_code; @@ -121,12 +121,13 @@ onMount(() => { if (_CodeMirror) { CodeMirror = _CodeMirror; - createEditor(mode || 'svelte'); - editor.setValue(code || ''); + createEditor(mode || 'svelte').then(() => { + editor.setValue(code || ''); + }); } else { - codemirror_promise.then(mod => { + codemirror_promise.then(async mod => { CodeMirror = mod.default; - createEditor(mode || 'svelte'); + await createEditor(mode || 'svelte'); editor.setValue(code || ''); }); } @@ -137,12 +138,10 @@ } }); - function createEditor(mode) { + async function createEditor(mode) { if (destroyed || !CodeMirror) return; - if (editor) { - editor.toTextArea(); - } + if (editor) editor.toTextArea(); const opts = { lineNumbers, @@ -162,6 +161,12 @@ 'Shift-Tab': tab }; + // Creating a text editor is a lot of work, so we yield + // the main thread for a moment. This helps reduce jank + await sleep(50); + + if (destroyed) return; + editor = CodeMirror.fromTextArea(refs.editor, opts); editor.on('change', instance => { @@ -171,8 +176,13 @@ } }); + await sleep(50); editor.refresh(); } + + function sleep(ms) { + return new Promise(fulfil => setTimeout(fulfil, ms)); + } + +
+ {#if process.browser} + + {/if} +
diff --git a/site/src/components/Repl/index.svelte b/site/src/components/Repl/index.svelte index 7e81f662c5..50499f163f 100644 --- a/site/src/components/Repl/index.svelte +++ b/site/src/components/Repl/index.svelte @@ -7,6 +7,7 @@ import ModuleEditor from './Input/ModuleEditor.svelte'; import Output from './Output/index.svelte'; import InputOutputToggle from './InputOutputToggle.svelte'; + import Bundler from './Bundler.js'; export let version = 'beta'; // TODO change this to latest when the time comes export let embedded = false; @@ -31,6 +32,8 @@ module_editor.set($selected.source, $selected.type); output.set($selected, $compile_options); + + rebundle(); } export function update(data) { @@ -69,8 +72,11 @@ let module_editor; let output; - function rebundle() { - workers.bundler.postMessage({ type: 'bundle', components: $components }); + let current_token; + async function rebundle() { + const token = current_token = {}; + const result = await bundler.bundle($components); + if (result && token === current_token) bundle.set(result); } setContext('REPL', { @@ -143,30 +149,7 @@ let width = typeof window !== 'undefined' ? window.innerWidth : 300; let show_output = false; - onMount(async () => { - workers = { - bundler: new Worker('/workers/bundler.js') - }; - - workers.bundler.postMessage({ type: 'init', version }); - workers.bundler.onmessage = event => { - bundle.set(event.data); - }; - - return () => { - workers.bundler.terminate(); - }; - }); - - $: if ($bundle && $bundle.error && $selected) { - sourceErrorLoc = $bundle.error.filename === `${$selected.name}.${$selected.type}` - ? $bundle.error.start - : null; - } - - $: if (workers && $components) { - workers.bundler.postMessage({ type: 'bundle', components: $components }); - } + const bundler = process.browser && new Bundler(version); $: if (output && $selected) { output.update($selected, $compile_options); diff --git a/site/src/routes/repl/_utils/process_example.js b/site/src/components/Repl/process_example.js similarity index 100% rename from site/src/routes/repl/_utils/process_example.js rename to site/src/components/Repl/process_example.js diff --git a/site/src/components/TopNav.svelte b/site/src/components/TopNav.svelte index d1e4db6d31..d02ff58cec 100644 --- a/site/src/components/TopNav.svelte +++ b/site/src/components/TopNav.svelte @@ -52,7 +52,7 @@ background-color: white; box-shadow: 0 -0.4rem 0.9rem 0.2rem rgba(0,0,0,.5); font-family: var(--font); - z-index: 10; + z-index: 100; user-select: none; transform: translate(0,calc(-100% - 1rem)); transition: transform 0.2s; diff --git a/site/src/routes/_layout.svelte b/site/src/routes/_layout.svelte index 386c27ac39..a72065a7c2 100644 --- a/site/src/routes/_layout.svelte +++ b/site/src/routes/_layout.svelte @@ -4,7 +4,6 @@ import Nav from '../components/TopNav.svelte'; export let segment; - export let path; @@ -20,7 +19,8 @@ main { position: relative; margin: 0 auto; - padding: var(--nav-h) var(--side-nav) 0 var(--side-nav); + /* padding: var(--nav-h) var(--side-nav) 0 var(--side-nav); */ + padding: var(--nav-h) 0 0 0; overflow-x: hidden; } \ No newline at end of file diff --git a/site/src/routes/blog/index.svelte b/site/src/routes/blog/index.svelte index 86828e42ca..b6743d94a1 100644 --- a/site/src/routes/blog/index.svelte +++ b/site/src/routes/blog/index.svelte @@ -30,7 +30,7 @@ grid-template-columns: 1fr 1fr; grid-gap: 1em; min-height: calc(100vh - var(--nav-h)); - padding: var(--top-offset) 0; + padding: var(--top-offset) var(--side-nav) 0 var(--side-nav); max-width: var(--main-width); margin: 0 auto; } diff --git a/site/src/routes/examples/index.svelte b/site/src/routes/examples/index.svelte index fa6ee35025..68cb9e3110 100644 --- a/site/src/routes/examples/index.svelte +++ b/site/src/routes/examples/index.svelte @@ -15,6 +15,7 @@ - - {name} • Svelte REPL - -
{#if process.browser} - + {/if}
diff --git a/site/src/routes/repl/index.svelte b/site/src/routes/repl/index.svelte index 8671717f5d..4f3a4f9f7c 100644 --- a/site/src/routes/repl/index.svelte +++ b/site/src/routes/repl/index.svelte @@ -11,7 +11,7 @@