reshadow icon indicating copy to clipboard operation
reshadow copied to clipboard

[svelte] Reshadow + Svelte SSR Styles

Open s0kil opened this issue 5 years ago • 4 comments

When reshadow processes styles, they no longer are extracted to a css file, instead are evaluated by JavaScript at runtime.

Ex runtime styles:

<script>
    import {__init__ as __reshadow__} from '@reshadow/svelte';
    import {beforeUpdate as __bu__, afterUpdate as __au__} from 'svelte';

    import __styled__, {
        __extract__,
        set,
        create,
        css,
        use,
        map,
        __css__,
    } from '@reshadow/core';
    let newColor = 'blue';
    let color = 'tomato';
    const __styled___c8 = create([
        (__css__(
            `.___button_uwcly_1 {
    padding: 5px 10px;
    border-radius: 5px;
    font-size: 16px;
}

.___button_uwcly_1.__use--type_uwcly_1.__use--type_primary_uwcly_1 {
    color: green;
}

.___button_uwcly_1.__use--size_uwcly_1.__use--size_s_uwcly_1 {
    font-size: 14px;
    color: var(--c8_0);
}

.___button_uwcly_1.__use--size_uwcly_1.__use--size_m_uwcly_1 {
    font-size: 16px;
    color: var(--c8_1);
}`,
            /*__css_end__*/
            '1868321304',
        ),
        {
            __button: `___button_uwcly_1`,
            '_use--type': `__use--type_uwcly_1`,
            '_use--type_primary': `__use--type_primary_uwcly_1`,
            '_use--size': `__use--size_uwcly_1`,
            '_use--size_s': `__use--size_s_uwcly_1`,
            '_use--size_m': `__use--size_m_uwcly_1`,
        }),
    ]);

    $: __styles__ = __styled__(
        (set([__styled___c8], `--c8_0:${color};--c8_1:${newColor};`),
        __extract__()),
    );

    const __getStyles__ = () => __styles__;
    __reshadow__(
        {beforeUpdate: __bu__, afterUpdate: __au__},
        __getStyles__,
        () => {
            __styled__ = __styled__;
            map = map;
        },
    );
</script>

It would be ideal to return static styles in a style tag so Svelte could export them into a CSS file, and Reshadow will process dynamic styles at runtime.

Ex static styles:

<script>
    import {__init__ as __reshadow__} from '@reshadow/svelte';
    import {beforeUpdate as __bu__, afterUpdate as __au__} from 'svelte';

    import __styled__, {
        __extract__,
        set,
        create,
        css,
        use,
        map,
        __css__,
    } from '@reshadow/core';
    let newColor = 'blue';
    let color = 'tomato';
    const __styled___c8 = create([
        {
            __button: `___button_uwcly_1`,
            '_use--type': `__use--type_uwcly_1`,
            '_use--type_primary': `__use--type_primary_uwcly_1`,
            '_use--size': `__use--size_uwcly_1`,
            '_use--size_s': `__use--size_s_uwcly_1`,
            '_use--size_m': `__use--size_m_uwcly_1`,
        },
    ]);

    $: __styles__ = __styled__(
        (set([__styled___c8], `--c8_0:${color};--c8_1:${newColor};`),
        __extract__()),
    );

    const __getStyles__ = () => __styles__;
    __reshadow__(
        {beforeUpdate: __bu__, afterUpdate: __au__},
        __getStyles__,
        () => {
            __styled__ = __styled__;
            map = map;
        },
    );
</script>

<style>
    .___button_uwcly_1 {
        padding: 5px 10px;
        border-radius: 5px;
        font-size: 16px;
    }

    .___button_uwcly_1.__use--type_uwcly_1.__use--type_primary_uwcly_1 {
        color: green;
    }

    .___button_uwcly_1.__use--size_uwcly_1.__use--size_s_uwcly_1 {
        font-size: 14px;
        color: var(--c8_0);
    }

    .___button_uwcly_1.__use--size_uwcly_1.__use--size_m_uwcly_1 {
        font-size: 16px;
        color: var(--c8_1);
    }
</style>

<button
    {...map(
        'button',
        use({
            size: 's',
        }),
        {
            $$style: __styles__.$$style,
        },
    )}
    class="___button_uwcly_1 __use--size_uwcly_1 __use--size_s_uwcly_1">
    Small
</button>
<button
    {...map(
        'button',
        use({
            size: 'm',
        }),
        {
            $$style: __styles__.$$style,
        },
    )}
    class="___button_uwcly_1 __use--size_uwcly_1 __use--size_m_uwcly_1">
    Medium
</button>
<button
    {...map(
        'button',
        use({
            type: 'primary',
        }),
        {
            $$style: __styles__.$$style,
        },
    )}
    class="___button_uwcly_1 __use--type_uwcly_1 __use--type_primary_uwcly_1">
    Primary
</button>

s0kil avatar Jun 05 '19 07:06 s0kil

Another suggestion for runtime performance: cache all styles for re-use and inject CSS using .insertRule()

s0kil avatar Jun 05 '19 07:06 s0kil

Hi @s0kil, thank you very much for the request!

Yeah, I think it's really important to extract styles also with svelte, and I don't see any problems with it at all (the same trick as with webpack should work out of the box)

So I think I'll have a chance to make it today/tomorrow

And thank you for the link to the nano-css, looks really interesting!

I also thought about insertRule and made some experiments with such implementation, but found the whole <style> insertion a bit more effective (as a separate tag, without previous changing, just because of the specific reshadow implementation we don't insert any rules during the runtime, only for the first time on initializing if styles were not extracted), and reshadow runtime also has quite effective caching by generated hash.

But I think about runtime mixins too and how they could be extracted and optimized, and mixins implementation probably should be with CSSOM

lttb avatar Jun 05 '19 09:06 lttb

@s0kil, I've made some benchmarks comparing with nano-css with styled-interface: https://xggtc.sse.codesandbox.io/public#nano-css-styled (production build)

and the difference on 100 boxes is quite big (ms):

reshadow reshadow-runtime reshadow-styled nano-css-styled
69 77 115 573
50 58 81 1457
22 38 56 2348
22 29 64 3418
21 36 58 4320

I think that there are some things that could be optimized in the example for nano-css, but the idea was to try the interface and solution as is

lttb avatar Jun 05 '19 21:06 lttb

@lttb Looks great, but we still got to get them static styles out of the JavaScript bundle. Not everyone can afford supercomputers to parse JavaScript bundles (:

s0kil avatar Jun 05 '19 23:06 s0kil