github.com/cortesi/devd@v0.0.0-20200427000907-c1a3bfba27d8/README.md (about)

     1  
     2  [![Travis Build Status](https://travis-ci.org/cortesi/devd.svg?branch=master)](https://travis-ci.org/cortesi/devd)
     3  
     4  
     5  
     6  # devd: a local webserver for developers
     7  
     8  ![screenshot](docs/devd-terminal.png "devd in action")
     9  
    10  # Install
    11  
    12  Go to the [releases page](https://github.com/cortesi/devd/releases/latest), download the package for your OS, and copy the binary to somewhere on your PATH.
    13  
    14  If you have a working Go installation, you can also say
    15  
    16      go get github.com/cortesi/devd/cmd/devd
    17  
    18  # Quick start
    19  
    20  Serve the current directory, open it in the browser (**-o**), and livereload when files change (**-l**):
    21  
    22  ```bash
    23  devd -ol .
    24  ```
    25  
    26  Reverse proxy to http://localhost:8080, and livereload when any file in the **src** directory changes:
    27  
    28  ```bash
    29  devd -w ./src http://localhost:8080
    30  ```
    31  
    32  
    33  # Using devd with modd
    34  
    35  [Modd](https://github.com/cortesi/modd) is devd's sister project - a dev tool
    36  that runs commands and manages daemons in response to filesystem changes. Devd
    37  can be used with modd to rebuild a project and reload the browser when
    38  filesystem changes are detected.
    39  
    40  Here's a quick example of a simple *modd.conf* file to illustrate.
    41  
    42  ```
    43  src/** {
    44      prep: render ./src ./rendered
    45  }
    46  
    47  rendered/*.css ./rendered/*.html {
    48      daemon: devd -m ./rendered
    49  }
    50  ```
    51  
    52  The first block runs the *render* script whenever anything in the *src*
    53  directory changes. The second block starts a devd instance, and triggers
    54  livereload with a signal whenever a .css or .html file in the *rendered*
    55  directory changes.
    56  
    57  See the [modd](https://github.com/cortesi/modd) project page for details.
    58  
    59  
    60  # Features
    61  
    62  ### Cross-platform and self-contained
    63  
    64  Devd is a single statically compiled binary with no external dependencies, and
    65  is released for macOS, Linux and Windows. Don't want to install Node or Python
    66  in that light-weight Docker instance you're hacking in? Just copy over the devd
    67  binary and be done with it.
    68  
    69  
    70  ### Designed for the terminal
    71  
    72  This means no config file, no daemonization, and logs that are designed to be
    73  read in the terminal by a developer. Logs are colorized and log entries span
    74  multiple lines. Devd's logs are detailed, warn about corner cases that other
    75  daemons ignore, and can optionally include things like detailed timing
    76  information and full headers.
    77  
    78  
    79  ### Convenient
    80  
    81  To make quickly firing up an instance as simple as possible, devd automatically
    82  chooses an open port to run on (unless it's specified), and can open a browser
    83  window pointing to the daemon root for you (the **-o** flag in the example
    84  above). It also has utility features like the **-s** flag, which auto-generates
    85  a self-signed certificate for devd, stores it in ~/.devd.certs and enables TLS
    86  all in one step.
    87  
    88  
    89  ### Livereload
    90  
    91  When livereload is enabled, devd injects a small script into HTML pages, just
    92  before the closing *head* tag. The script listens for change notifications over
    93  a websocket connection, and reloads resources as needed. No browser addon is
    94  required, and livereload works even for reverse proxied apps. If only changes
    95  to CSS files are seen, devd will only reload external CSS resources, otherwise
    96  a full page reload is done. This serves the current directory with livereload
    97  enabled:
    98  
    99  <pre class="terminal">devd -l .</pre>
   100  
   101  You can also trigger livereload for files that are not being served, letting
   102  you reload reverse proxied applications when source files change. So, this
   103  command watches the *src* directory tree, and reverse proxies to a locally
   104  running application:
   105  
   106  <pre class="terminal">devd -w ./src http://localhost:8888</pre>
   107  
   108  The **-x** flag excludes files from triggering livereload based on a [pattern
   109  specification](#excluding-files-from-livereload). The following command
   110  disables livereload for all files with the ".less" extension:
   111  
   112  <pre class="terminal">devd -x "**.less" -l .</pre>
   113  
   114  When livereload is enabled (with the **-L**, **-l** or **-w** flags), devd
   115  responds to a SIGHUP by issuing a livereload notice to all connected browsers.
   116  This allows external tools, like devd's sister project **modd**, to trigger
   117  livereload. If livereload is not enabled, SIGHUP causes the daemon to exit.
   118  
   119  The closing *head* tag must be found within the first 30kb of the remote file,
   120  otherwise livereload is disabled for the file.
   121  
   122  
   123  ### Reverse proxy + static file server + flexible routing
   124  
   125  Modern apps tend to be collections of web servers, and devd caters for this
   126  with flexible reverse proxying. You can use devd to overlay a set of services
   127  on a single domain, add livereload to services that don't natively support it,
   128  add throttling and latency simulation to existing services, and so forth.
   129  
   130  Here's a more complicated example showing how all this ties together - it
   131  overlays two applications and a tree of static files. Livereload is enabled for
   132  the static files (**-l**) and also triggered whenever source files for reverse
   133  proxied apps change (**-w**):
   134  
   135  <pre class="terminal">
   136  devd -l \
   137  -w ./src/ \
   138  /=http://localhost:8888 \
   139  /api/=http://localhost:8889 \
   140  /static/=./assets
   141  </pre>
   142  
   143  The [route specification syntax](#routes) is compact but powerful enough to cater for most use cases.
   144  
   145  ### Light-weight virtual hosting
   146  
   147  Devd uses a dedicated domain - **devd.io** - to do simple virtual hosting. This
   148  domain and all its subdomains resolve to 127.0.0.1, which we use to set up
   149  virtual hosting without any changes to */etc/hosts* or other local
   150  configuration. Route specifications that don't start with a leading **/** are
   151  taken to be subdomains of **devd.io**. So, the following command serves a
   152  static site from devd.io, and reverse proxies a locally running app on
   153  api.devd.io:
   154  
   155  <pre class="terminal">
   156  devd ./static api=http://localhost:8888
   157  </pre>
   158  
   159  
   160  ### Latency and bandwidth simulation
   161  
   162  Want to know what it's like to use your fancy 5mb HTML5 app from a mobile phone
   163  in Botswana? Look up the bandwidth and latency
   164  [here](http://www.cisco.com/c/en/us/solutions/collateral/service-provider/global-cloud-index-gci/CloudIndex_Supplement.html),
   165  and invoke devd like so (making sure to convert from kilobits per second to
   166  kilobytes per second and account for the location of your server):
   167  
   168  <pre class="terminal">devd -d 114 -u 51 -n 275 .</pre>
   169  
   170  Devd tries to be reasonably accurate in simulating bandwidth and latency - it
   171  uses a token bucket implementation for throttling, properly handles concurrent
   172  requests, and chunks traffic up so data flow is smooth.
   173  
   174  
   175  ## Routes
   176  
   177  The devd command takes one or more route specifications as arguments. Routes
   178  have the basic format **root=endpoint**. Roots can be fixed, like
   179  "/favicon.ico", or subtrees, like "/images/" (note the trailing slash).
   180  Endpoints can be filesystem paths or URLs to upstream HTTP servers.
   181  
   182  Here's a route that serves the directory *./static* under */assets* on the server:
   183  
   184  ```
   185  /assets/=./static
   186  ```
   187  
   188  To use a **devd.io** subdomain (which will resolve to 127.0.0.1), just add it
   189  to the the front of the root specification. We recognize subdomains by the fact
   190  that they don't start with a leading **/**. So, this route serves the
   191  **/static** directory under **static.devd.io/assets**:
   192  
   193  ```
   194  static/assets=./static
   195  ```
   196  
   197  Reverse proxy specifications are similar, but the endpoint specification is a
   198  URL. The following serves a local URL from the root **app.devd.io/login**:
   199  
   200  ```
   201  app/login=http://localhost:8888
   202  ```
   203  
   204  If the **root** specification is omitted, it is assumed to be "/", i.e. a
   205  pattern matching all paths. So, a simple directory specification serves the
   206  directory tree directly under **devd.io**:
   207  
   208  ```
   209  devd ./static
   210  ```
   211  
   212  Similarly, a simple reverse proxy can be started like this:
   213  
   214  ```
   215  devd http://localhost:8888
   216  ```
   217  
   218  There is also a shortcut for reverse proxying to localhost:
   219  
   220  ```
   221  devd :8888
   222  
   223  ```
   224  
   225  ### Serving default content for files not found
   226  
   227  The **--notfound** flag can be passed multiple times, and specifies a set of
   228  routes that are consulted when a requested file is not found by the static file
   229  server. The basic syntax is **root=path**, where **root** has the same
   230  semantics as route specification. As with routes, the **root=** component is
   231  optional, and if absent is taken to be equal to **/**. The **path** is always
   232  relative to the static directory being served. When it starts with a leading
   233  slash (**/**), devd will only look for a replacement file in a single location
   234  relative to the root of the tree. Otherwise, it will search for a matching file
   235  by joining the specified **path** with all path components up to the root of
   236  the tree.
   237  
   238  Let's illustrate this with an example. Say we have a */static* directory as
   239  follows:
   240  
   241  ```
   242  ./static
   243  ├── bar
   244  │   └── index.html
   245  └── index.html
   246  ```
   247  
   248  We can specify that devd should look for an *index.html* anywhere on the path
   249  to the root of the static tree as follows:
   250  
   251  ```
   252  devd --notfound index.html  /static
   253  ```
   254  
   255  Now, the following happens:
   256  
   257  * A request for */nonexistent.html* returns the contents of */index.html*
   258  * A request for */bar/nonexistent.html* returns the contents of */bar/index.html*
   259  * A request for */foo/bar/voing/index.html* returns the contents of */index.html*
   260  
   261  We could instead specify an absolute path in the route, in which case the
   262  contents of */index.html* would be returned for all the examples above:
   263  
   264  ```
   265  devd --notfound /index.html  /static
   266  ```
   267  
   268  Devd won't serve an over-ride page if the expected type of the incoming request
   269  doesn't match that of the override specification. We do this by looking at the
   270  file extension and expected MIME types of the over-ride and request, defaulting
   271  to *text/html* if the type couldn't be positively established. This prevents
   272  issues where, for instance, an HTML over-ride page might be served where images
   273  are expected.
   274  
   275  
   276  ## Excluding files from livereload
   277  
   278  The **-x** flag supports the following terms:
   279  
   280  Term          | Meaning
   281  ------------- | -------
   282  `*`           | matches any sequence of non-path-separators
   283  `**`          | matches any sequence of characters, including path separators
   284  `?`           | matches any single non-path-separator character
   285  `[class]`     | matches any single non-path-separator character against a class of characters
   286  `{alt1,...}`  | matches a sequence of characters if one of the comma-separated alternatives matches
   287  
   288  Any character with a special meaning can be escaped with a backslash (`\`). Character classes support the following:
   289  
   290  Class      | Meaning
   291  ---------- | -------
   292  `[abc]`    | matches any single character within the set
   293  `[a-z]`    | matches any single character in the range
   294  `[^class]` | matches any single character which does *not* match the class
   295  
   296  
   297  ## About reverse proxying
   298  
   299  Devd does not validate upstream SSL certificates when reverse proxying. For our
   300  use case, development servers will usually be running locally, often with
   301  self-signed certificates for testing. You shouldn't use devd in cases where
   302  upstream cert validation matters.
   303  
   304  The *X-Forwarded-Host* and *X-Forwarded-Proto* headers are set to the devd
   305  server's address and protocol for reverse proxied traffic. You might need to
   306  enable support for this in your application for redirects and the like to work
   307  correctly.
   308  
   309  
   310  # Development
   311  
   312  The scripts used to build this package for distribution can be found
   313  [here](https://github.com/cortesi/godist). External packages are vendored using
   314  [dep](https://github.com/golang/dep).