Code Monkey home page Code Monkey logo

svelte's Introduction

Cybernetically enhanced web apps: Svelte

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.

Roadmap

You may view our roadmap if you'd like to see what we're currently working on.

Contributing

Please see the Contributing Guide and the svelte package for information on contributing to Svelte.

svelte.dev

The source code for https://svelte.dev lives in the sites folder, with all the documentation right here. The site is built with SvelteKit.

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

svelte's People

Contributors

antony avatar baseballyama avatar benmccann avatar btk5h avatar conduitry avatar dependabot[bot] avatar dreamindani avatar dummdidumm avatar ekhaled avatar emiltholin avatar geoffrich avatar github-actions[bot] avatar gtm-nayan avatar ignatiusmb avatar jacwright avatar jches avatar lukeed avatar mindrones avatar mrkishi avatar navorite avatar ngtr6788 avatar paulbgd avatar pngwn avatar puruvj avatar rich-harris avatar swatinem avatar tanhauhau avatar tivac avatar trueadm avatar zxbodya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svelte's Issues

Illegal source: same filename, different contents

When using the filename option of the compiler I get the error Error: Illegal source: same filename (App.html), different contents.

  const svelte = require('svelte')
  const result = svelte.compile('<h1>Hello {{name}}!</h1>', {
    filename: 'App.html',
    format: 'cjs',
    name: 'App',
  })

I digged into it and it looks like the error is thrown by 'magic-string', and the reason is because compiler/generate/index.js is calling Bundle.addSource twice with the same options.filename, the first time when adding the intro and the second time when adding each part

HTMLElement.style is readonly

I noticed the REPL wasn't working in Safari 10.0.1 (11602.2.14.0.7). Execution gets to:

