Coder Social home page Coder Social logo

sycamore-rs / sycamore Goto Github PK

View Code? Open in Web Editor NEW
2.7K 24.0 145.0 2.79 MB

A library for creating reactive web apps in Rust and WebAssembly

Home Page: https://sycamore-rs.netlify.app

License: MIT License

Rust 99.14% HTML 0.19% CSS 0.20% JavaScript 0.47%
rust gui web wasm web-framework html signals reactive dom webassembly

sycamore's Introduction

Sycamore

Crates.io docs.rs GitHub contributors Discord

Sycamore is a reactive library for creating web apps in Rust and WebAssembly.

#[component]
fn Hello<G: Html>() -> View<G> {
    view! {
        p { "Hello World!" }
    }
}
  • Lightning Speed: Sycamore harnesses the full power of Rust via WebAssembly, giving you full control over performance.
  • Ergonomic and Intuitive: Write code that feels natural. Everything is built on reactive primitives without a cumbersome virtual DOM.
  • No JavaScript: Had enough of JavaScript? So have we. Create apps using Sycamore without touching a single line of JS.

Documentation

Sycamore is extensively documented:

Still have questions? Don't hesitate to stop by our friendly Discord server.

Examples

Sycamore has many examples for your reference in the examples/ directory. Be sure to check them out!

Viewing on sycamore-rs.netlify.app

All the examples are hosted under sycamore-rs.netlify.app/examples/<example_name> with <example_name> being the name of the example you want to view. For instance, the todomvc example is hosted on sycamore-rs.netlify.app/examples/todomvc.

Building Locally

All the examples can also be built locally using Trunk. For instance, the following command builds and serves the todomvc example:

cd examples/todomvc
trunk serve

Now open up localhost:8080 in your browser to see "Hello World!".

Perseus

Perseus is a fullstack framework built with Sycamore. Think NextJS or SvelteKit but with no JavaScript. Everything from backend to frontend is built with pure Rust!

Alternatives?

Don't think Sycamore is for you? Thankfully, there are plenty of alternatives!

  • SolidJS: A declarative, efficient and flexible JavaScript library for building user interfaces
    Solid is a JavaScript library which greatly inspired Sycamore. Many concepts such as fine-grained reactivity and components as factory functions were borrowed from Solid. If you don't mind working with JavaScript (or TypeScript), go check it out!
  • Yew: Rust / Wasm framework for building client web apps
    Yew was also a big inspiration for Sycamore. Yew employs a VDOM and has a MVU (Elm) architecture. If you think that's for you, take a look!
  • MoonZoon: Rust Fullstack Framework
    MoonZoon also champions the no VDOM paradigm and uses dominator as its underlying DOM layer. MoonZoon is a fullstack framework making it easier to combine frontend and backend code with minimal boilerplate.

Contributing

Sycamore would not have been possible without the wonderful contributions from the community. Thank you!

Special thanks to @nate-sys for designing the Sycamore logo!

sycamore's People

Contributors

alexisfontaine avatar alsuren avatar amnrg avatar arctic-hen7 avatar attriaayush avatar blainehansen avatar danielalvsaaker avatar danielnehrig avatar dav1dde avatar dependabot[bot] avatar dten avatar dyanechi avatar emi2k01 avatar eugenesvk avatar ewaldhorn avatar gearme avatar hmikihiro avatar iiiii7d avatar jquesada2016 avatar kestrer avatar lights0123 avatar lukechu10 avatar makoven avatar mc1098 avatar tmpr avatar tshepang avatar wainwrightmark avatar wingertge avatar x37v avatar yatesco 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

sycamore's Issues

Component children

