基于browser-sync的前端预处理器工作流

之前使用预处理器一直是基于vim插件autocommand,最近和同事协作开发,vim入门太陡峭,抽了点时间用browser-sync实现了类似功能。具体功能如下:自动检测jade、sass、livescript等源码文件的改动,编译对应的html、css、js,更新改动到浏览器中打开的页面。

明确几个定义:
1. browser-sync nodejs插件,官方说明 Time-saving synchronised browser testing。
2. 前端预处理器 jade、sass、livescript。
3. 工作流 使用browser-sync整合jade、sass、livescript完成开发的一套流程。

依赖:
nodejs
 npm package: jade、livescript、browser-sync
ruby
 gem package: sass

工作目录:

workspace/
  _source/
    jade/
    sass/
    live/
  html
    css/
    js/
    img/

说明:_source目录下存放预处理器源代码,html目录存放生成的html、css、js等。

在workspace目录下创建 browserSync.ls 具体代码如下:

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
path = require \path
exec = require \child_process .exec
browserSync = require \browser-sync .create!
 
# config {{{
outputDir = 'html'
cssOutputDir = "#outputDir/css"
jsOutputDir = "#outputDir/js"
 
reloadWatchFile = ''
  # "#outputDir/*.html"
  # "#jsOutputDir/*.js"
  # "#outputDir/img/*.*"
 
compileWatchFile =
  "_source/jade/*.jade"
  "_source/sass/*.sass"
  "_source/live/*.ls"
 
autoCompileFile = true
# }}}
# getTimeToken {{{
getTimeToken = ->
  currDate = new Date()
  hours = currDate.getHours()
  minutes = currDate.getMinutes()
  seconds = currDate.getSeconds()
  if hours < 10
    hours = "0#hours"
  if minutes < 10
    minutes = "0#minutes"
  if seconds < 10
    seconds = "0#seconds"
  "#hours:#minutes:#seconds"
# }}}
# compileTask {{{
getCompileCmdAndFileName = (file, ext) ->
  filename = path.basename file, ext
 
  switch ext
  case '.jade' then
    compileFileName = "#outputDir/#{filename}.html"
    cmd = "jade -Po #outputDir #file"
  case '.sass' then
    compileFileName = "#cssOutputDir/#{filename}.css"
    cmd = "sass --sourcemap=none --style compact #file|sed '/^@charset/d'>#compileFileName"
  case '.coffee' then
    compileFileName = "#jsOutputDir/#{filename}.js"
    cmd = "coffee --no-header -bco #jsOutputDir #file"
  case '.ls' then
    compileFileName = "#jsOutputDir/#{filename}.js"
    cmd = "lsc --no-header -bco #jsOutputDir #file"
  default
    compileFileName = cmd = ''
  [cmd, compileFileName]
 
compileTask = (file, ext, reload) !->
  cmdIndex = -1
  try
    [cmd, filename] = getCompileCmdAndFileName file, ext
 
  if not cmd or not filename
    console.log "cmd not define. file: #file ext: #ext"
 
  # exec callback
  execCallback = (err, stdo, stde) !->
    if err is null and not stde
      if cmdIndex is -1
        console.log "[#{getTimeToken!}] compiled #filename"
        reload filename if reload
      else
        execCmd()
    else
      console.log err || stde
 
  # execute command
  do execCmd = !->
    if Array.isArray cmd
      currCmd = cmd[++cmdIndex]
      if cmd.length <= cmdIndex+1
        ``cmdIndex = -1;``
    else
      currCmd = cmd
 
    if currCmd
      exec currCmd, execCallback
 
compileCallback = (file) !->
  ext = path.extname file
  filename = path.basename file
 
  # ignore partial file
  if filename.charAt(0) is '_'
    return undefined
 
  switch ext
  case '.jade', '.coffee', '.ls', '.sass'
    #   compileTask file, ext
    # case '.sass'
    compileTask file, ext, browserSync.reload
  default
    console.log 'unknown file type.'
# }}}
# browserSync {{{
browserSync.init do
  server:
    baseDir: outputDir
    index: \index.html
  open: false
 
if reloadWatchFile and reloadWatchFile.length
  browserSync.watch reloadWatchFile
  .on \change, browserSync.reload
 
wacher = browserSync.watch compileWatchFile
.on \change, compileCallback
# auto compile file
if autoCompileFile
  wacher.on \add, compileCallback
# }}}
 
# vim: set sw=2 ts=2 sts=2 et fdm=marker:

使用方法如下:
cd workspace
lsc browserSync.ls

* lsc 是 livescript的命令,使用npm 全局安装 livescript 后方可使用。

配置说明:
outputDir        html文件的输出目录,web server的根目录。
cssOutputDir     css文件输出目录。
jsOutputDir      js文件输出目录。
reloadWatchFile  检测改动的目录,如果文件发生变更,会更新到打开的页面中。html/css/js已自动更新,默认可留空。
compileWatchFile 监测的源码文件,如果发生变化执行编译任务。
autoCompileFile  自动编译文件,设为true时,每次启动会把所有的源码文件编译一遍。