function renderMainFragment ( root, component, target ) {
	var div = document.createElement( 'div' );
	div.setAttribute( 'svelte-1546246679', '' );
	div.className = "left";
	div.style = "width: " + ( root.verticalDividerPos ) + "%;";

…where it blows up with TypeError: Attempted to assign to readonly property.

This error appears to agree with the specs. CSS Object Model Level 2 defines the element style attribute to be readonly, offering mutability via the CSSStyleDeclaration provided by the style attribute rather than the style attribute itself. HTML5's global style attribute definition references CSSOM for the style IDL instead of explicitly stating it, though it includes a non-normative section describing style as having a getter with no setter:

element.style
Returns a CSSStyleDeclaration object for the element's style attribute.

MDN's style page describes "Setting style" as a thing which one can do, but explains that this is really just shorthand:

Styles can be set by assigning a string directly to the style property (as in elt.style = "color: blue;" ), which forwards it as el.style.cssText = "color:blue;", though it returns a CSSStyleDeclaration object which is read-only.

Probably this code should say .style.cssText="" instead of .style="".

Self-references/partials

An interesting point raised in this article – how can you have tree-like structures without hardcoding the depth of the tree?

Certainly should be possible within Svelte's architecture – possibly using a partial or maybe some sigil that causes the component to render itself (<@Self nodes='{{child.nodes}}'/>, or something)

HTML preprosessor support

I know it's very subjective - but I'm a huge advocate of Pug or JSX, anything that can help me write HTML!

Would be kind of nice to be able to write my templates with Pug, and have Svelte interpret that, whether or not it's an extra build step or not.

Example:

HelloWorld.pug

.my-app
   h1 {{hello}}

And being able to import that into a HelloWorld.js file

import HelloWorld from './HelloWorld.pug';

new HelloWorld({
   target: document.body,
   data: {
      hello: 'World'
   }
});

My only concern is writing JavaScript in Pug is terrible, so like isolate the template element to Pug and the JS, events, handlers, etc... to a JS file.

Need fix in Nested Component tutorial

In the tutorial,
https://svelte.technology/guide#scoped-styles

Could you add some code for the missing code in Widget.html as I assume it should be not HTML?

Widget.html

<div class='widget-container'>
  <Widget foo bar='static' baz='{{dynamic}}'/>
</div>

<script>
  import Widget from './Widget.html';

  export default {
    data () {
      return {
        dynamic: 'this can change'
      }
    },

    components: {
      Widget
    }
  };
</script>

It was getting an error, wasn't sure if the tutorial have some missing code?

svelte compile --format iife wjs.html > wjs.js
compiling wjs.html...
No name was supplied for imported module './Widget.html'. Guessing 'Widget', but you should use options.globals

Rely less on anchors

Currently, Svelte peppers the DOM with comments for every {{#if..}} or {{#each...}} block:

<!--#if visible-->

In many cases (e.g. where the block is that last thing in the element's fragment, or where the block is followed by an element that is never removed) that's unnecessary.

Nested components

It should be possible to do this:

<div class='widget-container'>
  <Widget ref:widget bind:foo='bar' baz='42' thing='{{dynamic}}'/>
</div>

<script>
  import Widget from './Widget.html';

  export default {
    components: { Widget }
  };
</script>

SSR and progressive enhancement

SSR could potentially be something like this:

require( 'svelte/ssr/register' );

const renderWidget = require( './components/Widget.html' );
const html = renderWidget({
  foo: 1,
  bar: 2
});

Not exactly sure how progressive enhancement would be implemented, and whether it can be done in a zero-cost way, but it'd be pretty cool. I don't know whether it looks more like this (i.e. all components can be rendered as progressive enhancements)...

const widget = new Widget({
  target: document.querySelector( 'main' ),
  enhance: true
});

...or this (i.e. only components that we know up-front we will want to use that way get the extra code):

<!-- Widget.html -->
<p>i am a widget</p>

<script>
  export default {
    enhance: true,
    // ...
  };
</script>

More two-way binding

Currently only a few <input> types are supported – need to handle textareas, selects, contenteditable, etc etc...

AMD, CommonJS, UMD and IIFE output formats

Much as I'd like to not do this, it'll be much easier for people to understand Svelte if they can generate executable code directly via the command line, rather than expecting them to already be using an ES module bundler.

API:

import * as svelte from 'svelte';

const { code, map } = svelte.compile( source, {
  format: 'amd',
  amd: 'some-id'
});

const { code, map } = svelte.compile( source, {
  format: 'iife',
  name: 'MyComponent'
});

We're already using the name option to control constructor name, it would just become required for IIFE and UMD bundles.

Question: Duplicate code elimination across npm modules

Coming from your blog post about framework-less frameworks I was struggling to understand your concept of "interoperability".

Considering the fact that you might load five published modules embedding partially the same functionality, how do you ensure to not have duplicated code being bundled up and therefore blocking the browser again while parsing a lot of duplications?

That starts of with using same methods from packages (e.g. something from react, or just some lodash.uniq or so), which could be some kind of combined (though you'd lose the version independence) and ends in "custom functionality" that does semantically the same (which I consider unable to combine, as you'd have to mathematically prove two functions operate the same on any given input).

With todays ecosystem of JS I don't think that would decrease the bundle sizes for any decent sized real-world project.

I might be wrong, then I would love to be educated on how you guys handle this - because the intention is great!

Non-mustache delimiters?

Seems a few people have had a negative initial reaction to Svelte thinking that it was using 'proper' Mustache, which is a very restrictive language with some interesting syntax, rather than just using {{ and }} as delimiters around dynamic content and #if/#each blocks.

It might be worth considering an alternative, so that people aren't confused. Not sure what it'd be though

Events

Need to add publish/subscribe functionality. Also, need to have a way to listen to events from child components, perhaps the same way Ractive does it:

<Widget on:select='select($1)'/>

Possible to define key parameter for each?

With Angular you can use track by with ng-repeat and with React the key parameter to reorder/reuse DOM elements. Does Svelte have reordering/reusing option with each?

Question: Philosophy

What would be svelte's differences over Vue & Ractive? I'm excited would love to know if there are any plans for supporting dynamic components?

An example would be a global component that loads in dynamically and then appears in other components that have it in their template syntax.

Component layout
{{sidebar}}

Moments later sidebar.js loads on the page and sets itself as the global sidebar component. Which it then appears in the layout.

This is how my current projects/apps work with some sugar on-top of Ractive; to get it to play nicely. The idea is that the app builds itself over time based on what it needs when it needs it. The new .reset methods in (Ractive) are a huge plus for getting all of that to work especially the hot-reloading I have made. Would love to see that same functionality or even a step in the dynamic direction.

Standalone vs non-standalone

Having zero runtime dependencies is really nice – it makes the generated code easier to follow and more versatile. Optionally, though, it might be good to offer builds that reduce code duplication – for example, the observe code is the same everywhere, and there are a few DOM helpers that could live externally.

Parent data should (probably) override child data

In this situation...

<!-- App.html -->
<Counter bind:count='x'/>
<p>count: {{x}}</p>

<script>
  import Counter from './Counter.html';

  export default {
    data: () => ({
      x: 10
    }),

    components: {
      Counter
    }
  };
</script>
<!-- Counter.html -->
<button on:click='set({ count: count + 1 })'>+1</button>

<script>
  export default {
    data: () => ({
      count: 0
    })
  };
</script>

...the value of x in App.html should be used, rather than the default value in Counter.html.

Rename onrender/onteardown to oncreate/ondestroy

This is a very subjective issue and probably deeply affected by my experience with React, but the name onrender was quite confusing to me. I presumed that onrender would be called every time the component's DOM changed (i.e. every time it is rendered to HTML) rather than just once when the component is added to the document. (By the way, I presume that it's only called when the component is added to the doc based on the code samples; the documentation does not say one way or another.)

Two suggestions:

  1. Change the documentation's "Lifecycle Hooks" section so that it says clearly exactly when the lifecycle hook functions are called.
  2. Consider renaming onrender to onsetup. In my experience, "setup" is more usually used as a counterpart to "teardown". Another possibility would be something like onaddtodocument and onremovefromdocument.

As I say, this is super subjective, but it was legitimately confusing to me while reading over code, even after I figured out that onrender is only called on setup.

Thanks so much!

Extra slash in the generated JS code

True, there is an extra slash being generated in the Hello world\! based on the svelte tutorial.
Seem like there is a lot of events in the generated JS code which can be confuse for newbie, I'm half-confuse so it would be helpful to explain the generated JS in the tutorials.

Option to prevent two-way binding?

A lot of people have internalized the FUD around two-way binding to the extent that they're turned off Svelte altogether, notwithstanding the fact that it's optional and explicitly opt-in. I wonder if the compiler should have an option that prevents bindings from being used, so the 'we lost our second round of financing because a junior dev added a bind: directive' scenario doesn't arise

Custom element interop

It might be possible to do this sort of thing:

import define from 'svelte/custom-elements/define.js';
import MyComponent from './components/MyComponent.html';

define( 'my-component', MyComponent );

Svelte might mean that custom elements finally make sense... no need to choose between a) writing reams of vanilla JS or b) using a framework that defeats the object of using custom elements

Transitions

A UI library needs a transition system. Ideally it would have the following features:

  • transition code shouldn't be deeply intertwined with the rest of the code (as in Ractive)
  • should facilitate JS or CSS transitions
  • should have zero cost for people who aren't using transitions
  • transition plugins should be easy to write
  • control over order (e.g. Vue has out-in, which is nice – could get even more granular for staggered transitions)
  • nice-to-have – abortable/reversable transitions (e.g. if something is fading out because you toggled visible, and you toggle it again before the fade completes, it'd be great to unfade the same element, rather than letting the fade complete and rendering a new element)
  • some way to access the transitions in such a way that you can do advanced stuff like transitioning one element into another, a la Ramjet

Proposed syntax, following that used by existing directives:

{{#if visible}}
  <div in:fade='{duration:200}' out:fly='{x:100,easing:'elastic'}'>hello!</div>
{{/if}}

{{{triples}}}

We'll eventually need some way to inject arbitrary (sanitized? or is that the dev's responsibility?) HTML

Development warnings

There are a few things that can't be caught with static analysis, such as missing data on first render. Is better if we only check those things in development mode, since it's unnecessary code in production otherwise.

Deep setting/getting/observing

Don't quite know how important this is, and whether it justifies the extra complexity it would entail:

component.observe( 'some.deep.keypath', console.log );
component.set( 'some.deep.keypath', 42 );
const answer = component.get( 'some.deep.keypath' );

For now I'm inclined not to bother with it, but I'll leave this issue here anyway in case I change my mind.

Idea: create more functional code for fragments

One thing that actually bothers me when looking at the svelte output is that it uses closures for the update and teardown methods, which might be ok for minification, because it can minify all the variable names, but is actually bad for code reuse inside the VM.
I also experimented with a similar code generation idea over a year ago, and I thought to myself, why not make those things functional, like this:

  • Fragment.create(…) => Instance appends to the DOM and returns an object with the important dom elements
  • Fragment.update(Instance, …) instead of using closure upvars or this, we just pass in the object with the dom elements
  • Fragment.teardown(Instance) same here

Also, thinking about #1 and #9, we could also have these methods:

  • Fragment.toString(…) will render to a string for SSR
  • Fragment.hidrate(…) => Instance will create the element map from already existing DOM elements

I think this can be done internally without changing the public API of components.

What do you think @Rich-Harris?

Would you like some webpack'y help?

Hey @Rich-Harris!!!

This looks pretty neat, I noticed general output from the REPL was globally stuff. I haven't dove deep enough to learn more about svelte (maybe I should). Regardless, I'm sure you will have at least a few requests for webpack'y things, so we are devoted to helping you out in those regards. Let me know if we can be of assistance (if even needed).

Constructors rather than factories

Having gone back and forth on this, I think it makes more sense for components to be constructors rather than factories – i.e. instead of this...

export default function createComponent ( options ) {
  // ...
}

...this:

export default function Widget ( options ) {
  // ...
}

This makes Svelte components slightly more familiar for people coming from e.g. Ractive or Vue, and has this important benefit:

// awkward naming
import createWidget from './Widget.html';
const widget = createWidget(...);

// better
import Widget from './Widget.html';
const widget = new Widget(...);

(Capitalising filenames makes sense because inline components should also be capitalised, i.e. <Widget foo='bar'/> – this is a good way to visually distinguish elements from components in a way that doesn't make them look like web components.)

Use innerHTML for static elements?

Would need to compare performance, but it's entirely possible that in cases where you just have a bunch of static markup inside an element, it would be quicker to use node.innerHTML = markup rather than constructing the DOM programmatically.

Only set attributes that have actually changed

I thought browsers might optimise this away, but it seems that – at least in some cases, such as an iframe's srcdoc attribute – invoking the setter causes unnecessary work to happen

License statement on generated code?

Can @Rich-Harris confirm that the generated code would not fall under the MIT license of this project?

Ideally I would like to see top-level header blocks such as https://github.com/sveltejs/svelte/blob/master/compiler/generate/index.js#L385-L476 marked with a public license such as CC0 which should be valid in places such as Germany ref: http://opensource.stackexchange.com/questions/4136/whats-the-status-of-cc0-under-the-eyes-of-german-law/4214#4214.

An additional improvement would be to move this and any other verbatim "header blocks" to a referenced external dependency.

Working with template on serverside

If I still using Swift server side, on first load, it will need to show news, update, etc. I have to retrieve from DB and it will pass to server side template for rendering.

For Svelte to work, I would have to compile with Svelte first before porting to server side to add more coding on the home page?

{{yield}}

Once #4 is implemented, need to figure out a way to yield, without which component composition is somewhat limited:

{{#if error}}
  <Modal>
    <p>something went wrong!</p>
    <button on:click='set({ error: null })'>dismiss</button>
  </Modal>
{{/if}}

In Ractive that's done with the {{yield}} operator, and it works well. For simplicity's sake, probably best just to have a single yield per component (i.e. no named yields, and no yields in #each blocks) for now.

Further improve bundle size

I was looking at the js-framework-benchmark output for Svelte and it got me thinking, take this:

function renderMainFragment ( root, component, target ) {
	var div = document.createElement( 'div' );
	div.className = "jumbotron";
	
	var div1 = document.createElement( 'div' );
	div1.className = "row";
	
	var div2 = document.createElement( 'div' );
	div2.className = "col-md-6";
...
}

Could you not simplify this somewhat, to be:

function elementWithClass ( tag, className ) {
 var elem = document.createElement( tag );
 elem.className = className;

 return elem;
}
function renderMainFragment ( root, component, target ) {
  var div = elementWithClass('div', 'jumbotron');
  var div1 = elementWithClass('div', 'row');
  var div2 = elementWithClass('div', 'col-md-6');
...
}

This is actually something the old Inferno's used to do (would compile vdom to client-side code) with t7. It would look ahead to see if there are many common patterns (like an element with a className) and build dedicated factories for them. Performance actually improved in many cases, as the function for the component was small enough when minified to be inlined by most JavaScript engines.

Scoped CSS

Same as Ractive components. A few thoughts:

  • Svelte can probably be a bit smarter than Ractive about knowing whether it needs to 'double up' selectors (i.e. Ractive isn't sure whether a given scoped style applies to a top-level element or only to its children, so it expands .the-selector {...} to both [data-gubbins=xyz].the-selector {...} and [data-gubbins=xyz] .the-selector {...} (note the space in the second example)
  • Basing the unique ID (used for scoping) on a hash of the template might be a nice way to solve the problem of scoped CSS in server-rendered HTML matching what gets rendered to the DOM
  • The CSS parser/transformer doesn't need to be compact enough to run in the browser, so we can have fun with transformations and optimisations (e.g. minifying CSS)
  • We could warn about unused selectors etc

refs can be unset incorrectly

In a case like this...

{{#if foo}}
  <div ref:bar>...</div>
{{else}}
  <div ref:bar>...</div>
{{/if}}

...the bar ref can be set to null by the outgoing fragment after it's been updated by the incoming fragment

REPL bug caused by `dynamicAttributes`?

The REPL's output view is not updated when the selected gist is changed.

This seems to be caused because the compiler generates the following code for the Element:

update: function(changed, root) {
	var codeMirror_changes = {};
	if ('undefined'in changed) {
		codeMirror_changes.code = root.compiled.code;
	}
	if (Object.keys(codeMirror_changes).length) {
		codeMirror.set(codeMirror_changes);
	}
}

Apparently, the dynamicAttributes end up with undefined dependencies for deep object paths.

I'm afraid I haven't been able to dive deep enough to attempt a PR, yet. Sorry! But if you have any directions and feel like this would be a productive first contribution, I can certainly try. 👍

Documentation suggestion: clearly state how scope works in Svelte HTML files

Congrats on your launch! I'm excited by the idea and trying to wrap my brain around the concepts.

Take it or leave it, but one thing that was quite confusing to me while reading the docs was how variables are scoped and this is managed, and I think it could be made clearer. A few questions, for example:

  • Are top-level variables in the <script> chunks addressable in html?
  • What about named exports from the <script> chunk?
  • The <script> default export exposes data, helpers, and methods to the html at the top level. It also exposes computed, but as values, not methods. Are any other parts of the default export exposed, and if so, how?
  • It seems that methods are called with a this pointer. Does this always refer to the component, or does it sometimes refer to the DOM node, as would normally happen in event handlers? Do any other methods get this pointers (helpers or function values in data)?
  • What happens in case of name collisions in data, helpers, methods, and computed?

I know this may seem pedantic, but questions like these are genuinely what I was thinking about as I read the doc and the TodoMVC code. The magic that connects the script section to the HTML template is the most confusing part to me by far, at least at this early point.

Thanks again for your hard work!

Additional methods

Convenience methods could be added like so – easy enough for people who need them, but zero cost for people who don't:

<script>
  import { animate, toggle, add, subtract, push, pop } from 'svelte/extras/methods.js';

  export default {
    methods: { animate, toggle, add, subtract, push, pop }
  };
</script>

Validation

Should have a validation step that produces errors/warnings as appropriate, before the component is generated. For example, data should always be a function expression, methods shouldn't clash with builtins, computed properties can't have cyclical dependencies, etc etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.