/
atom.xml
291 lines (185 loc) · 10.3 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Category: git | TJ VanToll]]></title>
<link href="http://tjvantoll.com/blog/categories/git/atom.xml" rel="self"/>
<link href="http://tjvantoll.com/"/>
<updated>2013-01-24T22:06:33-05:00</updated>
<id>http://tjvantoll.com/</id>
<author>
<name><![CDATA[TJ VanToll]]></name>
<email><![CDATA[tj.vantoll@gmail.com]]></email>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[The Ideal LESS Workflow with git]]></title>
<link href="http://tjvantoll.com/2012/07/07/the-ideal-less-workflow-with-git/"/>
<updated>2012-07-07T00:00:00-04:00</updated>
<id>http://tjvantoll.com/2012/07/07/the-ideal-less-workflow-with-git</id>
<content type="html"><![CDATA[<p>LESS is a CSS pre-processor written in JavaScript. Unlike its main competitor SASS, it has the ability to run both on the client side via a simple <code><script></code> tag, as well as server-side in Node.js. The fact that LESS files can be processed client side is advantageous for a number of reasons:</p>
<h4><strong>There are no dependencies.</strong></h4>
<p>To develop LESS files all you need is your browser. SASS requires Ruby to be running on your system to generate the CSS files.</p>
<p>While some would argue that this isn't a big deal (Ruby is pre-installed on OS X for example), it can potentially put off beginners or those not familiar with the command line. A lot of people that write CSS wear a designer hat more than a developer hat. Even if <em>you</em> know what you're doing, if you're on a team with less technical people oftentimes the simplest approach will make everyone happy.</p>
<h4><strong>You can auto-reload changes to less files without reloading the browser and without external dependencies.</strong></h4>
<p>With LESS you can easily watch for changes by appending <code>#!watch</code> to the URL or by running <code>less.watch()</code> from the console. There's no additional setup and no need to reload your browser, changes take effect automatically.</p>
<p>If you want files to be regenerated using SASS you must tell SASS which files to watch via the command line or use an app that does that for you. If you want CSS changes to happen without reloading your browser you need to enlist the help of an app / extension such as <a href="http://livereload.com">LiveReload</a>. While this works fine this is yet another dependency.</p>
<!--more-->
<h3>Production</h3>
<p>While the ease of use during development is great, you don't want visitors to your site to incur the cost of processing the LESS files client side in a production setting. The easy way to accomplish this is to manually run <code>lessc</code> from the command line to convert all LESS files into CSS files, and then updating all of your .less paths in <code><link></code> tags to use .css paths.</p>
<p>This works, but the lazy programmer in you will be looking to automate this after doing this more than once. If you're using Git for source control one way you can accomplish this is by running a commit hook to do the generation.</p>
<h3>Git Commit Hooks</h3>
<p><a href="http://git-scm.com/book/en/Customizing-Git-Git-Hooks">Git commit hooks</a> allow you to run scripts whenever a commit occurs. A <code>pre-commit</code> hook allows you to run a script that can also optionally prevent the commit from occurring. The <code>pre-commit</code> hook works well for generating CSS files from LESS files for a few reasons.</p>
<ul>
<li>Once the script is in place you no longer have to manually generate CSS files, it'll simply be done automatically when you commit changes to source control.</li>
<li>The script can be setup so that if <code>lessc</code> fails the commit will be rejected. Therefore, LESS files with invalid syntax will be kept out of source control.</li>
</ul>
<p>To create a Git commit hook navigate into the <code>.git/hooks</code> directory of your repository. This folder has a number of sample hooks that you can potentially use with a <code>.sample</code> suffix. To create a <code>pre-commit</code> script that Git will run simply create an un-prefixed copy of <code>pre-commit.sample</code>.</p>
<p><code>bash
cd /MyProject/.git/hooks
cp pre-commit.sample pre-commit
</code></p>
<p>Once a <code>pre-commit</code> file exists in <code>.git/hooks</code>, Git will run it before every commit.</p>
<h3>The Script</h3>
<p>There are many ways to implement a script that generates CSS files from LESS files. This is the <code>pre-commit</code> script that I use.</p>
<p>``` bash The script</p>
<h1>!/bin/sh</h1>
<h1>Pre-commit hook to generate .css files from .less files using lessc.</h1>
<h1>Script assumes .less files are in a directory named "less" and will</h1>
<h1>put the generated files in a sibling "css" directory. The generated</h1>
<h1>CSS will also be compressed as part of lessc.</h1>
<p>#</p>
<h1>When .less files are deleted the script will delete the corresponding</h1>
<h1>.css files if they exist.</h1>
<p>#</p>
<h1>Example</h1>
<h1>-------</h1>
<p>#</p>
<h1>Before: After:</h1>
<p>#</p>
<h1>foo/ foo/</h1>
<h1>less/ css/</h1>
<h1>a.less a.css</h1>
<h1>bar/ less/</h1>
<h1>less/ a.less</h1>
<h1>b.less bar/</h1>
<h1>css/</h1>
<h1>b.css</h1>
<h1>less</h1>
<h1>b.less</h1>
<p>#</p>
<h1>Loop over all files included in the commit.</h1>
<p>for file in $( exec git diff-index --cached --name-only HEAD )
do</p>
<h1>We only want to take action unless the file is a LESS file.</h1>
<p> if [[ $file == <em>".less"</em> ]]; then</p>
<pre><code>lessFile=$file
</code></pre>
<h1>Find where the corresponding CSS file should be located</h1>
<h1>in the file system, in this case a sibling CSS directory.</h1>
<pre><code>cssFile="${lessFile/less\//css/}"
cssFile="${cssFile/.less/.css}"
</code></pre>
<h1>Determine the status of the file in the commit.</h1>
<h1>M = Modified, A = Added, D = deleted, R = renamed,</h1>
<h1>C = copied, U = Updated but unmerged</h1>
<pre><code>status=$( exec git status --porcelain $lessFile )
</code></pre>
<h1>If the file was deleted as part of the commit, delete the</h1>
<h1>corresponding CSS file.</h1>
<pre><code>if [[ $status == D* ]]; then
if [ -e "$cssFile" ]; then
echo "Removing $cssFile"
git rm $cssFile
fi
else
</code></pre>
<h1>Otherwise we must generate the CSS file. First create a</h1>
<h1>CSS folder to place the file in. The -p option for mdkir</h1>
<h1>tells it to create parent folders if necessary.</h1>
<pre><code> baseDirectory=${lessFile/less\/*/}
mkdir -p ${baseDirectory}css
</code></pre>
<h1>Log to the console that the CSS is being generated so the person</h1>
<h1>running the commit is aware.</h1>
<pre><code> echo "Generating $cssFile from $lessFile"
</code></pre>
<h1>Run lessc to do the actual generation. If lessc fails exit</h1>
<h1>with a code of 1 so that the commit is rejected. The -x option</h1>
<h1>tells lessc to generate compressed CSS for production usage.</h1>
<pre><code> if ! lessc -x $lessFile $cssFile; then
exit 1
fi
</code></pre>
<h1>Add the CSS file to the commit.</h1>
<pre><code> git add $cssFile
fi
</code></pre>
<p> fi
done
```</p>
<p>You could greatly simplify this script to simply run <code>lessc</code> on all .less files on every commit. I go file by file because the script has to be run on a large code base where generating hundreds to thousands of CSS files on every commit isn't practical. This script is also setup to create sibling <code>css</code> and <code>less</code> directories. You could easily modify this to simply put the files in the same directory; I like them to be logically separated.</p>
<h3>Automating <code><link></code> File Paths</h3>
<p>As I said, the script I use assumes that there are sibling <code>css</code> and <code>less</code> directories. To give a concrete example of this say I have the following file system structure.</p>
<pre><code>/MyProject
/css
* Generated files *
index.html
/js
less.js
/less
a.less
b.less
</code></pre>
<p>To include these files I use the following locally:</p>
<p>``` html Local Includes</p>
<!-- index.html -->
<p><!DOCTYPE html>
<html></p>
<pre><code><head>
<link rel="stylesheet/less" href="less/a.less">
<link rel="stylesheet/less" href="less/b.less">
<script src="js/less.js"></script>
</head>
<body>
</body>
</code></pre>
<p></html>
```</p>
<p>And the following in production:</p>
<p>``` html Production Includes</p>
<!-- index.html -->
<p><!DOCTYPE html>
<html></p>
<pre><code><head>
<link rel="stylesheet" href="css/a.css">
<link rel="stylesheet" href="css/b.css">
</head>
<body>
</body>
</code></pre>
<p></html>
```</p>
<p>The best way to handle both development and production with minimal maintenance is to use some sort of server-side check so that you don't have to change your HTML whenever you release to production. Here's an example of a PHP script that does this by detecting whether the host contains <code>localhost</code>.</p>
<p>``` html Making both imports work</p>
<!-- index.html -->
<p><!DOCTYPE html>
<html></p>
<pre><code><head>
<? if (strpos($_SERVER['HTTP_HOST'], 'localhost')) { ?>
<link rel="stylesheet/less" href="http://tjvantoll.com/less/a.less">
<link rel="stylesheet/less" href="http://tjvantoll.com/less/b.less">
<script src="http://tjvantoll.com/js/less.js"></script>
< } else { ?>
<link rel="stylesheet" href="http://tjvantoll.com/css/a.css">
<link rel="stylesheet" href="http://tjvantoll.com/css/b.css">
<? } ?>
</head>
<body>
</body>
</code></pre>
<p></html>
```</p>
<h3>Conclusion</h3>
<p>Using LESS client side is awfully convenient, but it shouldn't be done in a production setting. If you use LESS a lot then this is something you'll want to automate in your workflow. In my opinion using a git <code>pre-commit</code> hook is a clean way to accomplish this. Feel free to use my script or alter it to your liking. If you have any other ways you automate your LESS workflow I'd love to hear about it. Let me know in the comments.</p>
]]></content>
</entry>
</feed>