Describe the solution you'd like
Components (#[component(_)]) should be able to have child nodes or props.

Design

Currently, component functions only accept an optional single parameter (the prop type). With this feature, component functions should allow for an optional second parameter that is the children passed to the component. To prevent ambiguity when the prop type is omitted, the children parameter must also be marked with a #[slot] attribute.

Proposed changes to the #[component(_)] attribute macro

The proposed syntax is as follows:

#[component(MyComponent<G>)]
fn my_component(props: Props, #[slot] children: TemplateResult<G>) -> TemplateResult<G> {
    template! { ... }
}

// Or with props omitted (having type '()')
#[component(MyComponent<G>)]
fn my_component(#[slot] children: TemplateResult<G>) -> TemplateResult<G> {
    template! { ... }
}

Children type and proposed changes to the template! macro

The proposed changes to the template! macro is as follows:

template! {
    MyComponent() {
        div
    }
}

This will pass a TemplateResult representing the div element to the component. Other types can be passed as well:

template! {
    MyComponent() {
        (123u32)
    }
}

This will pass a u32 of value 123u32 to the component.

The macro should not attempt to do any casting of the type passed in.

Additional information

This will improve the ergonomics of using Indexed and Keyed utility components. The map function can be passed as the children to reduce the number of props. The syntax would be as follows:

template! {
    Indexed(IndexedProps { each=my_vec }) {
        (|x| template! {
            p { (x) }
        })
    }
}

Alternatives

Make children a field of the property type. This is the design of many other web frameworks such as React and Yew.
This does not fit as well into Rust patterns because Rust does not have structural types. One would therefore need an additional trait to access the child and make constructing components in the template! macro more complicated.

Run benchmarks in CI

Micro-benchmarks that do not depend on wasm-bindgen can use criterion.
Benchmarks that depend on wasm-bindgen can use benchmark.js for running e2e benchmarks.

PRs with the performance label should automatically trigger the CI workflow. The workflow should post a message to the conversation thread with a diff between HEAD and branch benchmark results.

Setup documentation website

Is your feature request related to a problem? Please describe.
Although the website is up and running, there is nothing on there except for examples. Eventually, all the documentation will be hosted on that website.

Describe the solution you'd like
Documentation should be written in markdown in a separate directory. The website should scrape the directory and render the markdown (with syntax highlighting).

Describe alternatives you've considered
Use a documentation framework (e.g. https://docusaurus.io/) or a blog generator (e.g. https://www.getzola.org/). In fact, the yew documentation (https://yew.rs) uses Docusarus. This will probably be easier to setup.

Using maple to build the maple docs, however, will provide more dogfooding for testing out maple. In fact, the Seed docs (https://seed-rs.org) is built using Seed as well.

Additional context
The GitHub markdown API could be useful to quickly get a working prototype: https://docs.github.com/en/rest/reference/markdown
Eventually, we would probably want to render the markdown by ourselves using pulldown-cmark and syntect.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Make hooks update in component lifecycle

Currently, create_signal and the likes return Rcs. The user must clone them into which ever scope they are used, which is veyr unergonomic. These hooks should create state with the same lifetime as the enclosing component.

Unfortunately, this also means that the simplicity of a single function is no longer possible for defining new components. A proc-macro-attribute could potentially help with this.

Prerender documentation to html

Right now, the documentation is sent as markdown to the browser where it is rendered client-side to html using pulldown_cmark. This is sub-optimal.

To fix this, there should be a new docs crate with the markdown files. In the build.rs file, the markdown should be transformed into html which is emitted, along with metadata (outline) into a JSON file. These generated files should be copied by Trunk to the output folder.

The current docs folder should be renamed to website. The web app should fetch the JSON, parse it using serde (maybe use serde_lite instead?), and display the html and outline.

`#[component(...)]` attribute macro

Is your feature request related to a problem? Please describe.
With #67, all components need to be generic over G: GenericNode. This is quite unergonomic and unpractical.

Describe the solution you'd like
There should be a proc-macro-attribute similar to #[launch] from Rocket which will infer the return type automatically with the generic parameter.

In case we need to access the type parameter, there should be a node_type = G argument for #[component] which will name the type parameter as the specified identifier. If not specified, the type param name should default to something like __GenericNodeT or similar to prevent name clashes. This type param should always be the last parameter added.

In addition, this could resolve the problem of having components being PascalCased rather than snake_cased per Rust naming conventions. We could make components structs rather than functions behind the scene which implement a Component trait. This would have the additional benefit of making components safer to use as one cannot use just any function as a component.

The proposed syntax is the following:

#[component(MyComponent, node_type = G)]
fn my_component(props: Props) -> _ {
    template! { ... }
}

#[component(App)]
fn my_component(props: Props) -> _ {
    template! { MyComponent(props) }
}

Describe alternatives you've considered
Do not use a proc-macro-attribute. Using more proc-macros could lead to a slight increase in compile times.

Additional context
Check whether there is any conflict with rust-analyzer code completion.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Versioned documentation on website

Is your feature request related to a problem? Please describe.
Users when looking at the documentation are sometimes confused about what features are available on the latest released version and the version on master.

Describe the solution you'd like
The docs' version should be displayed and a dropdown menu should allow the user to switch between different versions.
A new version of the docs should be saved every major release while in pre-release (0.x.y) and every major or minor release after 1.0.
All the versioned docs should be saved directly into the source tree.

Describe alternatives you've considered
Use GitHub to get different versioned docs. This path is unlikely because GitHub was not designed to host static files.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Recreate dependency graph on every call in create_effect

Describe the bug
The dependency graph should be recreated every time the closure in create_effect is called. If there is control flow in the closure or not every expression is executed, not all the states could get tracked.

Additional context
Useful blog post: https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p

Questionnaire

  • I would like to fix this bug but I don't know where to start
  • I would like to fix this bug and I have a solution
  • I don't have time to implement this / I don't want to implement this

Router

Is your feature request related to a problem? Please describe.
Maple currently does not have a built-in official way to make Single Page Apps.

Describe the solution you'd like
There should be a new maple-router crate (or something else, depending on #70) that allows creation of type-checked routes that are order-independent. This router should be component based to deeply integrate with Maple.

Describe alternatives you've considered
Use an existing router. This would not be as integrated and would be unergonomic to use.

Additional context
Look at yew-router implementation.

API (rustdoc) for master on website

Is your feature request related to a problem? Please describe.
Auto-generated documentation exists at docs.rs. However, there does not exist any hosted API documentation for code on master. One needs to first clone the repo and run cargo doc to view the documentation.

Describe the solution you'd like
Build documentation as part of the website build CI task. This should run cargo doc and copy the directory from target/doc to docs/dist/api/.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Deeply nested state reactivity

Is your feature request related to a problem? Please describe.
The current way of having fine grained reactivity for nested state is basically wrapping every member around Signal. This is cumbersome and unergonomic.

Describe the solution you'd like
An attribute macro called observable (or something else) which creates a new struct with the previous struct name appended with a Observable (e.g. AppState becomes AppStateObservable. This struct should have methods for all the fields which are wrappers around Signal::get and Signal::set.

A new method should be added to Signal called subscribe which is identical to get but without returning any value (saving a Rc::clone). The -Observable struct should then have methods subscribe and subscribe_nested where the former subscribes to all the fields and the later subscribes to all the fields and all nested fields (subscribe when any element in the tree changes).

The existing struct should also have methods fn observable(&self) -> SelfObservable, fn into_observable(self) -> SelfObservable and fn new_default_observable() -> SelfObservable for creating the Observable struct.

Additional context
This would be similar to SolidJS's createState function except it uses the JS Proxy for property get and set.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Use dedicated type for StateHandle instead of Rc<dyn Fn>

Changing StateHandle and SetStateHandle to be a dedicated type instead of just a function would increase type safety, as users won't be able to accidentially mix up state handles and functions that are used for other things. Additionally it may improve performance since dynamic dispatch is not used. It does slightly reduce ergonomics - .get() would probably have to be used instead of just calling the function - but at least to me that feels more natural anyway. What do you think?

Tweened values

Is your feature request related to a problem? Please describe.
A tweened Signal for smooth animations.

Describe the solution you'd like
There should be a new trait Tweenable or something of the like which is implemented for values that can be tweened. Eventually, there should be a derive macro that implements Tweenable when all child fields are also Tweenable.

There should be a new Tween struct that Derefs to a StateHandle so that it can be used anywhere a Signal can also be used.
When calling set on the Tween, instead of immediately changing the value, it should be tweened using an easing function which is then updated on every requestAnimationFrame. Tweened should internally use a Signal to handle all state updating.

Additional context
Prior art: https://svelte.dev/docs#svelte_motion

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Scroll back to top of page automatically on navigation

Simply call window.scrollTo(0, 0) (equivalent using wasm-bindgen) after here:

// Update History API.
let history = web_sys::window().unwrap().history().unwrap();
history
.push_state_with_url(
&JsValue::UNDEFINED,
"",
Some(pathname.get().as_str()),
)
.unwrap();

and here:
// Update History API.
let history = web_sys::window().unwrap().history().unwrap();
history
.push_state_with_url(&JsValue::UNDEFINED, "", Some(pathname.get().as_str()))
.unwrap();

Add more easing functions

Is your feature request related to a problem? Please describe.
Maple ships with some easing functions out of the box for use with Tweened. They are in the maple_core::easing module. There are some easing functions that are missing, notably, circular, sine, exponential, bounce and perhaps some more.

Describe the solution you'd like
For all the different easing functions listed above, there should be in, out and inout variants.

Additional context
https://easings.net/ would be a good reference for the right mathematical functions for each ease function.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Issues When Running

I can't seem to get the Hello World example from the README running. I have updated my main.rs file and added the dependency to Cargo.toml, but when I run using trunk I get a long list of errors (see below).

Environment

  • Maple: 0.4.x
  • WSL / Ubuntu 20.04.1 LTS

Additional context
I have updated trunk, wasm-pack-cli, Rust, and a few other dependencies I think are related, just in case.

Here is the start of the output. The list goes on for quite a while longer.

โฏ trunk serve --open
Apr 01 07:16:47.612  INFO ๐Ÿ“ฆ starting build
Apr 01 07:16:47.616  INFO spawning asset pipelines
Apr 01 07:16:47.775  INFO building maple-test
   Compiling js-sys v0.3.49
   Compiling console_error_panic_hook v0.1.6
error: expected `,`
  --> /home/googlemac/.cargo/registry/src/github.com-1ecc6299db9ec823/console_error_panic_hook-0.1.6/src/lib.rs:80:43
   |
80 |             #[wasm_bindgen(js_namespace = console)]
   |                                           ^^^^^^^

error[E0433]: failed to resolve: use of undeclared type `Error`
   --> /home/googlemac/.cargo/registry/src/github.com-1ecc6299db9ec823/console_error_panic_hook-0.1.6/src/lib.rs:106:21
    |
106 |             let e = Error::new();
    |                     ^^^^^ not found in this scope
    |
help: consider importing one of these items
    |
71  | use std::error::Error;
    |
71  | use std::io::Error;
    |
71  | use wasm_bindgen::__rt::core::fmt::Error;
    |

error[E0425]: cannot find function `error` in this scope
   --> /home/googlemac/.cargo/registry/src/github.com-1ecc6299db9ec823/console_error_panic_hook-0.1.6/src/lib.rs:117:13
    |
117 |             error(msg);
    |             ^^^^^ not found in this scope

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0425, E0433.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `console_error_panic_hook`

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: expected `,`
   --> /home/googlemac/.cargo/registry/src/github.com-1ecc6299db9ec823/js-sys-0.3.49/src/lib.rs:639:39
    |
639 |         #[wasm_bindgen(js_namespace = Atomics, catch)]
    |                                       ^^^^^^^

error: expected `,`
   --> /home/googlemac/.cargo/registry/src/github.com-1ecc6299db9ec823/js-sys-0.3.49/src/lib.rs:649:39

2-way data binding

Is your feature request related to a problem? Please describe.
Reduce boilerplate especially with inputs and forms.

Describe the solution you'd like
Binding to html element properties. Component state is binded automatically.

Syntax:

let value = Signal::new(String::new());

template! { input(bind:value=value) }

bind: should always bind to properties while attributes in template! without bind: always become attributes in the DOM.

Only a few specific properties on some elements will be supported. This is because the way for detecting property changes is via emitted events from the element. E.g. for value on <input>, we listen for the input event.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Support for static rendering

Is your feature request related to a problem? Please describe.
There's a distinct lack of isomorphic support in the Rust ecosystem. I've been working on this for Yew, but it's such a large codebase (and userbase) that everything must tread very lightly and the code churn means it is a constantly moving target.

Less important, but, the ultimate context (admittedly somewhat personal) for this is that I would like to create an isomorphic app to replace the tangled mess that is main.js in the Rustdoc project, which will unlock incremental redesigns of the documentation platform we all use for Rust crate documentation. This could theoretically just be done with existing JS tooling, except that the build pipeline for crates.io is so complex and computationally expensive that they don't want an extra type of tooling added to the mix, so, whatever is added must be based in Rust.

Describe the solution you'd like
It would be a huge boon to this project if server-side rendering / isomorphic apps were supported from early on. Some things this encourages are: an opinionated app structure and ability to statically discover facts about the application (without running it) such as routes, which would probably be wanted at some point anyway. The first iteration of this feature would be just pure static rendering (aka SSR). The next step could be either isomorphic apps or static site generation, the latter being probably the least work since it's just an extension of static rendering. Once two of those things are done, the third should be relatively simple to add.

Describe alternatives you've considered
Percy and Yew are both solid contenders. I have been working on Yew for the past year, since it has more community support and is thus more proven, but again this is a complication due to inertia, and it would be cool to see a library support this use-case out of the box.

Additional context
I am also a maintainer of Trunk so I can provide support in the build process if there's any trickiness there.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

JSX-like syntax macro

Nice work on maple! Really like the VDOM-free reactivity approach and looking forward to see how this develops.

Wanted to leave a shameless plug here: in case you'd ever consider a JSX-like syntax for maple, then maybe my syn-rsx crate might be of interest.

Feel free to close the issue if you consider this out of scope or an ad :D, and good luck with the library!

Discord invite is expired

Discord link in the README is to an expired invitation. Would like to join but cannot. Looks like a cool library!

Use Vercel for hosting docs website

GitHub Pages does not build for branches and PR. Using Vercel will allow previewing of the docs website on any PR. Benchmark reports can also be uploaded into the docs/dist/ folder to allow easy viewing.

Edit: Vercel seems to have some limitations with trunk. Will use Netlify instead.

Remove `format!` calls in `SsrNode`

Using format! is bad for performance because it pulls in the formatting infrastructure. Instead, replace all instances where format! is used with push and push_str. Also use String::with_capacity when possible to avoid unnecessary allocations.

All panics in TodoMVC

Describe the bug
All panics in TodoMVC when there's no completed items, but some uncompleted items.

To Reproduce
Run TodoMVC example,
Add an item
Click "All"
See in script console that a panic occured.

Expected behavior
TodoMVC should never panic

Environment

  • Sycamore: master
  • Browser: Chrome
  • OS: Windows

Document fragments in `template!` macro

Describe the solution you'd like
The template! macro should allow document fragments without the <></> JSX syntax.
The following should be accepted by the template! macro:

// multiple children
template! {
    p { ... }
    a { ... }
};

// empty fragment
template! {}

The TemplateResult struct should be converted into an enum with the variants Single and List where the second variant is used for document fragments (including empty fragments). This should not use the DocumentFragment under the hood as it behaves somewhat differently from Nodes. For one thing, when appending a DocumentFragment to the DOM, the elements are moved out of the fragment and no longer accessible. Instead, TemplateResult::List should use a Vec or other collection under the hood.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Edit
The current way Keyed and Indexed are a bit buggy. They return DocumentFragments which, as described above, have certain differences from other html nodes. This results in a panic when updating Keyed and Indexed at the top level of a template!, e.g.

template! {
    Keyed {..} // panics when iterable is updated
}

Node references

Is your feature request related to a problem? Please describe.
Allow getting a reference to the underlying DOM node.

Describe the solution you'd like
A special ref attribute that will assign a NodeRef with the value of the DOM node.

Additional context
Look at Yew's implementation: https://github.com/yewstack/yew/blob/5fc4387dc58b7f87c9a71ee734bf04d307fb7226/packages/yew/src/html/mod.rs#L68

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Hydrate DOM on client side

Is your feature request related to a problem? Please describe.
This is the second part to implementing #47 (first part implementation #67 )

Describe the solution you'd like
Once the server side rendered DOM has been sent to the client, the client will need to re-hydrate the DOM by reusing already existing DOM nodes (the client should not recreate new DOM nodes and replace those rendered by the server).

Additional context
Look at how some other frameworks implement DOM hydrating.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Support nested effects

Is your feature request related to a problem? Please describe.
Nested effects are required to implement #18

Describe the solution you'd like
Nested effects should be supported via the create_effect function.

Additional context
Semantics:

  • Inner effect has dependencies on state used inside inner closure.
  • Outer effect has dependencies on state used inside outer closure but not within inner closure.

Proposed implementation: #18 (comment)

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

map_keyed panic when updating with same data

Describe the bug
Modifying an iterator while it's filtered causes a panic

To Reproduce
Steps to reproduce the behavior:

  1. Run todos example
  2. Add 2 items (test, test2)
  3. Check test2
  4. Hit Active
  5. Hit Clear completed

Expected behavior
The item should be removed from the list, but nothing on the UI should change in this example

Error

panicked at 'start is the first index where items[start] != new_items[start]', /sycamore/packages/sycamore/src/rx/iter.rs:69:17

Environment

  • Sycamore: master
  • Browser: firefox

Testing story

Make it easy to unit test components as well as integration and E2E tests.
Scenarios should include but not limited to:

  • Ergonomic assertions about DOM state
  • DOM snapshot testing
  • Code coverage
  • Mocking (Network requests, cookies, sessions, authentication, etc...)

Introduce a new abstraction layer in `TemplateResult` for multiple backends

Is your feature request related to a problem? Please describe.
Blocker for #47

Describe the solution you'd like
The current TemplateResult struct is basically a new-type around web_sys::Node. To support SSR, template!s should be rendered to a String rather than DOM nodes. The TemplateResult struct should therefore represent the complete DOM hierarchy with a .to_node() method to convert this layer into DOM nodes. This might also be related to #19.

For supporting SSR/pre-rendered applications, TemplateResult should have a .to_string().

Note that this is not a VDOM because this abstraction layer is only a wrapper around pure DOM nodes. Updates will still be made directly without any patching or reconciliation phase.

Describe alternatives you've considered
Render the DOM in a wasm runtime (e.g. NodeJS, wasmer, etc...) with mocked DOM apis (e.g. jsdom. This is sounds more like a workaround rather than a real solution. We will probably run into future problems with this as well.

Additional context
Percy supports SSR: https://chinedufn.github.io/percy/views/server-side-rendering/how-to-ssr.html
Solid-SSR is probably also worth looking at as this library is heavily inspired by SolidJS: https://github.com/ryansolid/solid/tree/master/packages/solid-ssr

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Remove "Effects created outside of a reactive root will never get disposed." warning

The warning says that the state that the effect owns will never get dropped. However, reactive scopes created using render and render_to are stored in a global Owner list never to be dropped anyways. The message should therefore be removed as it does not make a lot of sense. The only change needed is deleting the following lines:
https://github.com/lukechu10/maple/blob/90e6d46679a62d715f3502f3f64811482c94f02a/maple-core/src/reactive/effect.rs#L242-L249

The warning message for on_cleanup, however, should be kept because adding a cleanup outside of a reactive scope will have no effect whatsoever.

Questionnaire

  • I would like to fix this bug but I don't know where to start
  • I would like to fix this bug and I have a solution
  • I don't have time to implement this / I don't want to implement this

Properly dispose of effects

Describe the bug
Effects should be owned by a reactivity root, created using a create_root method.

Questionnaire

  • I would like to fix this bug but I don't know where to start
  • I would like to fix this bug and I have a solution
  • I don't have time to implement this / I don't want to implement this

Component lifecycle

Is your feature request related to a problem? Please describe.
Components should have some lifecycle hooks for on_created and on_destroyed.

Describe the solution you'd like
on_created is similar to create_effect except it only runs once.
on_destoryed is a bit more complicated. Currently, components are simply function calls. For on_destroyed to be implemented, the function call needs to be wrapped up in another create_component utility. This utility function will setup the lifecycle hooks for the code inside the component.

Additional context
Add any other context or screenshots about the feature request here.

Questionnaire

  • I would like to implement this feature but I don't know where to start
  • I would like to implement this feature and I have a solution
  • I don't have time to implement this / I don't want to implement this

Make `map_indexed` and `map_keyed` more idiomatic

Right now, map_indexed and map_keyed use a lot of index manipulations. This is not very idiomatic in Rust.

Preferably, most of it can be refactored to use iterators instead. This will improve maintainability and perhaps even performance because it will remove the need for bound checks.

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.