- Notifications
You must be signed in to change notification settings - Fork145
A local webserver for developers
License
cortesi/devd
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Go to thereleases page, download the package for your OS, and copy the binary to somewhere on your PATH.
If you have a working Go installation, you can also say
go get github.com/cortesi/devd/cmd/devd
Serve the current directory, open it in the browser (-o), and livereload when files change (-l):
devd -ol.
Reverse proxy tohttp://localhost:8080, and livereload when any file in thesrc directory changes:
devd -w ./src http://localhost:8080
Modd is devd's sister project - a dev toolthat runs commands and manages daemons in response to filesystem changes. Devdcan be used with modd to rebuild a project and reload the browser whenfilesystem changes are detected.
Here's a quick example of a simplemodd.conf file to illustrate.
src/** { prep: render ./src ./rendered}rendered/*.css ./rendered/*.html { daemon: devd -m ./rendered}
The first block runs therender script whenever anything in thesrcdirectory changes. The second block starts a devd instance, and triggerslivereload with a signal whenever a .css or .html file in therendereddirectory changes.
See themodd project page for details.
Devd is a single statically compiled binary with no external dependencies, andis released for macOS, Linux and Windows. Don't want to install Node or Pythonin that light-weight Docker instance you're hacking in? Just copy over the devdbinary and be done with it.
This means no config file, no daemonization, and logs that are designed to beread in the terminal by a developer. Logs are colorized and log entries spanmultiple lines. Devd's logs are detailed, warn about corner cases that otherdaemons ignore, and can optionally include things like detailed timinginformation and full headers.
To make quickly firing up an instance as simple as possible, devd automaticallychooses an open port to run on (unless it's specified), and can open a browserwindow pointing to the daemon root for you (the-o flag in the exampleabove). It also has utility features like the-s flag, which auto-generatesa self-signed certificate for devd, stores it in ~/.devd.certs and enables TLSall in one step.
When livereload is enabled, devd injects a small script into HTML pages, justbefore the closinghead tag. The script listens for change notifications overa websocket connection, and reloads resources as needed. No browser addon isrequired, and livereload works even for reverse proxied apps. If only changesto CSS files are seen, devd will only reload external CSS resources, otherwisea full page reload is done. This serves the current directory with livereloadenabled:
devd -l .
You can also trigger livereload for files that are not being served, lettingyou reload reverse proxied applications when source files change. So, thiscommand watches thesrc directory tree, and reverse proxies to a locallyrunning application:
devd -w ./src http://localhost:8888
The-x flag excludes files from triggering livereload based on apatternspecification. The following commanddisables livereload for all files with the ".less" extension:
devd -x "**.less" -l .
When livereload is enabled (with the-L,-l or-w flags), devdresponds to a SIGHUP by issuing a livereload notice to all connected browsers.This allows external tools, like devd's sister projectmodd, to triggerlivereload. If livereload is not enabled, SIGHUP causes the daemon to exit.
The closinghead tag must be found within the first 30kb of the remote file,otherwise livereload is disabled for the file.
Modern apps tend to be collections of web servers, and devd caters for thiswith flexible reverse proxying. You can use devd to overlay a set of serviceson a single domain, add livereload to services that don't natively support it,add throttling and latency simulation to existing services, and so forth.
Here's a more complicated example showing how all this ties together - itoverlays two applications and a tree of static files. Livereload is enabled forthe static files (-l) and also triggered whenever source files for reverseproxied apps change (-w):
devd -l \-w ./src/ \/=http://localhost:8888 \/api/=http://localhost:8889 \/static/=./assets
Theroute specification syntax is compact but powerful enough to cater for most use cases.
Devd uses a dedicated domain -devd.io - to do simple virtual hosting. Thisdomain and all its subdomains resolve to 127.0.0.1, which we use to set upvirtual hosting without any changes to/etc/hosts or other localconfiguration. Route specifications that don't start with a leading/ aretaken to be subdomains ofdevd.io. So, the following command serves astatic site from devd.io, and reverse proxies a locally running app onapi.devd.io:
devd ./static api=http://localhost:8888
Want to know what it's like to use your fancy 5mb HTML5 app from a mobile phonein Botswana? Look up the bandwidth and latencyhere,and invoke devd like so (making sure to convert from kilobits per second tokilobytes per second and account for the location of your server):
devd -d 114 -u 51 -n 275 .
Devd tries to be reasonably accurate in simulating bandwidth and latency - ituses a token bucket implementation for throttling, properly handles concurrentrequests, and chunks traffic up so data flow is smooth.
The devd command takes one or more route specifications as arguments. Routeshave the basic formatroot=endpoint. Roots can be fixed, like"/favicon.ico", or subtrees, like "/images/" (note the trailing slash).Endpoints can be filesystem paths or URLs to upstream HTTP servers.
Here's a route that serves the directory./static under/assets on the server:
/assets/=./static
To use adevd.io subdomain (which will resolve to 127.0.0.1), just add itto the the front of the root specification. We recognize subdomains by the factthat they don't start with a leading/. So, this route serves the/static directory understatic.devd.io/assets:
static/assets=./static
Reverse proxy specifications are similar, but the endpoint specification is aURL. The following serves a local URL from the rootapp.devd.io/login:
app/login=http://localhost:8888
If theroot specification is omitted, it is assumed to be "/", i.e. apattern matching all paths. So, a simple directory specification serves thedirectory tree directly underdevd.io:
devd ./static
Similarly, a simple reverse proxy can be started like this:
devd http://localhost:8888
There is also a shortcut for reverse proxying to localhost:
devd :8888
The--notfound flag can be passed multiple times, and specifies a set ofroutes that are consulted when a requested file is not found by the static fileserver. The basic syntax isroot=path, whereroot has the samesemantics as route specification. As with routes, theroot= component isoptional, and if absent is taken to be equal to/. Thepath is alwaysrelative to the static directory being served. When it starts with a leadingslash (/), devd will only look for a replacement file in a single locationrelative to the root of the tree. Otherwise, it will search for a matching fileby joining the specifiedpath with all path components up to the root ofthe tree.
Let's illustrate this with an example. Say we have a/static directory asfollows:
./static├── bar│ └── index.html└── index.html
We can specify that devd should look for anindex.html anywhere on the pathto the root of the static tree as follows:
devd --notfound index.html /static
Now, the following happens:
- A request for/nonexistent.html returns the contents of/index.html
- A request for/bar/nonexistent.html returns the contents of/bar/index.html
- A request for/foo/bar/voing/index.html returns the contents of/index.html
We could instead specify an absolute path in the route, in which case thecontents of/index.html would be returned for all the examples above:
devd --notfound /index.html /static
Devd won't serve an over-ride page if the expected type of the incoming requestdoesn't match that of the override specification. We do this by looking at thefile extension and expected MIME types of the over-ride and request, defaultingtotext/html if the type couldn't be positively established. This preventsissues where, for instance, an HTML over-ride page might be served where imagesare expected.
The-x flag supports the following terms:
Term | Meaning |
---|---|
* | matches any sequence of non-path-separators |
** | matches any sequence of characters, including path separators |
? | matches any single non-path-separator character |
[class] | matches any single non-path-separator character against a class of characters |
{alt1,...} | matches a sequence of characters if one of the comma-separated alternatives matches |
Any character with a special meaning can be escaped with a backslash (\
). Character classes support the following:
Class | Meaning |
---|---|
[abc] | matches any single character within the set |
[a-z] | matches any single character in the range |
[^class] | matches any single character which doesnot match the class |
Devd does not validate upstream SSL certificates when reverse proxying. For ouruse case, development servers will usually be running locally, often withself-signed certificates for testing. You shouldn't use devd in cases whereupstream cert validation matters.
TheX-Forwarded-Host andX-Forwarded-Proto headers are set to the devdserver's address and protocol for reverse proxied traffic. You might need toenable support for this in your application for redirects and the like to workcorrectly.
The scripts used to build this package for distribution can be foundhere. External packages are vendored usingdep.
About
A local webserver for developers