Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Static Site Generation for the Masses

Static Site Generation for the Masses

Static website generators are slowly rising in popularity and have been proven to be a worthy alternatives to CMSes in many cases. This talk explains what static site generators are, how they avoid the traditional problems with CMSes, and explains what technical challenges must be overcome when implementing one.

Denis Defreyne

February 03, 2013
Tweet

More Decks by Denis Defreyne

Other Decks in Technology

Transcript

  1. STATIC SITE GENERATION
    FOR THE MASSES
    Denis Defreyne
    FOSDEM 2013
    1

    View Slide

  2. Me
    2

    View Slide

  3. Me
    2
    ‣ Denis Defreyne

    View Slide

  4. Me
    2
    ‣ Denis Defreyne
    twitter.com/ddfreyne

    View Slide

  5. Me
    2
    ‣ Denis Defreyne
    twitter.com/ddfreyne
    github.com/ddfreyne

    View Slide

  6. Me
    2
    ‣ Denis Defreyne
    twitter.com/ddfreyne
    github.com/ddfreyne
    ‣ Software Engineer

    View Slide

  7. Me
    2
    ‣ Denis Defreyne
    twitter.com/ddfreyne
    github.com/ddfreyne
    ‣ Software Engineer
    ‣ Author of nanoc

    View Slide

  8. What exactly does a
    STATIC SITE GENERATOR
    do?
    3

    View Slide

  9. 4

    View Slide

  10. 4
    Mark-
    down

    View Slide

  11. Markdown
    5
    In  *exactly*  one  month,  there’s  FOSDEM  
    again!  I  can  barely  control  my  excitement!
    *  First  element  of  a  list
    *  Second  element

    View Slide

  12. 6
    Mark-
    down

    View Slide

  13. 6
    Mark-
    down
    HTML
    fragment

    View Slide

  14. HTML from Markdown
    7
    In  exactly  one  month,  there’s  
    FOSDEM  again!  I  can  barely  control  my  
    excitement!

    First  element  of  a  list
    Second  element

    View Slide

  15. 8
    Mark-
    down
    HTML
    fragment

    View Slide

  16. 8
    Mark-
    down
    HTML
    fragment
    Layout

    View Slide

  17. Layout
    9



    <%=  item[:title]  %>


    <%=  yield  %>


    View Slide

  18. 10
    Mark-
    down
    HTML
    fragment
    Layout

    View Slide

  19. 10
    Mark-
    down
    HTML
    fragment
    Layout
    +
    HTML

    View Slide

  20. 11



    One  Month  until  FOSDEM!


    In  exactly  one  month,  there’s  FOSDEM  
    again!  I  can  barely  control  my  excitement!

    First  element  of  a  list
    Second  element



    View Slide

  21. 12
    Mark-
    down
    HTML
    fragment
    Layout
    +
    HTML

    View Slide

  22. 13

    View Slide

  23. VPS + 96 MB RAM + Ruby =
    TOO SLOW!
    13

    View Slide

  24. 14
    nanoc
    φϊοΫ

    View Slide

  25. 15

    View Slide

  26. 16
    CMS
    Content Management System

    View Slide

  27. 16
    CMS
    Content Management System

    View Slide

  28. 17
    SSG
    Static Site Generator

    View Slide

  29. Road map
    18

    View Slide

  30. Road map
    1. What are SSGs?
    18

    View Slide

  31. Road map
    1. What are SSGs?
    2. What are SSGs capable of?
    18

    View Slide

  32. Road map
    1. What are SSGs?
    2. What are SSGs capable of?
    3. Lessons Learnt & Future Work
    18

    View Slide

  33. 19
    What are SSGs?

    View Slide

  34. Tiny example – pages
    20
    content/
    about.md
    blog/
    2013-­‐01-­‐02-­‐one-­‐month-­‐until-­‐fosdem.md
    2013-­‐02-­‐03-­‐fosdem-­‐was-­‐awesome.md

    View Slide

  35. Tiny example – pages
    21
    -­‐-­‐-­‐
    title:  One  Month  until  FOSDEM!
    -­‐-­‐-­‐
    In  exactly  one  month,  there’s  FOSDEM  again!  
    I  can  barely  control  my  excitement!

    View Slide

  36. Tiny example – layouts
    22


    <%=  item[:title]  %>


    <%=  yield  %>


    View Slide

  37. Tiny example – result
    23


    One  Month  until  FOSDEM!


    In  exactly  one  month,  there’s  FOSDEM  again!  I  
    can  barely  control  my  excitement!


    View Slide

  38. Tiny example – result
    24
    output/
    about/index.html
    blog/2013/01/one-­‐month-­‐until-­‐fosdem/index.html
    blog/2012/02/fosdem-­‐was-­‐awesome/index.html

    View Slide

  39. 25

    View Slide

  40. 26

    View Slide

  41. 27

    View Slide

  42. 28

    View Slide

  43. 29

    View Slide

  44. 30

    View Slide

  45. 31

    View Slide

  46. 32

    View Slide

  47. 33

    View Slide

  48. Ace - awestruct - Blacksmith - Blogofile - Bonsai - Cactus
    - Chisel - coleslaw - Composer - cyrax - Deplot - Fairytale
    - FMPP - Frank - fugitive - Graze - Hakyll - Hammer -
    Hastie - Hobix - Hyde - Jekyll - jinjet - jkl - Korma -
    Machined - Magneto - Markbox - Markdoc - Middleman -
    mynt - nanoc - Nikola - Octopress - Pagegen - Pelican -
    Petrify - Phrozn - PieCrust - Pilcrow - Pith - poole - Punch
    - Quill - RakeWeb - Rassmalog - Rizzo - Rog - romulus -
    Rote - RubyFrontier - Ruroh - Second Crack - Socrates -
    Speechhub - Stasis - staticjinja - StaticMatic -
    StaticMatic2 - StaticWeb - Tahchee - Ultra simple Site
    Maker - Webby - webgen - Website Meta Language -
    Wintersmith - wok - yassg - yst - Yurt CMS - ZenWeb
    33

    View Slide

  49. Ace - awestruct - Blacksmith - Blogofile - Bonsai - Cactus
    - Chisel - coleslaw - Composer - cyrax - Deplot - Fairytale
    - FMPP - Frank - fugitive - Graze - Hakyll - Hammer -
    Hastie - Hobix - Hyde - Jekyll - jinjet - jkl - Korma -
    Machined - Magneto - Markbox - Markdoc - Middleman -
    mynt - nanoc - Nikola - Octopress - Pagegen - Pelican -
    Petrify - Phrozn - PieCrust - Pilcrow - Pith - poole - Punch
    - Quill - RakeWeb - Rassmalog - Rizzo - Rog - romulus -
    Rote - RubyFrontier - Ruroh - Second Crack - Socrates -
    Speechhub - Stasis - staticjinja - StaticMatic -
    StaticMatic2 - StaticWeb - Tahchee - Ultra simple Site
    Maker - Webby - webgen - Website Meta Language -
    Wintersmith - wok - yassg - yst - Yurt CMS - ZenWeb
    33

    View Slide

  50. Ace - awestruct - Blacksmith - Blogofile - Bonsai - Cactus
    - Chisel - coleslaw - Composer - cyrax - Deplot - Fairytale
    - FMPP - Frank - fugitive - Graze - Hakyll - Hammer -
    Hastie - Hobix - Hyde - Jekyll - jinjet - jkl - Korma -
    Machined - Magneto - Markbox - Markdoc - Middleman -
    mynt - nanoc - Nikola - Octopress - Pagegen - Pelican -
    Petrify - Phrozn - PieCrust - Pilcrow - Pith - poole - Punch
    - Quill - RakeWeb - Rassmalog - Rizzo - Rog - romulus -
    Rote - RubyFrontier - Ruroh - Second Crack - Socrates -
    Speechhub - Stasis - staticjinja - StaticMatic -
    StaticMatic2 - StaticWeb - Tahchee - Ultra simple Site
    Maker - Webby - webgen - Website Meta Language -
    Wintersmith - wok - yassg - yst - Yurt CMS - ZenWeb
    33
    INCOMPLETE

    View Slide

  51. 34

    View Slide

  52. 35

    View Slide

  53. 36

    View Slide

  54. 37
    Why static sites?

    View Slide

  55. 37
    1. Fast
    Why static sites?

    View Slide

  56. 37
    1. Fast
    2. Secure
    Why static sites?

    View Slide

  57. 37
    1. Fast
    2. Secure
    3. Works with your own tools (vim!)
    Why static sites?

    View Slide

  58. 37
    1. Fast
    2. Secure
    3. Works with your own tools (vim!)
    4. Content is in plain text
    Why static sites?

    View Slide

  59. 37
    1. Fast
    2. Secure
    3. Works with your own tools (vim!)
    4. Content is in plain text
    5. Easy to deploy
    Why static sites?

    View Slide

  60. 37
    1. Fast
    2. Secure
    3. Works with your own tools (vim!)
    4. Content is in plain text
    5. Easy to deploy
    6. Easy to preview
    Why static sites?

    View Slide

  61. 37
    1. Fast
    2. Secure
    3. Works with your own tools (vim!)
    4. Content is in plain text
    5. Easy to deploy
    6. Easy to preview
    7. Makes collaboration easy
    Why static sites?

    View Slide

  62. 38

    View Slide

  63. 39
    What are SSGs capable of?

    View Slide

  64. Arbitrary metadata
    40

    View Slide

  65. Arbitrary metadata
    41
    title:      Braid
    kind:        review
    subtype:  game
    year:        2008
    rating:    5

    View Slide

  66. Arbitrary metadata
    42

    <%  @item.children  do  |review|  %>

    <%=  '˒'  *  review[:rating]  %>
    <%=  review[:title]  %>

    <%  end  %>

    View Slide

  67. Arbitrary metadata
    43

    ˒˒˒˒ˑ  Borderlands
    ˒˒˒˒˒  Braid
    ˒˒˒˒ˑ  Legend  of  Grimrock
    ˒˒˒˒˒  Max  Payne
    ˒˒˒˒ˑ  Minecraft

    View Slide

  68. Filters
    44

    View Slide

  69. Filters – Markdown
    A  First  Level  Header
    ====================
    A  Second  Level  Header
    -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
    Now  is  the  time  for  all  good  men  to  come  to  the  aid  of  their  
    country.  This  is  just  a  regular  paragraph.
    *  Quick  brown  fox
    *  Lazy  dog
    45

    View Slide

  70. Filters – Textile
    h1.  Give  RedCloth  a  try!
    A  *simple*  paragraph  with
    a  line  break,  some  _emphasis_  and  a  "link":http://redcloth.org
    *  an  item
    *  and  another
    #  one
    #  two
    46

    View Slide

  71. Filters – ERB



    <%=  item[:title]  %>


    <%=  yield  %>


    47

    View Slide

  72. Filters – Mustache



    {{  title  }}


    {{  yield  }}


    48

    View Slide

  73. Filters – Haml
    !!!
    %html
    %head
    %title=  @item[:title]
    %body
    =  yield
    49

    View Slide

  74. Filters – Colorize Syntax

    def  my_function
       (1..10).map  do  |i|
           "#{i}  is  #{i  %  2  ==  1  ?  'odd'  :  'even'}"
       end
    end

    50

    View Slide

  75. Filters – Colorize Syntax
    def  my_function
       (1..10).map  do  |i|
           "#{i}  is  #{i  %  2  ==  1  ?  'odd'  :  'even'}"
       end
    end
    51

    View Slide

  76. Filters – Typogruby
    52
    "Typogruby makes HTML look
    smarter & better, don't you think?"
    “Typogruby makes HTML look
    smarter & better, don’t you think?”

    View Slide

  77. Filters – Custom
    class  CensorFilter  <  Nanoc::Filter
    identifier  :censor
    def  run(content,  params={})
    content.gsub('nanoc  sucks',  'nanoc  rocks')
    end
    end
    53

    View Slide

  78. Rules
    54

    View Slide

  79. Rules
    55
    compile  '*'  do
    if  @item[:kind]  ==  'article'
    filter  :bluecloth
    end
    layout  'default'
    end

    View Slide

  80. Rules
    56
    compile  '/images/*/'  do
       filter  :img_optimize
    end

    View Slide

  81. Rules
    57
    compile  '/images/*/'  do
       filter  :img_optimize
    end
    compile  '/images/*/',  :rep  =>  :thumbnail  do
       filter  :scale,  :width  =>  140
    end

    View Slide

  82. Rules
    58
    compile  '/blog/*/',  :rep  =>  :mp3  do
       filter  :say
       filter  :lame
    end

    View Slide

  83. Rules versus Makefiles
    59

    View Slide

  84. Rules versus Makefiles
    59
    ‣ Push vs. pull

    View Slide

  85. Rules versus Makefiles
    59
    ‣ Push vs. pull
    ‣ Cleaner syntax

    View Slide

  86. Rules versus Makefiles
    59
    ‣ Push vs. pull
    ‣ Cleaner syntax
    ‣ Automatic dependency tracking

    View Slide

  87. Helpers
    60

    View Slide

  88. 61
    module  Nanoc::Helpers::Tagging
    #  Find  all  items  with  the  given  tag.
    #
    #  @param  [String]  tag  The  tag  for  which  to  find  all  items
    #
    #  @return  [Array]  All  items  with  the  given  tag
    def  items_with_tag(tag)
    @items.select  do  |i|
    (i[:tags]  ||  []).include?(tag)
    end
    end
    end

    View Slide

  89. Helpers – example
    62
    Tags  for  <%=  @item[:tag]  %>

    <%  items_with_tag(@item[:tag]).each  do  |i|  %>
    <%=  link_to(@item[:tag],  i)  %>
    <%  end  %>

    View Slide

  90. Workflow
    63

    View Slide

  91. Workflow
    63
    1. Development

    View Slide

  92. Workflow
    63
    1. Development
    1. Version controlled

    View Slide

  93. Workflow
    63
    1. Development
    1. Version controlled
    2. Branched development

    View Slide

  94. Workflow
    63
    1. Development
    1. Version controlled
    2. Branched development
    3. Pull requests

    View Slide

  95. Workflow
    63
    1. Development
    1. Version controlled
    2. Branched development
    3. Pull requests
    2. Release

    View Slide

  96. Workflow
    63
    1. Development
    1. Version controlled
    2. Branched development
    3. Pull requests
    2. Release
    1. Preview

    View Slide

  97. Workflow
    63
    1. Development
    1. Version controlled
    2. Branched development
    3. Pull requests
    2. Release
    1. Preview
    2. Check

    View Slide

  98. Workflow
    63
    1. Development
    1. Version controlled
    2. Branched development
    3. Pull requests
    2. Release
    1. Preview
    2. Check
    3. Deploy

    View Slide

  99. 64
    Data Sources

    View Slide

  100. 65
    Data Sources – nanoc

    View Slide

  101. 66
    nanoc site CLI
    YARD
    FS
    {

    View Slide

  102. 67
    nanoc CLI – definition
    name                'dostuff'
    usage              'dostuff  [options]'
    aliases          :ds,  :stuff
    summary          'does  stuff'
    description  'This  command  does  a  lot!'
    GITHUB.COM/DDFREYNE/CRI

    View Slide

  103. 68
    nanoc CLI – generated help
    NAME
           dostuff  -­‐  does  stuff
    USAGE
           dostuff  [options]
    DESCRIPTION
           This  command  does  a  lot  of  stuff.  I  really  mean  a  lot.
    OPTIONS
           -­‐h  -­‐-­‐help            show  help  for  this  command
           -­‐m  -­‐-­‐more            do  even  more  stuff
           -­‐s  -­‐-­‐stuff          specify  stuff  to  do
    GITHUB.COM/DDFREYNE/CRI

    View Slide

  104. 69

    View Slide

  105. nanoc filter
    class  CensorFilter  <  Nanoc::Filter
    identifier  :censor
    #  Some  documentation  goes  here…
    def  run(content,  params={})
    content.gsub('nanoc  sucks',  'nanoc  rocks')
    end
    end
    70

    View Slide

  106. 71

    View Slide

  107. 71

    View Slide

  108. 72

    View Slide

  109. 72

    View Slide

  110. 73

    View Slide

  111. 74
    Data Sources – FOSDEM

    View Slide

  112. {
    75
    FOSDEM site
    PentaBarf
    FS

    View Slide

  113. 76

    View Slide

  114. 77

    View Slide

  115. 78
    github.com/fosdem/website

    View Slide

  116. 78
    github.com/fosdem/website

    View Slide

  117. SSGs advantages
    79

    View Slide

  118. SSGs advantages
    ‣ More than Markdown + layout → HTML!
    79

    View Slide

  119. SSGs advantages
    ‣ More than Markdown + layout → HTML!
    ‣ Satisfactory in many cases
    79

    View Slide

  120. SSGs advantages
    ‣ More than Markdown + layout → HTML!
    ‣ Satisfactory in many cases
    ‣ Dynamic with JavaScript
    79

    View Slide

  121. SSGs advantages
    ‣ More than Markdown + layout → HTML!
    ‣ Satisfactory in many cases
    ‣ Dynamic with JavaScript
    ‣ Usable for publishing your data
    79

    View Slide

  122. 80
    Lessons Learnt

    View Slide

  123. Internal DSLs
    81

    View Slide

  124. Internal DSLs
    compile  '/about/'  do
    filter  :kramdown
    end
    82

    View Slide

  125. Internal DSLs – side effects
    compile  '/about/'  do
    filter  :kramdown
    File.open('output/stuff.txt',  'w')  do  |f|
    f.write(item.raw_content)
    end
    end
    83

    View Slide

  126. Internal DSLs – mutability
    compile  '/articles/*/'  do
       unless  @item[:layout]
    @item[:layout]  =  'article'
    end
       layout  @item[:layout]
    end
    84

    View Slide

  127. Speed
    85

    View Slide

  128. Incremental compilation
    86

    View Slide

  129. Incremental compilation
    86
    ‣ Recompile only what’s necessary

    View Slide

  130. Incremental compilation
    86
    ‣ Recompile only what’s necessary
    ‣ Ω (#items) → Ω(#changed-items)

    View Slide

  131. Incremental compilation
    86
    ‣ Recompile only what’s necessary
    ‣ Ω (#items) → Ω(#changed-items)
    ‣ Scenarios

    View Slide

  132. Incremental compilation
    86
    ‣ Recompile only what’s necessary
    ‣ Ω (#items) → Ω(#changed-items)
    ‣ Scenarios
    Single changed page

    View Slide

  133. Incremental compilation
    86
    ‣ Recompile only what’s necessary
    ‣ Ω (#items) → Ω(#changed-items)
    ‣ Scenarios
    Single changed page
    Changed page that is included elsewhere

    View Slide

  134. Incremental compilation
    86
    ‣ Recompile only what’s necessary
    ‣ Ω (#items) → Ω(#changed-items)
    ‣ Scenarios
    Single changed page
    Changed page that is included elsewhere
    Changed rules

    View Slide

  135. Pick the right libraries
    87

    View Slide

  136. Pick the right libraries
    ‣ RubyPants, Typogruby
    87

    View Slide

  137. Pick the right libraries
    ‣ RubyPants, Typogruby
    Winner: Fast Aleck
    87

    View Slide

  138. Pick the right libraries
    ‣ RubyPants, Typogruby
    Winner: Fast Aleck
    ‣ pygmentize, pygments.rb
    87

    View Slide

  139. Pick the right libraries
    ‣ RubyPants, Typogruby
    Winner: Fast Aleck
    ‣ pygmentize, pygments.rb
    Winner: pygments.rb
    87

    View Slide

  140. 88

    View Slide

  141. 89

    View Slide

  142. 90
    Future Work

    View Slide

  143. Future Work
    91

    View Slide

  144. Future Work
    91
    ‣ Improving speed (Parallellisation)

    View Slide

  145. Future Work
    91
    ‣ Improving speed (Parallellisation)
    ‣ Supporting huge sites

    View Slide

  146. Future Work
    91
    ‣ Improving speed (Parallellisation)
    ‣ Supporting huge sites
    ‣ Writing great documentation

    View Slide

  147. Future Work
    91
    ‣ Improving speed (Parallellisation)
    ‣ Supporting huge sites
    ‣ Writing great documentation
    ‣ Building an active contributors’ community

    View Slide

  148. Future Work
    91
    ‣ Improving speed (Parallellisation)
    ‣ Supporting huge sites
    ‣ Writing great documentation
    ‣ Building an active contributors’ community
    ‣ GUI?

    View Slide

  149. 92
    Recap

    View Slide

  150. SSGs…
    93

    View Slide

  151. SSGs…
    93
    ‣ have big obvious advantages

    View Slide

  152. SSGs…
    93
    ‣ have big obvious advantages
    fast, secure, easy to deploy, …

    View Slide

  153. SSGs…
    93
    ‣ have big obvious advantages
    fast, secure, easy to deploy, …
    ‣ have big non-obvious advantages

    View Slide

  154. SSGs…
    93
    ‣ have big obvious advantages
    fast, secure, easy to deploy, …
    ‣ have big non-obvious advantages
    metadata, data sources, checks, …

    View Slide

  155. SSGs…
    93
    ‣ have big obvious advantages
    fast, secure, easy to deploy, …
    ‣ have big non-obvious advantages
    metadata, data sources, checks, …
    ‣ turn your web site into an open-source project!

    View Slide

  156. SSGs…
    93
    ‣ have big obvious advantages
    fast, secure, easy to deploy, …
    ‣ have big non-obvious advantages
    metadata, data sources, checks, …
    ‣ turn your web site into an open-source project!
    share, learn, collaborate

    View Slide

  157. 94

    View Slide

  158. 94
    MAIL [email protected]
    TWITTER @ddfreyne
    GITHUB github.com/ddfreyne
    WWW nanoc.ws
    GITHUB github.com/nanoc
    IRC freenode #nanoc

    View Slide

  159. 95
    Extra Slides!

    View Slide

  160. Preprocessing
    96
    preprocess  do
    ts  =  Set.new(@items.map  {  |i|  i[:tags]  }.flatten)
    ts.each  do  |tag|
    @items  <<  Nanoc::Item.new(
    "",  {  :tag  =>  tag  },  "/tags/#{tag}/")
    end
    end

    View Slide