1 | # Watchalive!
|
2 |
|
3 | > Serve, watch, compile sources, receive events/data and trigger custom actions in browsers.
|
4 |
|
5 |
|
6 | ## Caution (current state)
|
7 |
|
8 | This project is not intended to be used as open source. DO NOT try to use it.
|
9 |
|
10 | ## Features
|
11 | - Serves development sources and assets using its own HTTP server.
|
12 | - Watches file changes and sends the events/date to the client (default action on file change is page reload), using web sockets.
|
13 | - Compiles (transpiles) resources and watches the dependencies for changes. Can be easily extended via transpile plugins. Currently bundled with LESS/CSS plugin out of the box.
|
14 | - Can proxy and route requests or use custom middleware to handle requests.
|
15 | - Fully configurable.
|
16 |
|
17 | ## Advantages
|
18 |
|
19 | Advantages over other solutions like `livereload`, `live-server`, `browser-sync`, etc:
|
20 |
|
21 | - Watches only files served to client(s).
|
22 | - Caches watched files, so loading time of client page is faster.
|
23 | - Simple transpiler plugin system, allows you to serve any sources like `*.coffee, *.scss, *.less, etc` in transparent manner without need to have compiled version on the drive.
|
24 | - It notifies client side about particular changes (by default send list of changed files urls).
|
25 | - It can send sources of changed files.
|
26 | - Watch dependencies of transpiled files for changed.
|
27 | - You can do with this what ever you want, reload page, do live refresh of css styles, or hot replacement of JS modules, rerun test, whatever.
|
28 | - Flexible custom routes and proxies configuration support.
|
29 |
|
30 | ## Installation and usage
|
31 |
|
32 | > npm install watchalive
|
33 |
|
34 | ### Server side usage:
|
35 |
|
36 | ```javascript
|
37 | var Watchalive = require('watchalive')
|
38 |
|
39 | var wa = new Watchalive({
|
40 | port: 7001,
|
41 | base: __dirname,
|
42 | transpile: {
|
43 | less: true
|
44 | },
|
45 | route: [
|
46 | {'/': '/web/index.html'},
|
47 | {'/bootstrap/*': '/bower_components/bootstrap/*'},
|
48 | {'/mobile': '/mobile/index.html'},
|
49 | ],
|
50 | proxy: {context: '/api', port: 4000},
|
51 | skip: ['bower_components/*', 'node_modules/*', '**/favicon.ico'],
|
52 | console: true, // will send console outputs to server
|
53 | reload: true // will make client page reload on any file changes
|
54 | })
|
55 |
|
56 | wa.start()
|
57 | ```
|
58 |
|
59 | After this watchalive is available http://localhost:7000
|
60 |
|
61 | This is a flat version of config (some options may overlap, use consciously). You can give more structure to it (see `Default Config`).
|
62 |
|
63 |
|
64 |
|
65 | #### Command line usage
|
66 |
|
67 | You may also install it globally to use from command line
|
68 | > npm install watchalive -g
|
69 |
|
70 | Usage:
|
71 | > watchalive [options]
|
72 |
|
73 | > watchalive --port 8000 --base /front-app
|
74 |
|
75 | > watchalive --config myconfig.json
|
76 |
|
77 | > watchalive myconfig.json
|
78 |
|
79 | By default looks up 'watchalive.json' in working directory to use as config file.
|
80 |
|
81 | #### Grunt/gulp task wrapper
|
82 | > npm install watchalive-runner
|
83 |
|
84 | Just pass your config as options to watchalive grunt/gulp task.
|
85 | In grunt/gulp task there is available option `useGlobal` (`boolean, false`) tells if to use locally installed watchalive version or global one.
|
86 | By default the tasks looks up for local watchalive package and falls back to global.
|
87 |
|
88 |
|
89 | ### Client side usage:
|
90 |
|
91 | Watchalive client is not intended to do some client work (except page reload if needed), but rather to allow you handle server events and data, and do any custom actions you need.
|
92 |
|
93 | By default client watchalive script is injected first in the head, that will make available global `watchalive` object in the page at load time.
|
94 |
|
95 | You can configure it like:
|
96 |
|
97 | ```HTML
|
98 | <script>
|
99 |
|
100 | watchalive.config({
|
101 | host: 'http://myserver.local:7001', // custom host if watchalive server is not on the same domain
|
102 | reload: true, // make page reload on any file changes received,
|
103 | console: ['error'] // intercept console `error` calls and sends it to the server
|
104 | })
|
105 |
|
106 | // you can manually handle file change data received from server
|
107 | watchalive.onFiles(function(changes){
|
108 | changes.forEach(function(file){
|
109 | if (/\.css$/.test(file)){
|
110 | // simple css link hot reload
|
111 | var sheets = document.getElementsByTagName("link");
|
112 | for (var i = 0; i < sheets.length; ++i) {
|
113 | var elem = sheets[i];
|
114 | var rel = elem.rel;
|
115 | if (elem.href && rel == "stylesheet") {
|
116 | var url = elem.href.replace(/\?\d+/, '');
|
117 | if (url.lastIndexOf(file) + file.length == url.length){
|
118 | elem.href = url + '?' + (new Date().valueOf());
|
119 | }
|
120 | }
|
121 | }
|
122 | } else {
|
123 | window.location.reload()
|
124 | }
|
125 | })
|
126 | })
|
127 |
|
128 | </script>
|
129 | ```
|
130 |
|
131 |
|
132 | ## Default config
|
133 | The default config gives you a <b>quick look</b> on all options and default values that will be merged with your config values.
|
134 |
|
135 | ```javascript
|
136 | var defaultConfig = {
|
137 | port: 7000, // port to serve files and handle socket connection
|
138 | base: process.cwd(), // base from where files are served and resolved
|
139 | stdin: true, // enable basic management via stdin commands
|
140 | debug: false, // output debug messages
|
141 |
|
142 | serve: {
|
143 | clientLibName: 'watchalive.js',
|
144 | injectScript: true, // inject client script in HTML automatically
|
145 | injectSocketIo: true, // if false won't load socket.io
|
146 | injectScriptTo: 'head', // where to inject script `head` or `body`
|
147 | transpile: {}, // enabled embedded and custom transpilers
|
148 | route:[], // additional flexible config for routes
|
149 | proxy: [], // proxy requests config (for example to API server)
|
150 | middleware: [], // middlewares for express.js server (NOT IMPLEMENTED)
|
151 | favicon: 'favicon.png', // use standard express.js middleware to serve favicon
|
152 | http2: false, // enables HTTP2 server
|
153 | httpOptions: false // options to pass to HTTP server
|
154 | },
|
155 | watch: {
|
156 | dependencies: true, // watch for dependencies (of transpiled files)
|
157 | files: [], // additionally watch for matched files (NOT IMPLEMENTED)
|
158 | skip: [], // skip some files
|
159 | served: true, // watch for files served by HTTP server
|
160 | poolInterval: 200, // interval for pooling
|
161 | debounce: 100 // delay to handle multiple
|
162 | },
|
163 | clients: {
|
164 | badge: true, // show badge on client (NOT IMPLEMENTED, badge always shown)
|
165 | reload: false, // if clients should be reloaded on change events
|
166 | console: false, // should console be intercepted on clients
|
167 | allowMessages: true, // show custom message (NOT IMPLEMENTED)
|
168 | sendData: false // send changed files data to client
|
169 | }
|
170 | }
|
171 | ```
|
172 |
|
173 |
|
174 | ## Options
|
175 |
|
176 | ###### port
|
177 | Type: `Number`
|
178 | Default value: `7000`
|
179 |
|
180 | Port for running Express server and sockets endpoint
|
181 |
|
182 | ###### base
|
183 | Type: `String`
|
184 | Default value: `process.cwd()`
|
185 |
|
186 | Base directory (root from where developers assets are served), this is also base directory for other relative paths in config.
|
187 |
|
188 | ###### stdin
|
189 | Type: `Boolean`
|
190 | Default value: `true`
|
191 |
|
192 | Enable commands via standard input
|
193 |
|
194 | ###### debug
|
195 | type: `boolean`, default: `false`
|
196 |
|
197 | Enable output of debug messages.
|
198 |
|
199 | -----
|
200 |
|
201 | ###### serve
|
202 | Type: `Boolean|Object`
|
203 | Default value: `true`
|
204 |
|
205 | Sets serving rules. If `true` then `default` options are used. If `false` disable files serving.
|
206 |
|
207 | ###### serve.clientLibName
|
208 | Type: `String`
|
209 | Default value: `watchalive.js`
|
210 |
|
211 | Name of client script to load via script tag.
|
212 |
|
213 | ###### serve.injectScript
|
214 | Type: `Boolean`
|
215 | Default value: `true`
|
216 |
|
217 | Enable automatic injection of client script tag in HTML.
|
218 |
|
219 | ###### serve.injectSocketIo
|
220 | Type: `Boolean`
|
221 | Default value: `true`
|
222 |
|
223 | Inject socket.io injection (if you want to use your own socket.io, set to `false`).
|
224 |
|
225 | WARNING: NOT IMPLEMENTED. Always injected.
|
226 |
|
227 | ###### serve.injectScriptTo
|
228 | Type: `String`
|
229 | Default value: `head`
|
230 |
|
231 | Two values are possible: `head` or `body`
|
232 |
|
233 | ###### serve.transpile
|
234 | Type: `Object`
|
235 |
|
236 | See `transpile` instructions.
|
237 |
|
238 | ###### serve.route
|
239 | Type: `Array|Object`
|
240 |
|
241 | See `route` instructions.
|
242 |
|
243 | ###### serve.proxy
|
244 | Type: `Array|Object`
|
245 |
|
246 | See proxy instructions.
|
247 |
|
248 | ###### serve.httpOptions
|
249 | type: `boolean|object`, default: `false`
|
250 |
|
251 | Custom HTTP/HTTP2 server options.
|
252 |
|
253 | ###### serve.http2
|
254 | Type: `boolean`, default: `false`
|
255 |
|
256 | Enables HTTP2 server! For convenience if `key` and `cert` are not passed in `httpOptions` sample self generated certificates are used.
|
257 |
|
258 |
|
259 | -----
|
260 |
|
261 | ##### watch.skip
|
262 | type: `boolean|string|array`, default: `false`
|
263 |
|
264 | Minimatch pattern(s) to skip files. Pattern(s) will be match with file path relative to base directory (for example if you want to skip `favicon.png` from all paths use `**/favicon.png` pattern)
|
265 |
|
266 | ##### watch.files
|
267 | Type: `Boolean|String|Array`
|
268 | Default value: `false`
|
269 |
|
270 | Minimatch pattern(s) to add files to watch (pattern will be match with file path relative to base directory)
|
271 |
|
272 | WARNING: NOT IMPLEMENTED.
|
273 |
|
274 | ##### watch.served
|
275 | Type: `Boolean`
|
276 | Default value: `true`
|
277 |
|
278 | Watch served files by HTTP server (with respect to `skip` option)
|
279 |
|
280 | ##### watch.dependencies
|
281 | Type: `Boolean`
|
282 | Default value: `true`
|
283 |
|
284 | Watch the files dependencies of transpiled sources (`skip` option is not considered)
|
285 |
|
286 | ##### watch.debounce
|
287 | Type: `Number`
|
288 | Default value: `100`
|
289 |
|
290 | Delay before change event is called (helps to prevent multiple change events for many successive file system events)
|
291 |
|
292 | ###### watch.poolInterval, `Number`, `200`
|
293 |
|
294 | Interval to pool file system (`fs.watch` parameter)
|
295 |
|
296 | ###### clients.sendData, `Boolean`, `false`
|
297 |
|
298 | Should or not changed files data be sent to client, if enabled file changes then are sent as array of `{file: ..., data: ...}`
|
299 |
|
300 |
|
301 | ### Routes
|
302 |
|
303 | `serve.route` can be array of object `{path: ..., target: ...}, or simpleer: `{'path/url': 'target/url/file'}`
|
304 | It is useful for development of sites that use Pushstate.
|
305 |
|
306 | ```javascript
|
307 | route: [
|
308 | // simple map - when client requests `/` it recievs /web/index.html
|
309 | {'/': '/web/index.html'},
|
310 | // when client requests `/mobiled` it recievs /web/index.html
|
311 | {path: '/mobile', target: '/mobile/index.html'},
|
312 |
|
313 | // wildcard (only single supported) - everyting after mypackage/ will be mapped
|
314 | /mypackage/*': '/bower_components/mypackage/*'},
|
315 |
|
316 | // parameters - /dist/foo will be mapped to /foo/index.dist.html
|
317 | {'/dist/:dest': '/:dest/index.dist.html'}
|
318 |
|
319 | // regexp path - when path is tring, regexp parameter should present even as empty string `regexp: ''`
|
320 | {path: '^/[\\w\\d-]+(/[\\w\\d-]+)?$', regexp: 'i', target: '/web/index.html'}
|
321 | ]
|
322 | ```
|
323 |
|
324 | ### Proxies
|
325 |
|
326 | `serve.proxy` can be array of object `{context: ..., target: ...}`
|
327 | Needed for exampley when you you want to proxy you requests to you API server.
|
328 |
|
329 | `context` defines which request to watchalive server should be proxied
|
330 |
|
331 | `target` is full host string value including protocol and port, it can be replaced with number of options including `port`, `protocol` and `host`
|
332 |
|
333 | `changeOrigin` - default true
|
334 |
|
335 | ```javascript
|
336 | proxy: [
|
337 | {context: '/api', port: 4000},
|
338 | {context: '/other-api', target: 'http://otherhost/api:9000'},
|
339 | ]
|
340 | ```
|
341 | ### Transpilers
|
342 |
|
343 |
|
344 | Currently only LESS/CSS transpiler is included out of the box. When you request *.less file it will be converted to css and sent as CSS data.
|
345 |
|
346 | You can easily add you custom transpilers like:
|
347 |
|
348 | ```javascript
|
349 | transpilers: {
|
350 | sass: {
|
351 | pattern: '*.scss',
|
352 | transpileFile: function(filePath, cache, callback){
|
353 | // read file at filePath
|
354 | // parse it
|
355 | // cache contains all files data currently watched
|
356 | // call callback(err, data, deps)
|
357 | // deps is optional array of file dependencies (full paths)
|
358 | },
|
359 | // or (NOT IMPLEMENTED yet)
|
360 | transpile: function(source, cache, callback){
|
361 |
|
362 | }
|
363 | }
|
364 | }
|
365 | ```
|
366 |
|
367 | ## License
|
368 |
|
369 | MIT |
\ | No newline at end of file |