/src/Website/Views/Documentation/GettingStarted_CombineAssetsIntoModules.cshtml

https://github.com/IanPatrickHughes/cassette · Razor · 125 lines · 114 code · 11 blank · 0 comment · 5 complexity · 215d573cfa0e3d97b75ada4af9bd9315 MD5 · raw file

  1. <h1>Combine assets into modules</h1>
  2. <p>Out of the box, Cassette runs in a very simple mode where each asset is treated separately.
  3. However, referencing many separate assets in production is bad for performance.
  4. So let's configure Cassette to combine assets into modules.
  5. </p>
  6. <h2>Wait a sec... Assets and modules?</h2>
  7. <p>An asset is any static file that ends up being used in the web browser, such JavaScript, CSS, CoffeeScript, LESS, HTML templates, etc.</p>
  8. <p>A module is a collection of assets that form a single resource, when deployed in production.</p>
  9. <p>For example, a collection of jQuery plugins can be combined into a single script. Cassette lets you keep
  10. each source file separate to make debugging easy. Then in production mode, Cassette will concatenate the files
  11. together.</p>
  12. <p>Cassette has three types of module:</p>
  13. <ul>
  14. <li>Scripts</li>
  15. <li>Stylesheets</li>
  16. <li>HTML Templates</li>
  17. </ul>
  18. <p>Each module is processed using a sequence of steps that transform the assets. For example, CoffeeScript assets are compiled into JavaScript.</p>
  19. <p>We need to tell Cassette how to build these modules.</p>
  20. <h2>Configuration</h2>
  21. <p>The <code>Cassette.Web</code> nuget package adds a file to your project called <code>CassetteConfiguration.cs</code>.
  22. The class in that file is used to configure Cassette.</p>
  23. <pre><code><span class="keyword">public class</span> <span class="code-type">CassetteConfiguration</span> : <span class="code-type">ICassetteConfiguration</span>
  24. {
  25. <span class="keyword">public</span> <span class="keyword">void</span> Configure(
  26. <span class="code-type">ModuleConfiguration</span> moduleConfiguration,
  27. <span class="code-type">ICassetteApplication</span> application)
  28. {
  29. <span class="comment">// ... configure Cassette here ...</span>
  30. }
  31. }</code></pre>
  32. <p class="minor">When the configuration is empty, Cassette will default to treating each asset as a separate module.</p>
  33. <h2>Group assets into directories</h2>
  34. <p>It's time to organise that untidy scripts directory! Each application is different, but essentially you need to
  35. divide the scripts into directories. Here's an example directory listing:</p>
  36. <pre><code>scripts/
  37. lib/
  38. jquery.js
  39. jquery-ui.js
  40. underscore.js
  41. shared/
  42. sidebar.js
  43. widget.js
  44. forms.js
  45. signup/
  46. index.js
  47. dashboard/
  48. index.js
  49. user.js
  50. other.js
  51. </code></pre>
  52. <p class="minor">Note that there are no <code>.min.js</code> files in there. Cassette will perform the minification for you.</p>
  53. <p>
  54. Keep in my that a module is a <em>unit of deployment</em>.
  55. If any asset in a module changes, then the entire module has to be downloaded again by web browsers.
  56. So perhaps group shared code into a module and put page scripts into their own modules.
  57. </p>
  58. <h2>Configure module sources</h2>
  59. <p>On application start up, Cassette will build the modules. A "module source" says where to look for assets and how to group them into modules.</p>
  60. <p>So far we've relied on the default <code>PerFileSource</code>. Let's change this to use directories instead.</p>
  61. <pre><code><span class="keyword">public class</span> <span class="code-type">CassetteConfiguration</span> : <span class="code-type">ICassetteConfiguration</span>
  62. {
  63. <span class="keyword">public</span> <span class="keyword">void</span> Configure(
  64. <span class="code-type">ModuleConfiguration</span> moduleConfiguration,
  65. <span class="code-type">ICassetteApplication</span> application)
  66. {
  67. moduleConfiguration.Add(
  68. <span class="keyword">new</span> <span class="code-type">DirectorySource</span>&lt;<span class="code-type">ScriptModule</span>&gt;(<span class="string">"scripts/lib"</span>, <span class="string">"scripts/shared"</span>, <span class="string">"scripts/signup"</span>, <span class="string">"scripts/dashboard"</span>)
  69. {
  70. FilePattern = <span class="string">"*.js"</span>
  71. }
  72. );
  73. }
  74. }</code></pre>
  75. <p>Here we've added a new <code>DirectorySource&lt;ScriptModule&gt;</code> object and listed the application relative directory paths.
  76. We've also set the <code>FilePattern</code> property so it only looks for JavaScript files.</p>
  77. <p>If there are many directories, it can be tedious to type them all in. Instead, use the <code>PerSubDirectorySource</code>:</p>
  78. <pre><code><span class="keyword">public class</span> <span class="code-type">CassetteConfiguration</span> : <span class="code-type">ICassetteConfiguration</span>
  79. {
  80. <span class="keyword">public</span> <span class="keyword">void</span> Configure(
  81. <span class="code-type">ModuleConfiguration</span> moduleConfiguration,
  82. <span class="code-type">ICassetteApplication</span> application)
  83. {
  84. moduleConfiguration.Add(
  85. <span class="keyword">new</span> <span class="code-type">PerSubDirectorySource</span>&lt;<span class="code-type">ScriptModule</span>&gt;(<span class="string">"scripts"</span>)
  86. {
  87. FilePattern = <span class="string">"*.js"</span>
  88. }
  89. );
  90. }
  91. }</code></pre>
  92. <p>Cassette will now create a module for each sub-directory of the scripts directory.</p>
  93. <h2>Referencing modules</h2>
  94. <p>When each asset was treated separately our view pages had to reference each file. For example:</p>
  95. <pre><code><span class="code-tag">@@{</span>
  96. <span class="code-type">Assets</span>.Scripts.Reference(<span class="string">"scripts/dashboard/index.js"</span>);
  97. <span class="code-type">Assets</span>.Scripts.Reference(<span class="string">"scripts/dashboard/user.js"</span>);
  98. <span class="code-type">Assets</span>.Scripts.Reference(<span class="string">"scripts/dashboard/other.js"</span>);
  99. <span class="code-tag">}</span>
  100. </code></pre>
  101. <p>This can be simplified to a single reference to the module directory:</p>
  102. <pre><code><span class="code-tag">@@{</span>
  103. <span class="code-type">Assets</span>.Scripts.Reference(<span class="string">"scripts/dashboard"</span>);
  104. <span class="code-tag">}</span>
  105. </code></pre>
  106. <p>Please note: Referencing a specific asset file will still work, however this will also include <strong>all</strong> the assets
  107. in the module. Modules are "all or nothing".</p>
  108. <p>This also applies to reference within assets. For example, an asset in one module can reference other module.</p>
  109. <pre><code><span class="comment">/// &lt;reference path="~/scripts/lib" /></span>
  110. <span class="comment">jQuery is in the 'lib' module, so we can now use it in this file.</span>
  111. jQuery(document).ready(function() {
  112. ...
  113. });</code></pre>
  114. <p>However, you will lose Visual Studio IntelliSense when referencing like this.</p>