Cybernetically enhanced web apps

Overview

Cybernetically enhanced web apps: Svelte npm version license Chat

What is Svelte?

Svelte is a new way to build web applications. It's a compiler that takes your declarative components and converts them into efficient JavaScript that surgically updates the DOM.

Learn more at the Svelte website, or stop by the Discord chatroom.

Supporting Svelte

Svelte is an MIT-licensed open source project with its ongoing development made possible entirely by fantastic volunteers. If you'd like to support their efforts, please consider:

Funds donated via Open Collective will be used for compensating expenses related to Svelte's development such as hosting costs. If sufficient donations are received, funds may also be used to support Svelte's development more directly.

Development

Pull requests are encouraged and always welcome. Pick an issue and help us out!

To install and work on Svelte locally:

git clone https://github.com/sveltejs/svelte.git
cd svelte
npm install

Do not use Yarn to install the dependencies, as the specific package versions in package-lock.json are used to build and test Svelte.

To build the compiler and all the other modules included in the package:

npm run build

To watch for changes and continually rebuild the package (this is useful if you're using npm link to test out changes in a project locally):

npm run dev

The compiler is written in TypeScript, but don't let that put you off — it's basically just JavaScript with type annotations. You'll pick it up in no time. If you're using an editor other than Visual Studio Code, you may need to install a plugin in order to get syntax highlighting and code hints, etc.

Running Tests

npm run test

To filter tests, use -g (aka --grep). For example, to only run tests involving transitions:

npm run test -- -g transition

svelte.dev

The source code for https://svelte.dev, including all the documentation, lives in the site directory. The site is built with Sapper.

Is svelte.dev down?

Probably not, but it's possible. If you can't seem to access any .dev sites, check out this SuperUser question and answer.

License

MIT

Comments
  • Passing class to components

    Passing class to components

    I'm not sure if this isn't related to other issues, but I checked many of them and neither covers what I need.

    I come from React and CSS-Modules, where passing down styles is really easy. Just pass down className prop, and css-modules will figure out and hash styles to avoid conflicts.

    In svelte I cannot pass down classes to component through class prop, like so: https://svelte.dev/repl/1d0b80898137445da24cf565830ce3f7?version=3.4.2

    There are some solutions to pass styles, like using :global, but it's fragile: if anywhere inside child component will have class named same, it will cause problems. Sure, we can use BEM or another approach, be very careful with global styles, but I imagine it can happen automagically (like with CSS-Modules).

    Another approach is to add add divs inside componetns, but consider Col component from example above. If we have:

    <style>
        div {
            background: tomato;
        }
    </style>
    
    <Col>
        <div>content</div>
    </Col>
    

    content will get background, but also will have unwanted gap caused by Col padding. And quickly code will have many unwanted divs.

    Why I think it matters? I wrote hundreds of Rect components and what I learned is that Componets should be able to be styled by developer who is using it. Adding BEM layer or sth else is for me unnecessary work. And may cause conflicts. Imagine dev who use BEM. There may be rare cases when his (global) styles are named same as component's and interfere.

    in conclusion It will be great to pass down classes, not be global, but with some unique id.

    PS. I found modular-css package, but it's for svelte2, and I'm not sure if it will works with passing down styles to components.

    pending clarification 
    opened by wysher 126
  • Syntax changes

    Syntax changes

    Update 12 April

    Most of these decisions are fairly settled at this point — you can see a summary here.

    Original issue follows:


    I've referred to this obliquely in other issues, Gitter, etc, but haven't quite got to the point of starting a proper discussion about it.

    Essentially, for version 2 I'd like to move away from the Mustache-esque template syntax to something a bit lighter and more modern, which boils down to using one curly brace instead of two:

    <h1 class={myClass}>Hello {name}!</h1>
    

    The success of JSX has proved that the second curly is unnecessary. Moreover, a lot of people — particularly those who have been exposed to React — have a visceral negative reaction to double curlies, many of them assuming that it brings with it all the limitations of crusty old languages like Mustache and Handlebars, where you can't use arbitrary JavaScript in expressions.

    We would also put an end to this sort of thing — component properties being typecast — at the same time. (See #657).

    Quoted attributes

    At present, Svelte allows you to quote attributes and properties for the sake of your syntax highlighter:

    <Widget x={{y < z ? }}>this generally breaks highlighting</Widget>
    <Widget x="{{y < z ? }}">this generally breaks highlighting</Widget>
    

    I'd suggest that we keep that behaviour, so as not to force people to adopt additional tooling (which doesn't yet exist anyway). The same goes for directive arguments — these would be unchanged.

    Control flow

    It's less clear what to do about if/else/elseif, each, and await/then/catch. We could of course do this...

    {#if foo}
      <p>foo!</p>
    {else}
      <p>not foo!</p>
    {/if}
    

    ...though part of me feels like we're just continuing to accept the premise of Handlebars, and that there's a more natural approach waiting to be discovered. Just for the sake of argument:

    #if (foo) {
      <p>foo!</p>
    } else if (bar) {
      <p>bar!</p>
    } else {
      <p>neither foo nor bar!</p>
    }
    
    <ul>
      #each (cats as cat) {
        <li><a target='_blank' href={cat.video}>{cat.name}</a></li>
      }
    </ul>
    
    #await (promise) {
      <p>wait for it...</p>
    } then (answer) {
      <p>the answer is {answer}!</p>
    } catch (error) {
      <p>well that's odd</p>
    }
    

    Maybe that makes you want to barf, I don't know. But I'd be very interested to hear everyone's ideas.

    Keyed each blocks

    I'm in favour of replacing @name with by name, as discussed in #703 — it has some clear advantages.

    Triples

    Triples could arguably be unchanged — if anything, the increased distinction between {text} and {{{html}}} is a good thing. Or we could go in a totally different direction like <{html}>. Eager to hear thoughts.

    Static tags

    #364 — briefly discussed, but never acted upon: the idea of adding syntax for declaring tags static, as a way of saying to the compiler 'this will never change after the initial render, don't worry about generating update code'. Would be nice if whatever choices we make preserve that possibility.

    Escaping

    If you needed a literal { character in your markup, you could always do {'{'}. (This is how it's done in React.) Or you could do &#123;, which is pleasingly easy to remember. Does there need to be some method of escaping beyond that?

    Migrating

    All this stuff should come with an simple, completely automated way to upgrade an existing template. There could be a CLI tool, and the REPL would detect old templates and show an 'upgrade' button.


    Obviously we shouldn't rush into anything. But changes like these are best made earlier on in a project's lifecycle, so I'm eager to hear what people think so that we can start making some progress. Thanks!

    opened by Rich-Harris 125
  • Outros undefined when transitioning to another page

    Outros undefined when transitioning to another page

    Couldn't get a REPL repro but If I try to navigate from https://smelte-8z4ib07lj.now.sh/components/tabs to any other page I get this error:

    index.mjs:629 Uncaught (in promise) TypeError: Cannot read property 'callbacks' of undefined
        at U (index.mjs:629)
        at Object.o (Waypoint.svelte:116)
        at hn (index.mjs:761)
        at Object.o (Image.svelte:27)
        at hn (index.mjs:761)
        at Object.o (tabs.c766b77c.js:1)
        at hn (index.mjs:761)
        at Object.o (TabButton.svelte:11)
        at hn (index.mjs:761)
        at Object.o (Tab.svelte:6)
    </details>
    

    At this line:

    function transition_out(block, local, callback) {
        if (block && block.o) {
            if (outroing.has(block))
                return;
            outroing.add(block);
            **outros.callbacks.push(() => {**
                outroing.delete(block);
                if (callback) {
                    block.d(1);
                    callback();
                }
            });
            block.o(local);
        }
    }
    

    Works https://smelte-8z4ib07lj.now.sh/components/tabs

    Doesn't https://smelte-ocubxglhw.now.sh/components/tabs

    Not sure what causes the error so I simply patched it by adding an extra check if outros.callbacks is set.

    opened by matyunya 83
  • [feature] Dynamic elements implementation <svelte:element>

    [feature] Dynamic elements implementation

    ~~Again I started to refactor the render_dom part. I think we should implement <svelte:element> as Element + dynamic tag completely for maintainability.~~ => DONE.


    This is based on https://github.com/sveltejs/svelte/pull/5481. I cleaned up the code and few changes.

    • FIx few bugs.

      • Maintain attributes and events when changed <svelte:element>'s tag.
      • Fix rendering place when uses named slot.
    • Return compile error if svelte:element has animate because <svelte:element> doesn't support it.

    • Stop to use DynamicElement classes. Because...

      • I tried to create a base class but bundled javascript was broken due to circular dependency.
      • To use DynamicElement without extending makes much duplicate code, therefore I added a feature to Element which can have a tag dynamically.
    • Add more tests

    Before submitting the PR, please make sure you do the following

    • [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
    • [x] Prefix your PR title with [feat], [fix], [chore], or [docs].
    • [x] This message body should clearly illustrate what problems it solves.
    • [x] Ideally, include a test that fails without this PR but passes with it.

    Tests

    • [x] Run the tests with npm test and lint the project with npm run lint
    opened by baseballyama 82
  • TypeScript Roadmap via LSP

    TypeScript Roadmap via LSP

    Goal: TypeScript-style tooling in Svelte

    Getting TS in Svelte might be a blocker for some, but I think the biggest underlaying advantage comes in that the "TS support" is just a stricter version of the JS tooling. Everyone using Svelte gets improvements in tooling from this, not just folks with TS.

    This proposal makes a strong separation between the tooling and the svelte compiler. It explicitly minimizes the impact on core in favor of moving live-DX complexity to a svelte language server.

    The language server provides editor support and CLI validation for working in svelte, not the core library svelte. This isn't a unique concept, it's based on the vue eco-system which has similar "extend HTML" constraints.

    This pattern also allows different maintainers to work on JS/TS tooling independent of the svelte core team (which is how we do it in GraphQL), making it a good place for people who want to contribute to step up and own some of the svelte core ecosystem.

    Three main steps to get there:

    1. Add support in core for transpiling TypeScript in tags script, but ignore type-checking. TS will always synchronously emit JS if it's reasonably legal JS. This is the only change required in core. When you encounter a TS script tag, you can look up whether they have TS/Babel in deps and throw if not. No need to force the dep.

    2. Create "svelte/svelte-language-tools" repo in main org:

      1. Add svelte-language-server
      2. Add svelte-vscode
      3. Create a new CLI tool which uses the LSP to validate - this makes LSP calls against all .svelte files to run TS/JS tooling for errors.
    3. Svelte Language Server improvements

    Rationale

    1. This is to allow the editor support to make that assumption out of the box, and for a user to be able to safely write <script lang="typescript"> knowing that it will work with the core.

    2. Adding TypeScript support to Svelte can take a lot of tips from prior art done on Vue. Vetur acts as the higher level tooling framework for both providing the JS and TS tooling support in scripts.

      This pattern keeps most of the work in the LSP level, which means all editors can use it, the vscode extension would just be one client of many.

      The language server could turn into @svelte/language-server and the vscode-svelte can get some more maintainers added so that deploys can be done by others. If folks have other popular IDE integrations, they could live in this repo too.

      svelte check adds a way to validate on CI, which can handle folks without the extension not accidentally breaking things. Because TS will always emit JS even if it has type errors, on purpose.

    3. This is basically a "draw the rest of the owl"

    Work on Svelte Lanaguge Server

    Luckily, both vscode-svelte and svelte-langauge-server have already been built and worked on by @UnwrittenFun and he's interested in moving those to the org. They both are solid foundations to build upon, from looking through the code.

    They're definitely good enough for JS today, and considerably better than nothing!

    I think one of the first blockers on making it something recommended by default, is finding a way to make sure that money-labels (reactive designators) are handled in both JS and TS.

    Because the $: syntax does more work than TypeScript can know about $: x = count + 1 would probably need transforming into something like const x = () => { count + 1 } as an in-memory transform, so that the variables exist in the "TS representation" of the LSP (but not on disk)

    HTMLx

    The quick route:

    I think you can get autocompletion, but I'm not sure how feasible typechecking would be here in a cheap way.

    For inside {} the LSP could make API requests to the known script tags above and request all the variables at the top level scope (basically the equivilient of adding a newline in that script and then checking what's available.)

    In theory you could type check each one by making a unique TS document for all of them, with exposed globals from the main script - but that could be quite slow, and it's hard to say how well that could scale.

    Longest term:

    How TypeScript handles the LSP-ish server is by embedding it into the core codebase, perhaps over time it makes sense to give the LSP deeper access to the svelte compiler, so that the LSP can ask it questions about the document "what variables are available in this eval context?" as (I guess) you must have some of that information to do the compilation.

    I'd see this as quite a long time away, and you can get a lot of value right now in the LSP without access to that.

    The svelte language server could eventually split into a htmlx-language-server and the svelte version would wrap with svelte specific cases.

    Things to think about

    This opens up a lot of legitimate questions "like how does the tooling support x and y" - the answer to most of them is "that is something the language-server would have to handle" - the language server would need to keep track of files, their exports and more - it'll be a cool an interesting project for folks who care about the DX at editor level.

    Anything in vetur today should be feasible for svelte.

    /cc @octref who works on Vetur, and might have some insight.

    meta 
    opened by orta 74
  • Proposal: dynamic elements `<svelte:element>`

    Proposal: dynamic elements ``

    Just recording this as a requested feature, since it comes up from time to time. Not actually saying we should do it, but would be good to track the discussion.

    Proposal for <svelte:element>

    <script>
      export let type = 'div';
    </script>
    
    <svelte:element this={type}>
      <slot></slot>
    </svelte:element>
    

    What are the actual use cases? Are there any drawbacks?

    feature request popular 
    opened by arxpoetica 61
  • TypeScript support

    TypeScript support

    This is intended to be a tracking issue for TypeScript support. Feel free to edit.

    • [ ] Writing TypeScript in