├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── README.md ├── appveyor.yml ├── content └── blog │ ├── 2016-11-26-frameworks-without-the-framework.md │ ├── 2017-08-07-the-easiest-way-to-get-started.md │ ├── 2017-09-06-the-zen-of-just-writing-css.md │ ├── 2017-12-31-sapper-towards-the-ideal-web-app-framework.md │ ├── 2018-04-18-version-2.md │ ├── 2018-12-26-svelte-css-in-js.md │ └── 2018-12-27-virtual-dom-is-pure-overhead.md ├── cypress.json ├── cypress ├── fixtures │ └── example.json ├── integration │ └── spec.js ├── plugins │ └── index.js └── support │ ├── commands.js │ └── index.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── client.js ├── components │ ├── Icon.html │ ├── InlineSvg.html │ └── TopNav.html ├── routes │ ├── _error.html │ ├── _layout.html │ ├── about.html │ ├── api │ │ └── blog │ │ │ ├── [slug].js │ │ │ ├── _posts.js │ │ │ └── index.js │ ├── auth │ │ └── me.json.js │ ├── blog │ │ ├── [slug].html │ │ ├── index.html │ │ └── rss.xml.js │ └── index.html ├── server.js ├── service-worker.js ├── template.html ├── user.js └── utils │ └── _process_markdown.js └── static ├── favicon.ico ├── favicon.png ├── global.css ├── icons ├── arrow-right.svg ├── check.svg ├── chevron.svg ├── collapse.svg ├── download.svg ├── dropdown.svg ├── expand.svg ├── flip.svg ├── fork.svg ├── link.svg └── save.svg ├── manifest.json ├── media └── rethinking-best-practices.jpg └── workers ├── bundler.js └── compiler.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "rules": { 4 | "indent": [2, "tab", { "SwitchCase": 1 }], 5 | "semi": [2, "always"], 6 | "keyword-spacing": [2, { "before": true, "after": true }], 7 | "space-before-blocks": [2, "always"], 8 | "no-mixed-spaces-and-tabs": [2, "smart-tabs"], 9 | "no-cond-assign": 0, 10 | "no-unused-vars": 2, 11 | "object-shorthand": [2, "always"], 12 | "no-const-assign": 2, 13 | "no-class-assign": 2, 14 | "no-this-before-super": 2, 15 | "no-var": 2, 16 | "no-unreachable": 2, 17 | "valid-typeof": 2, 18 | "quote-props": [2, "as-needed"], 19 | "one-var": [2, "never"], 20 | "prefer-arrow-callback": 2, 21 | "prefer-const": [2, { "destructuring": "all" }], 22 | "arrow-spacing": 2, 23 | "no-inner-declarations": 0 24 | }, 25 | "env": { 26 | "es6": true, 27 | "browser": true, 28 | "node": true, 29 | "mocha": true 30 | }, 31 | "extends": [ 32 | "eslint:recommended", 33 | "plugin:import/errors", 34 | "plugin:import/warnings" 35 | ], 36 | "plugins": ["svelte3"], 37 | "parserOptions": { 38 | "ecmaVersion": 8, 39 | "sourceType": "module" 40 | }, 41 | "settings": { 42 | "import/core-modules": ["svelte"], 43 | "svelte3/extensions": [".html"] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | __sapper__ 4 | cypress/videos 5 | cypress/screenshots -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "stable" 5 | env: 6 | global: 7 | - BUILD_TIMEOUT=10000 8 | install: 9 | - npm install 10 | - npm install cypress 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-v3-blog 2 | 3 | Based on version of the default [Sapper](https://github.com/sveltejs/sapper) template that uses Rollup instead of webpack. To clone it and get started: 4 | 5 | ```bash 6 | npx degit sveltejs/sapper-template#rollup my-app 7 | cd my-app 8 | npm install # or yarn! 9 | npm run dev 10 | ``` 11 | 12 | Open up [localhost:3000](http://localhost:3000) and start clicking around. 13 | 14 | Consult [sapper.svelte.technology](https://sapper.svelte.technology) for help getting started. 15 | 16 | *[Click here for the webpack version of this template](https://github.com/sveltejs/sapper-template)* 17 | 18 | ## Svelte Site 19 | 20 | sveltejs/svelte/site is the second anchestor of this repository. 21 | 22 | ## Structure 23 | 24 | Sapper expects to find three directories in the root of your project — `app`, `assets` and `routes`. 25 | 26 | 27 | ### app 28 | 29 | The [app](app) directory contains the entry points for your app — `client.js`, `server.js` and (optionally) a `service-worker.js` — along with a `template.html` file. 30 | 31 | 32 | ### assets 33 | 34 | The [assets](assets) directory contains any static assets that should be available. These are served using [sirv](https://github.com/lukeed/sirv). 35 | 36 | In your [service-worker.js](app/service-worker.js) file, you can import these as `assets` from the generated manifest... 37 | 38 | ```js 39 | import { assets } from './manifest/service-worker.js'; 40 | ``` 41 | 42 | ...so that you can cache them (though you can choose not to, for example if you don't want to cache very large files). 43 | 44 | 45 | ### routes 46 | 47 | This is the heart of your Sapper app. There are two kinds of routes — *pages*, and *server routes*. 48 | 49 | **Pages** are Svelte components written in `.html` files. When a user first visits the application, they will be served a server-rendered version of the route in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel. (Sapper will preload and cache the code for these subsequent pages, so that navigation is instantaneous.) 50 | 51 | **Server routes** are modules written in `.js` files, that export functions corresponding to HTTP methods. Each function receives Express `request` and `response` objects as arguments, plus a `next` function. This is useful for creating a JSON API, for example. 52 | 53 | There are three simple rules for naming the files that define your routes: 54 | 55 | * A file called `routes/about.html` corresponds to the `/about` route. A file called `routes/blog/[slug].html` corresponds to the `/blog/:slug` route, in which case `params.slug` is available to the route 56 | * The file `routes/index.html` (or `routes/index.js`) corresponds to the root of your app. `routes/about/index.html` is treated the same as `routes/about.html`. 57 | * Files and directories with a leading underscore do *not* create routes. This allows you to colocate helper modules and components with the routes that depend on them — for example you could have a file called `routes/_helpers/datetime.js` and it would *not* create a `/_helpers/datetime` route 58 | 59 | 60 | ## Rollup config 61 | 62 | Sapper uses Rollup to provide code-splitting and dynamic imports, as well as compiling your Svelte components. As long as you don't do anything daft, you can edit the configuration files to add whatever plugins you'd like. 63 | 64 | 65 | ## Production mode and deployment 66 | 67 | To start a production version of your app, run `npm run build && npm start`. 68 | 69 | You can deploy your application to any environment that supports Node 8 or above. As an example, to deploy to [Now](https://zeit.co/now), run these commands: 70 | 71 | ```bash 72 | npm install -g now 73 | now 74 | ``` 75 | 76 | 77 | ## Bugs and feedback 78 | 79 | Sapper is in early development, and may have the odd rough edge here and there. Please be vocal over on the [Sapper issue tracker](https://github.com/sveltejs/sapper/issues). 80 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | shallow_clone: true 4 | 5 | init: 6 | - git config --global core.autocrlf false 7 | 8 | build: off 9 | 10 | environment: 11 | matrix: 12 | # node.js 13 | - nodejs_version: stable 14 | 15 | install: 16 | - ps: Install-Product node $env:nodejs_version 17 | - npm install cypress 18 | - npm install 19 | -------------------------------------------------------------------------------- /content/blog/2016-11-26-frameworks-without-the-framework.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Frameworks without the framework: why didn't we think of this sooner? 3 | description: You can't write serious applications in vanilla JavaScript without hitting a complexity wall. But a compiler can do it for you. 4 | pubdate: 2016-11-26 5 | author: Rich Harris 6 | authorURL: https://twitter.com/Rich_Harris 7 | --- 8 | 9 | > Wait, this new framework has a *runtime*? Ugh. Thanks, I'll pass. 10 | > **– front end developers in 2018** 11 | 12 | We're shipping too much code to our users. Like a lot of front end developers, I've been in denial about that fact, thinking that it was fine to serve 100kb of JavaScript on page load – just use [one less .jpg!](https://twitter.com/miketaylr/status/227056824275333120) – and that what *really* mattered was performance once your app was already interactive. 13 | 14 | But I was wrong. 100kb of .js isn't equivalent to 100kb of .jpg. It's not just the network time that'll kill your app'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. 15 | 16 | If you're not convinced that this is a problem, follow [Alex Russell](https://twitter.com/slightlylate) on Twitter. Alex [hasn't been making many friends in the framework community lately](https://twitter.com/slightlylate/status/728355959022587905), but he's not wrong. But the proposed alternative to using frameworks like Angular, React and Ember – [Polymer](https://www.polymer-project.org/1.0/) – hasn't yet gained traction in the front end world, and it's certainly not for a lack of marketing. 17 | 18 | Perhaps we need to rethink the whole thing. 19 | 20 | 21 | ## What problem do frameworks *really* solve? 22 | 23 | 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's not really true. At best, frameworks *move the complexity around*, away from code that you had to write and into code you didn't. 24 | 25 | 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 *concepts*. Frameworks are primarily a tool for structuring your thoughts, not your code. 26 | 27 | Given that, what if the framework *didn't actually run in the browser*? What if, instead, it converted your application into pure vanilla JavaScript, just like Babel converts ES2016+ to ES5? You'd pay no upfront cost of shipping a hefty runtime, and your app would get seriously fast, because there'd be no layers of abstraction between your app and the browser. 28 | 29 | 30 | ## Introducing Svelte 31 | 32 | 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 [learn in under 5 minutes](/guide)), 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. 33 | 34 | The [Svelte implementation of TodoMVC](http://svelte-todomvc.surge.sh/) weighs 3.6kb zipped. For comparison, React plus ReactDOM *without any app code* 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. 35 | 36 | And once your app *is* up and running, according to [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) **Svelte is fast as heck**. It's faster than React. It's faster than Vue. It's faster than Angular, or Ember, or Ractive, or Preact, or Riot, or Mithril. It's competitive with Inferno, which is probably the fastest UI framework in the world, for now, because [Dominic Gannaway](https://twitter.com/trueadm) is a wizard. (Svelte is slower at removing elements. We're [working on it](https://github.com/sveltejs/svelte/issues/26).) 37 | 38 | It's basically as fast as vanilla JS, which makes sense because it *is* vanilla JS – just vanilla JS that you didn't have to write. 39 | 40 | 41 | ## But that's not the important thing 42 | 43 | Well, it *is* important – performance matters a great deal. What's really exciting about this approach, though, is that we can finally solve some of the thorniest problems in web development. 44 | 45 | Consider interoperability. Want to `npm install cool-calendar-widget` 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 `cool-calendar-widget` was built in React and you'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.) 46 | 47 | Or [code splitting](https://twitter.com/samccone/status/797528710085652480). It's a great idea (only load the code the user needs for the initial view, then get the rest later), but there's a problem – even if you only initially serve one React component instead of 100, *you still have to serve React itself*. With Svelte, code splitting can be much more effective, because the framework is embedded in the component, and the component is tiny. 48 | 49 | Finally, something I've wrestled with a great deal as an open source maintainer: your users always want *their* features prioritised, and underestimate the cost of those features to people who don't need them. A framework author must always balance the long-term health of the project with the desire to meet their users' needs. That's incredibly difficult, because it'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't important enough. But with an approach like Svelte's, many features can be added with absolutely no cost to people who don't use them, because the code that implements those features just doesn't get generated by the compiler if it's unnecessary. 50 | 51 | 52 | ## We're just getting started 53 | 54 | Svelte is very new. There'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. 55 | 56 | But you can already build rich components with it, which is why we've gone straight to a stable 1.0.0 release. [Read the guide](/guide), [try it out in the REPL](/repl), and head over to [GitHub](https://github.com/sveltejs/svelte) to help kickstart the next era of front end development. 57 | -------------------------------------------------------------------------------- /content/blog/2017-08-07-the-easiest-way-to-get-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The easiest way to get started with Svelte 3 | description: This'll only take a minute. 4 | pubdate: 2017-08-07 5 | author: Rich Harris 6 | authorURL: https://twitter.com/Rich_Harris 7 | --- 8 | 9 | Svelte is a [new kind of framework](/blog/frameworks-without-the-framework). Rather than putting a ` 14 | 15 | 16 | 17 | 18 | 19 | 20 | 40 | -------------------------------------------------------------------------------- /src/components/InlineSvg.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/components/TopNav.html: -------------------------------------------------------------------------------- 1 | 42 | 43 | 220 | 221 | 222 | 223 |
224 | 255 |
-------------------------------------------------------------------------------- /src/routes/_error.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | {status} 9 | 10 |
11 |

{status}

12 | 13 |

{error.message}

14 | 15 | {#if dev && error.stack} 16 |
{error.stack}
17 | {/if} 18 |
19 | -------------------------------------------------------------------------------- /src/routes/_layout.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | {#if path !== '/repl/embed'} 11 |