Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite as a Svelte/Express app #56

Merged
merged 34 commits into from
Mar 19, 2017
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
13cd33e
start rebuilding as Svelte/Express app
Rich-Harris Mar 13, 2017
07eed0b
add guide
Rich-Harris Mar 13, 2017
55fc08c
implement some more nav stuff
Rich-Harris Mar 14, 2017
31fa19d
keep built routes/components out of repo
Rich-Harris Mar 14, 2017
0e047f1
fix stuff for now
Rich-Harris Mar 14, 2017
e5f99f4
sourcemaps
Rich-Harris Mar 14, 2017
1966319
fix scroll anchor positions
Rich-Harris Mar 14, 2017
fca87c6
various
Rich-Harris Mar 14, 2017
95012d8
hmm
Rich-Harris Mar 14, 2017
0bc689e
remove unused files
Rich-Harris Mar 14, 2017
f4abac1
repl mostly working
Rich-Harris Mar 14, 2017
267df96
load initial example in REPL
Rich-Harris Mar 14, 2017
420865d
fix SSR
Rich-Harris Mar 14, 2017
9f7869c
fix fonts in repl viewer
Rich-Harris Mar 14, 2017
23132f3
fix links
Rich-Harris Mar 14, 2017
ed09a4a
syntax highlighting
Rich-Harris Mar 14, 2017
71fc87a
activate guide JS, scroll correctly
Rich-Harris Mar 14, 2017
c26631c
remove guide JSON from repo
Rich-Harris Mar 14, 2017
99afc4e
remove repl button for a couple of snippets
Rich-Harris Mar 14, 2017
b85ed43
fix z indexes
Rich-Harris Mar 14, 2017
7238a61
fix repl
Rich-Harris Mar 14, 2017
26cb60c
fix guide generation
Rich-Harris Mar 14, 2017
6efb361
fix blog links
Rich-Harris Mar 15, 2017
caccbd1
section highlighting
Rich-Harris Mar 15, 2017
e298308
fix nav
Rich-Harris Mar 15, 2017
44d9653
smoother scrolling in guide
Rich-Harris Mar 15, 2017
65849a0
guess passive event listeners are broken, huh
Rich-Harris Mar 15, 2017
f2dc340
fallback fonts
Rich-Harris Mar 15, 2017
2bbad9a
fix minor error
Rich-Harris Mar 15, 2017
3074ebb
update roadtrip
Rich-Harris Mar 15, 2017
87d2a8e
ensure rollup is run before deployment
Rich-Harris Mar 15, 2017
b781683
ensure curl is loaded before the bundle
Rich-Harris Mar 15, 2017
9efbee7
redirect old REPL links
Rich-Harris Mar 19, 2017
1777e11
fix css
Rich-Harris Mar 19, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
"node": true,
"mocha": true
},
"globals": {
"svelte": true
},
"extends": [
"eslint:recommended",
"plugin:import/errors",
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@
node_modules
.gobble*
dist
public/bundle.js
public/bundle.js.map
public/main.css
public/guide.json
shared/components/guide-summary.json
server/components
server/routes
8 changes: 8 additions & 0 deletions client/codemirror.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import CodeMirror from 'codemirror';
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/shell/shell.js';
import 'codemirror/mode/htmlmixed/htmlmixed.js';
import 'codemirror/mode/xml/xml.js';
import 'codemirror/mode/css/css.js';

export default CodeMirror;
9 changes: 9 additions & 0 deletions client/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function get ( url ) {
return new Promise( ( fulfil, reject ) => {
const xhr = new XMLHttpRequest();
xhr.open( 'GET', url );
xhr.onerror = reject;
xhr.onload = () => fulfil( xhr.responseText );
xhr.send();
});
}
162 changes: 162 additions & 0 deletions client/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import roadtrip from 'roadtrip';
import Index from '../shared/routes/Index.html';
import BlogIndex from '../shared/routes/BlogIndex.html';
import BlogPost from '../shared/routes/BlogPost.html';
import Guide from '../shared/routes/Guide.html';
import Repl from '../shared/routes/Repl/index.html';
import Nav from '../shared/components/Nav.html';
import get from './get.js';

const header = document.querySelector( 'header' );
const main = document.querySelector( 'main' );

const nav = new Nav({
target: ( header.innerHTML = '', header )
});

let view;

// legacy
function redirect ( from, to ) {
roadtrip.add( from, {
enter: route => {
if ( typeof to === 'function' ) to = to( route );
roadtrip.goto( to, { replaceState: true });
}
});
}

redirect( '/blog/', '/blog' );
redirect( '/guide/', '/guide' );
redirect( '/blog/:slug/', route => `/blog/${route.params.slug}` );

roadtrip
.add( '/', {
enter ( route ) {
nav.set({ route: 'index' });

if ( route.isInitial ) return; // page is static

document.title = 'Svelte • The magical disappearing UI framework';

if ( view ) {
view.destroy();
} else {
main.innerHTML = '';
}

view = new Index({
target: main
});

window.scrollTo( route.scrollX, route.scrollY );
}
})
.add( '/blog', {
enter ( route ) {
nav.set({ route: 'blog' });

if ( route.isInitial ) return; // page is static

document.title = 'Svelte • The magical disappearing UI framework';

if ( view ) {
view.destroy();
} else {
main.innerHTML = '';
}

return get( `/blog.json` ).then( JSON.parse ).then( posts => {
view = new BlogIndex({
target: main,
data: {
posts
}
});

window.scrollTo( route.scrollX, route.scrollY );
});
}
})
.add( '/blog/:slug', {
enter ( route ) {
nav.set({ route: 'blog' });

if ( route.isInitial ) return; // page is static

return get( `/blog/${route.params.slug}.json` ).then( JSON.parse ).then( post => {
document.title = `${post.metadata.title} • Svelte`;

if ( view ) {
view.destroy();
} else {
main.innerHTML = '';
}

view = new BlogPost({
target: main,
data: {
post
}
});

// TODO this doesn't work because it's the <main> that scrolls, not the window
window.scrollTo( route.scrollX, route.scrollY );
});
}
})
.add( '/guide', {
enter ( route ) {
nav.set({ route: 'guide' });

document.title = 'Learn Svelte';

if ( view ) {
view.destroy();
} else {
main.innerHTML = '';
}

return get( `/guide.json` ).then( JSON.parse ).then( sections => {
view = new Guide({
target: main,
data: {
sections
}
});

view.on( 'scroll', id => {
nav.set({ active: id });
});

if ( route.scrollY === 0 ) {
// scroll to section
if ( window.location.hash.length > 1 ) {
const h = main.querySelector( window.location.hash );
if ( h ) window.scrollTo( 0, h.getBoundingClientRect().top );
}
} else {
window.scrollTo( route.scrollX, route.scrollY );
}
});
}
})
.add( '/repl', {
enter ( route ) {
nav.set({ route: 'repl' });

document.title = 'Svelte REPL';

if ( view ) {
view.destroy();
} else {
main.innerHTML = '';
}

view = new Repl({
target: main
});
}
});

roadtrip.start();
6 changes: 3 additions & 3 deletions src/guide/00-introduction.md → guide/00-introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ But Svelte has a crucial difference: rather than interpreting your application c

And because there's no overhead, you can easily adopt Svelte in an existing app incrementally, or ship widgets as standalone packages that work anywhere.

[Read the introductory blog post](/blog/frameworks-without-the-framework/) to learn more about Svelte's goals and philosophy.
[Read the introductory blog post](/blog/frameworks-without-the-framework) to learn more about Svelte's goals and philosophy.


### Understanding Svelte components
Expand Down Expand Up @@ -76,7 +76,7 @@ cd my-svelte-project

Inside `my-svelte-project`, create a `HelloWorld.html` file with the following contents:

```html
```html-no-repl
<h1>Hello {{name}}</h1>
```

Expand All @@ -90,7 +90,7 @@ The `--format iife` bit means 'generate an immediately-invoked function expressi

Create an `index.html` page and include the script we just generated:

```html
```html-no-repl
<!doctype html>
<html>
<head>
Expand Down
3 changes: 2 additions & 1 deletion src/guide/01-component-api.md → guide/01-component-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ drawingApp.observe( 'height', redraw, { defer: true });
```

To observe on a nested component, use refs:

```html-no-repl
<Widget ref:widget/>
<script>
Expand All @@ -116,8 +117,8 @@ To observe on a nested component, use refs:
}
};
</script>

```

### component.on(eventName, callback)

Allows you to respond to *events*:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
43 changes: 29 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
"name": "svelte.technology",
"version": "1.0.0",
"description": "Docs and examples for Svelte",
"main": "index.js",
"scripts": {
"start": "gobble",
"build": "gobble build -f dist",
"predeploy": "npm run build",
"predeploy:ci": "npm run build",
"deploy": "cd dist && now && now alias",
"deploy:ci": "cd dist && now --token $NOW_TOKEN && now alias --token $NOW_TOKEN"
"start": "node server",
"rollup": "rollup -c rollup/rollup.config.js && rollup -c rollup/rollup.config.codemirror.js",
"rollup:dev": "export DEV=true && rollup -c rollup/rollup.config.js -w",
"dev": "npm run rollup:dev & ( export DEV=true && node scripts/prep && node server )",
"prep": "node scripts/prep",
"predeploy": "npm run prep",
"predeploy:ci": "npm run prep",
"stage": "npm run prep && npm run rollup && now",
"deploy": "now && now alias",
"deploy:ci": "now --token $NOW_TOKEN && now alias --token $NOW_TOKEN"
},
"repository": {
"type": "git",
Expand All @@ -26,27 +29,39 @@
"homepage": "https://github.com/sveltejs/svelte.technology#readme",
"devDependencies": {
"chalk": "^1.1.3",
"clean-css": "^4.0.8",
"compression": "^1.6.2",
"eslint": "^3.17.1",
"eslint-plugin-import": "^2.2.0",
"gobble": "^0.12.0",
"gobble-cli": "^0.8.0",
"gobble-concat": "^0.4.1",
"gobble-postcss": "^0.3.0",
"gobble-rollup": "^0.40.0",
"gobble-uglifyjs": "^0.2.1",
"express": "^4.15.2",
"highlight.js": "^9.10.0",
"html-entities": "^1.2.0",
"marked": "^0.3.6",
"now": "^4.7.1",
"postcss-clearfix": "^1.0.0",
"postcss-import": "^9.1.0",
"postcss-nested": "^1.0.0",
"rollup": "^0.41.5",
"rollup-plugin-buble": "^0.15.0",
"rollup-plugin-commonjs": "^8.0.2",
"rollup-plugin-json": "^2.1.0",
"rollup-plugin-svelte": "^1.6.0"
"rollup-plugin-node-resolve": "^2.0.0",
"rollup-plugin-svelte": "^1.6.0",
"rollup-plugin-uglify": "^1.0.1",
"rollup-watch": "^3.2.2",
"uglify-js": "^2.8.12"
},
"dependencies": {
"codemirror": "^5.24.2",
"curl-amd": "^0.8.12",
"roadtrip": "^0.3.4",
"svelte": "^1.11.2"
},
"now": {
"alias": "svelte.technology",
"files": [
"public",
"server"
]
}
}
1 change: 1 addition & 0 deletions public/blog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"slug":"frameworks-without-the-framework","metadata":{"title":"Frameworks without the framework: why didn't we think of this sooner?","description":"You can't write serious applications in vanilla JavaScript without hitting a complexity wall. But a compiler can do it for you.","pubdate":"2016-11-26","author":"Rich Harris","authorURL":"https://twitter.com/Rich_Harris","dateString":"Fri Nov 25 2016"}}]
1 change: 1 addition & 0 deletions public/blog/frameworks-without-the-framework.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"html":"<blockquote>\n<p>Wait, this new framework has a <em>runtime</em>? Ugh. Thanks, I&#39;ll pass.\n<strong>– front end developers in 2018</strong></p>\n</blockquote>\n<p>We&#39;re shipping too much code to our users. Like a lot of front end developers, I&#39;ve been in denial about that fact, thinking that it was fine to serve 100kb of JavaScript on page load – just use <a href=\"https://twitter.com/miketaylr/status/227056824275333120\">one less .jpg!</a> – and that what <em>really</em> mattered was performance once your app was already interactive.</p>\n<p>But I was wrong. 100kb of .js isn&#39;t equivalent to 100kb of .jpg. It&#39;s not just the network time that&#39;ll kill your app&#39;s startup performance, but the time spent parsing and evaluating your script, during which time the browser becomes completely unresponsive. On mobile, those milliseconds rack up very quickly.</p>\n<p>If you&#39;re not convinced that this is a problem, follow <a href=\"https://twitter.com/slightlylate\">Alex Russell</a> on Twitter. Alex <a href=\"https://twitter.com/slightlylate/status/728355959022587905\">hasn&#39;t been making many friends in the framework community lately</a>, but he&#39;s not wrong. But the proposed alternative to using frameworks like Angular, React and Ember – <a href=\"https://www.polymer-project.org/1.0/\">Polymer</a> – hasn&#39;t yet gained traction in the front end world, and it&#39;s certainly not for a lack of marketing.</p>\n<p>Perhaps we need to rethink the whole thing.</p>\n<h2 id=\"what-problem-do-frameworks-really-solve-\">What problem do frameworks <em>really</em> solve?</h2>\n<p>The common view is that frameworks make it easier to manage the complexity of your code: the framework abstracts away all the fussy implementation details with techniques like virtual DOM diffing. But that&#39;s not really true. At best, frameworks <em>move the complexity around</em>, away from code that you had to write and into code you didn&#39;t.</p>\n<p>Instead, the reason that ideas like React are so wildly and deservedly successful is that they make it easier to manage the complexity of your <em>concepts</em>. Frameworks are primarily a tool for structuring your thoughts, not your code.</p>\n<p>Given that, what if the framework <em>didn&#39;t actually run in the browser</em>? What if, instead, it converted your application into pure vanilla JavaScript, just like Babel converts ES2016+ to ES5? You&#39;d pay no upfront cost of shipping a hefty runtime, and your app would get seriously fast, because there&#39;d be no layers of abstraction between your app and the browser.</p>\n<h2 id=\"introducing-svelte\">Introducing Svelte</h2>\n<p>Svelte is a new framework that does exactly that. You write your components using HTML, CSS and JavaScript (plus a few extra bits you can <a href=\"/guide\">learn in under 5 minutes</a>), and during your build process Svelte compiles them into tiny standalone JavaScript modules. By statically analysing the component template, we can make sure that the browser does as little work as possible.</p>\n<p>The <a href=\"http://svelte-todomvc.surge.sh/\">Svelte implementation of TodoMVC</a> weighs 3.6kb zipped. For comparison, React plus ReactDOM <em>without any app code</em> weighs about 45kb zipped. It takes about 10x as long for the browser just to evaluate React as it does for Svelte to be up and running with an interactive TodoMVC.</p>\n<p>And once your app <em>is</em> up and running, according to <a href=\"https://github.com/krausest/js-framework-benchmark\">js-framework-benchmark</a> <strong>Svelte is fast as heck</strong>. It&#39;s faster than React. It&#39;s faster than Vue. It&#39;s faster than Angular, or Ember, or Ractive, or Preact, or Riot, or Mithril. It&#39;s competitive with Inferno, which is probably the fastest UI framework in the world, for now, because <a href=\"https://twitter.com/trueadm\">Dominic Gannaway</a> is a wizard. (Svelte is slower at removing elements. We&#39;re <a href=\"https://github.com/sveltejs/svelte/issues/26\">working on it</a>.)</p>\n<p>It&#39;s basically as fast as vanilla JS, which makes sense because it <em>is</em> vanilla JS – just vanilla JS that you didn&#39;t have to write.</p>\n<h2 id=\"but-that-s-not-the-important-thing\">But that&#39;s not the important thing</h2>\n<p>Well, it <em>is</em> important – performance matters a great deal. What&#39;s really exciting about this approach, though, is that we can finally solve some of the thorniest problems in web development.</p>\n<p>Consider interoperability. Want to <code>npm install cool-calendar-widget</code> and use it in your app? Previously, you could only do that if you were already using (a correct version of) the framework that the widget was designed for – if <code>cool-calendar-widget</code> was built in React and you&#39;re using Angular then, well, hard cheese. But if the widget author used Svelte, apps that use it can be built using whatever technology you like. (On the TODO list: a way to convert Svelte components into web components.)</p>\n<p>Or <a href=\"https://twitter.com/samccone/status/797528710085652480\">code splitting</a>. It&#39;s a great idea (only load the code the user needs for the initial view, then get the rest later), but there&#39;s a problem – even if you only initially serve one React component instead of 100, <em>you still have to serve React itself</em>. With Svelte, code splitting can be much more effective, because the framework is embedded in the component, and the component is tiny.</p>\n<p>Finally, something I&#39;ve wrestled with a great deal as an open source maintainer: your users always want <em>their</em> features prioritised, and underestimate the cost of those features to people who don&#39;t need them. A framework author must always balance the long-term health of the project with the desire to meet their users&#39; needs. That&#39;s incredibly difficult, because it&#39;s hard to anticipate – much less articulate – the consequences of incremental bloat, and it takes serious soft skills to tell people (who may have been enthusiastically evangelising your tool up to that point) that their feature isn&#39;t important enough. But with an approach like Svelte&#39;s, many features can be added with absolutely no cost to people who don&#39;t use them, because the code that implements those features just doesn&#39;t get generated by the compiler if it&#39;s unnecessary.</p>\n<h2 id=\"we-re-just-getting-started\">We&#39;re just getting started</h2>\n<p>Svelte is very new. There&#39;s a lot of work still left to do – creating build tool integrations, adding a server-side renderer, hot reloading, transitions, more documentation and examples, starter kits, and so on.</p>\n<p>But you can already build rich components with it, which is why we&#39;ve gone straight to a stable 1.0.0 release. <a href=\"/guide\">Read the guide</a>, <a href=\"/repl\">try it out in the REPL</a>, and head over to <a href=\"https://github.com/sveltejs/svelte\">GitHub</a> to help kickstart the next era of front end development.</p>\n","metadata":{"title":"Frameworks without the framework: why didn't we think of this sooner?","description":"You can't write serious applications in vanilla JavaScript without hitting a complexity wall. But a compiler can do it for you.","pubdate":"2016-11-26","author":"Rich Harris","authorURL":"https://twitter.com/Rich_Harris","dateString":"Fri Nov 25 2016"},"slug":"frameworks-without-the-framework"}
Loading