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.

Be732ee41fd3038aa98a0a7e7b7be081?s=128

Denis Defreyne

February 03, 2013
Tweet

Transcript

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

    1
  2. Me 2

  3. Me 2 ‣ Denis Defreyne

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

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

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

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

    ‣ Author of nanoc
  8. What exactly does a STATIC SITE GENERATOR do? 3

  9. 4

  10. 4 Mark- down

  11. Markdown 5 In  *exactly*  one  month,  there’s  FOSDEM   again!

     I  can  barely  control  my  excitement! *  First  element  of  a  list *  Second  element
  12. 6 Mark- down

  13. 6 Mark- down HTML fragment

  14. HTML from Markdown 7 <p>In  <em>exactly</em>  one  month,  there’s  

    FOSDEM  again!  I  can  barely  control  my   excitement!</p> <ul> <li>First  element  of  a  list</li> <li>Second  element</li> </ul>
  15. 8 Mark- down HTML fragment

  16. 8 Mark- down HTML fragment Layout

  17. Layout 9 <!DOCTYPE  html> <html> <head> <title><%=  item[:title]  %></title> </head>

    <body> <%=  yield  %> </body> </html>
  18. 10 Mark- down HTML fragment Layout

  19. 10 Mark- down HTML fragment Layout + HTML

  20. 11 <!DOCTYPE  html> <html> <head> <title>One  Month  until  FOSDEM!</title> </head>

    <body> <p>In  <em>exactly</em>  one  month,  there’s  FOSDEM   again!  I  can  barely  control  my  excitement!</p> <ul> <li>First  element  of  a  list</li> <li>Second  element</li> </ul> </body> </html>
  21. 12 Mark- down HTML fragment Layout + HTML

  22. 13

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

    13
  24. 14 nanoc φϊοΫ

  25. 15

  26. 16 CMS Content Management System

  27. 16 CMS Content Management System

  28. 17 SSG Static Site Generator

  29. Road map 18

  30. Road map 1. What are SSGs? 18

  31. Road map 1. What are SSGs? 2. What are SSGs

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

    capable of? 3. Lessons Learnt & Future Work 18
  33. 19 What are SSGs?

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

  35. Tiny example – pages 21 -­‐-­‐-­‐ title:  One  Month  until

     FOSDEM! -­‐-­‐-­‐ In  exactly  one  month,  there’s  FOSDEM  again!   I  can  barely  control  my  excitement!
  36. Tiny example – layouts 22 <html> <head> <title><%=  item[:title]  %></title>

    </head> <body> <%=  yield  %> </body> </html>
  37. Tiny example – result 23 <html> <head> <title>One  Month  until

     FOSDEM!</title> </head> <body> In  exactly  one  month,  there’s  FOSDEM  again!  I   can  barely  control  my  excitement! </body> </html>
  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

  39. 25

  40. 26

  41. 27

  42. 28

  43. 29

  44. 30

  45. 31

  46. 32

  47. 33

  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
  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
  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
  51. 34

  52. 35

  53. 36

  54. 37 Why static sites?

  55. 37 1. Fast Why static sites?

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

  57. 37 1. Fast 2. Secure 3. Works with your own

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

    tools (vim!) 4. Content is in plain text Why static sites?
  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?
  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?
  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?
  62. 38

  63. 39 What are SSGs capable of?

  64. Arbitrary metadata 40

  65. Arbitrary metadata 41 title:      Braid kind:    

       review subtype:  game year:        2008 rating:    5
  66. Arbitrary metadata 42 <ul> <%  @item.children  do  |review|  %> <li>

    <%=  '˒'  *  review[:rating]  %> <%=  review[:title]  %> </li> <%  end  %> </ul>
  67. Arbitrary metadata 43 <ul> <li>˒˒˒˒ˑ  Borderlands</li> <li>˒˒˒˒˒  Braid</li> <li>˒˒˒˒ˑ  Legend

     of  Grimrock</li> <li>˒˒˒˒˒  Max  Payne</li> <li>˒˒˒˒ˑ  Minecraft</li> </ul>
  68. Filters 44

  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
  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
  71. Filters – ERB <!DOCTYPE  html> <html> <head> <title><%=  item[:title]  %></title>

    </head> <body> <%=  yield  %> </body> </html> 47
  72. Filters – Mustache <!DOCTYPE  html> <html> <head> <title>{{  title  }}</title>

    </head> <body> {{  yield  }} </body> </html> 48
  73. Filters – Haml !!! %html %head %title=  @item[:title] %body =

     yield 49
  74. Filters – Colorize Syntax <pre><code  class="language-­‐ruby"> def  my_function    (1..10).map

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

           "#{i}  is  #{i  %  2  ==  1  ?  'odd'  :  'even'}"    end end 51
  76. Filters – Typogruby 52 "Typogruby makes HTML look smarter &

    better, don't you think?" “Typogruby makes HTML look smarter & better, don’t you think?”
  77. Filters – Custom class  CensorFilter  <  Nanoc::Filter identifier  :censor def

     run(content,  params={}) content.gsub('nanoc  sucks',  'nanoc  rocks') end end 53
  78. Rules 54

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

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

  81. Rules 57 compile  '/images/*/'  do    filter  :img_optimize end compile

     '/images/*/',  :rep  =>  :thumbnail  do    filter  :scale,  :width  =>  140 end
  82. Rules 58 compile  '/blog/*/',  :rep  =>  :mp3  do    filter

     :say    filter  :lame end
  83. Rules versus Makefiles 59

  84. Rules versus Makefiles 59 ‣ Push vs. pull

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

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

    syntax ‣ Automatic dependency tracking
  87. Helpers 60

  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
  89. Helpers – example 62 <h1>Tags  for  <%=  @item[:tag]  %></h1> <ul>

    <%  items_with_tag(@item[:tag]).each  do  |i|  %> <li><%=  link_to(@item[:tag],  i)  %></li> <%  end  %> </ul>
  90. Workflow 63

  91. Workflow 63 1. Development

  92. Workflow 63 1. Development 1. Version controlled

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

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

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

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

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

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

    3. Pull requests 2. Release 1. Preview 2. Check 3. Deploy
  99. 64 Data Sources

  100. 65 Data Sources – nanoc

  101. 66 nanoc site CLI YARD FS {

  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
  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
  104. 69

  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
  106. 71

  107. 71

  108. 72

  109. 72

  110. 73

  111. 74 Data Sources – FOSDEM

  112. { 75 FOSDEM site PentaBarf FS

  113. 76

  114. 77

  115. 78 github.com/fosdem/website

  116. 78 github.com/fosdem/website

  117. SSGs advantages 79

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

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

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

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

    ‣ Satisfactory in many cases ‣ Dynamic with JavaScript ‣ Usable for publishing your data 79
  122. 80 Lessons Learnt

  123. Internal DSLs 81

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

  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
  126. Internal DSLs – mutability compile  '/articles/*/'  do    unless  @item[:layout]

    @item[:layout]  =  'article' end    layout  @item[:layout] end 84
  127. Speed 85

  128. Incremental compilation 86

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

  130. Incremental compilation 86 ‣ Recompile only what’s necessary ‣ Ω

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

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

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

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

    (#items) → Ω(#changed-items) ‣ Scenarios Single changed page Changed page that is included elsewhere Changed rules
  135. Pick the right libraries 87

  136. Pick the right libraries ‣ RubyPants, Typogruby 87

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

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

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

    ‣ pygmentize, pygments.rb Winner: pygments.rb 87
  140. 88

  141. 89

  142. 90 Future Work

  143. Future Work 91

  144. Future Work 91 ‣ Improving speed (Parallellisation)

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

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

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

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

    sites ‣ Writing great documentation ‣ Building an active contributors’ community ‣ GUI?
  149. 92 Recap

  150. SSGs… 93

  151. SSGs… 93 ‣ have big obvious advantages

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

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

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

    to deploy, … ‣ have big non-obvious advantages metadata, data sources, checks, …
  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!
  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
  157. 94

  158. 94 MAIL denis.defreyne@stoneship.org TWITTER @ddfreyne GITHUB github.com/ddfreyne WWW nanoc.ws GITHUB

    github.com/nanoc IRC freenode #nanoc
  159. 95 Extra Slides!

  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