Cut out SSR and speed up Habr 10 times

Hello, my name is Dmitry Karlovsky and I ... that still toxic pepper. I recently poured my alpha vibes to Alfa Bank . In response, the guys acted with dignity, and did not attack me in a personal with explanations how much I was wrong, but started a task on the github . And they even fixed something, making some of my claims untenable. But not the part where SSR messes up.



Time has passed, the dust has settled, and here the story continues: recently, the producer of the Habr content studio approached me with a proposal to sand their Cake . Well, let's uncover the fan!



Let there be a shit



Complex case



Take, for example, this page with 2500 comments. This is such a huge page that if you open it in Chrome, it will truncate it by 1400 comments. To read the rest you will have to open it, for example, in Ognelis. Let's leave the reason for this on the conscience of the developers. Let's better think about how to prevent this. But first, let's take measurements:



Index Desktop version (HTML) Mobile version (JSON) Expedited Universal Version (JSON)
Data size 12 MB 3.4 MB 3.4 MB
1000 KB 700 KB 700 KB
45 s 42 s 5 s
5 s 42 s 5 s
DOM 116K 100K < 1K
700 ms 30 ms
1800 ms 30 ms
800 MB 1000 MB 80 MB


You will die while you wait





  • β€” HTML JSON . , " ". , .
  • β€” , .
  • β€” (, β€” ), F5 ( " ") . .
  • β€” , , , , .
  • DOM β€” document.getElementsByTagName('*').length , .
  • β€” . .
  • β€” . .
  • β€” , (shift+esc) .


. - β€” .



Flyugegeheim





: . HTML. : HTML, "" JSON VueJS . , HTML. HTML , , .



, JSON 4 HTML. Tree , , JSON . , , , β€” 30%.



HTML , :



  1. , 8 , . loading="lazy", .
  2. HTML , , . DOM, HTML . β€” HTML.


, DOM . , . VueJS , .



100K DOM . 40 . .



DOM . , , , 700. , . β€” 2 . DOM . DevTools , .



Wood oppresses





β€” DOM . , . :



. . , , .
, . ### , . , .
. ### . ## . ###
. ## . ## . ### . # . ##
### ### ## ### ## ## ### ## #


:



  1. .
  2. , .


A choice of three evils





β€” $mol, , , $mol .



JSON. , , , . $mol_data:



const Person = Rec({
    alias: Str,
    id: Str,
    login: Str,
    fullname: Maybe( Str ),
    avatarUrl: Maybe( Str ),
    speciality: Maybe( Str ),
})

const Comment =  Rec({
    id: Int,
    author: Maybe( Person ),
    children: List( Int ),
    isAuthor: Maybe( Bool ),
    isPostAuthor: Maybe( Bool ),
    message: Str,
    parentId: Int,
    score: Maybe( Int ),
    timeChanged: Maybe( Moment ),
    timePublished: Maybe( Moment ),
})

const Comments_response = Rec({
    comments: Dict( Comment ),
    threads: List( Int ),
})


β€” null , .



, . , :



@ $mol_mem
comments_data() {
    const uri = `https://m.habr.com/kek/v2/articles/${ this.article_id() }/comments/`
    const data = Comments_response( this.$.$mol_fetch.json( uri ) )
    return data
}


, , . , HTML. $mol_html_view:



<= Article $mol_html_view
    html <= article_content \
    highlight <= search
    image_uri!node <= image_uri!node \


( view.tree, , .)



HTML, $mol_view , . , $mol_html_view , .



image_uri, IMG , . , src , data-src. :



image_uri( node : HTMLImageElement ) {
    return node.dataset.src || node.src || 'about:blank'
}


. / .



@ $mol_mem_key
comments_visible( id : number ) : readonly number[] {

    if( this.comment_expanded( id ) ) {
        return this.comments_all( id )
    } else {
        return this.comments_filtered( id )
    }

}


, . , $mol . , , - β€” .



, , , , . . β€” . :



Let them talk



Ctrl+F , $mol_hotkey :



plugins /
    <= Search_key $mol_hotkey
        mod_ctrl true
        key * F?event <=> search_focus?event null
    <= Theme $mol_theme_auto


:



search_focus( event : Event ) {
    this.Search().Suggest().Filter().focused( true )
    event.preventDefault()
}


, $mol_theme_auto, .



, , $mol_lights_toggle:



tools /
    <= Lights $mol_lights_toggle
    <= Sources $mol_link_source
        uri \https://github.com/nin-jin/habrcomment
    <= Search $mol_search
        query?val <=> search?val \


, .



, , $mol_style, , :



$mol_style_define( $my_habrcomment , {

    Orig: {
        flex: {
            grow: 1,
            shrink: 0,
            basis: per(50),
        },
    },

    Article: {
        maxWidth: rem(60),
    },

    Comments: {
        flex: {
            shrink: 0,
            grow: 1,
        },
    },

    Comments_empty: {
        padding: rem(1.5),
    },

} )


:



include \/mol/offline/install


Service Worker, .



, , , .



, : https://nin-jin.github.io/habrcomment/#article=423889



, :



javascript: document.location = document.location.href.replace( /\D+/ , 'https://nin-jin.github.io/habrcomment/#article=' )


King of Marriage





400 , . :



  • /
  • /
  • /


5 . 6 ( 2 , ). , . .



. , HTML . , - , :



<= Message $mol_html_view
    minimal_height 60
    highlight <= search \
    html <= message \
    image_uri!node <= image_uri!node \


HTML . , , , .



5 . 10 .



API, β€” , , . . , β€” . :



@ $mol_mem
comments_data() {
    const search = encodeURIComponent( this.search() )
    const uri = `https://m.habr.com/kek/v2/articles/${ this.article_id() }/comments/?search=${search}`
    const data = Comments_response( this.$.$mol_fetch.json( uri ) )
    return data
}


, , . . , . - β€” . API. β€” .



, β€” , HTML, , - : , , , BR, . , - , - .



$mol_html_view HTML- β€” , . , , .



, :



  1. β€” - $mol_list. , . - .
  2. , overflow-anchor, , . , , , 100K , .


β€” , . , , . , , .



King of Engineering





  1. SSR PWA.
  2. , , .
  3. , β€” .
  4. VueJS β€” , $mol β€” .
  5. , .
  6. It is worth preferring those solutions that do not lead to an uncontrolled increase in the number of elementals in the house.


Elemental



Links



  1. Reader sources - you can notice that there is nothing at all in the code.
  2. Page of the $ mol framework - be horrified how much we have there.
  3. Channel with news about $ mol and MAM - subscribe to be aware of everything important that happens to them.
  4. $ Mol video channel - video tutorials will appear here someday.



All Articles