{"id":13393998,"url":"https://github.com/cortesi/devd","last_synced_at":"2025-05-14T15:07:05.703Z","repository":{"id":38628696,"uuid":"43268361","full_name":"cortesi/devd","owner":"cortesi","description":" A local webserver for developers","archived":false,"fork":false,"pushed_at":"2024-05-01T11:07:08.000Z","size":11650,"stargazers_count":3454,"open_issues_count":26,"forks_count":145,"subscribers_count":74,"default_branch":"master","last_synced_at":"2025-04-11T06:15:52.097Z","etag":null,"topics":["front-end-development","livereload","reverse-proxies","webserver"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cortesi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-09-27T22:43:00.000Z","updated_at":"2025-04-06T05:42:33.000Z","dependencies_parsed_at":"2024-06-18T12:40:58.276Z","dependency_job_id":"127b82e3-17fb-467a-b14b-99fefd8277a9","html_url":"https://github.com/cortesi/devd","commit_stats":{"total_commits":169,"total_committers":19,"mean_commits":8.894736842105264,"dds":0.2781065088757396,"last_synced_commit":"c1a3bfba27d8e028de90fb24452374412a4cffb3"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortesi%2Fdevd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortesi%2Fdevd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortesi%2Fdevd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortesi%2Fdevd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cortesi","download_url":"https://codeload.github.com/cortesi/devd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254169392,"owners_count":22026211,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["front-end-development","livereload","reverse-proxies","webserver"],"created_at":"2024-07-30T17:01:05.110Z","updated_at":"2025-05-14T15:07:05.656Z","avatar_url":"https://github.com/cortesi.png","language":"Go","readme":"\n[![Travis Build Status](https://travis-ci.org/cortesi/devd.svg?branch=master)](https://travis-ci.org/cortesi/devd)\n\n\n\n# devd: a local webserver for developers\n\n![screenshot](docs/devd-terminal.png \"devd in action\")\n\n# Install\n\nGo 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.\n\nIf you have a working Go installation, you can also say\n\n    go get github.com/cortesi/devd/cmd/devd\n\n# Quick start\n\nServe the current directory, open it in the browser (**-o**), and livereload when files change (**-l**):\n\n```bash\ndevd -ol .\n```\n\nReverse proxy to http://localhost:8080, and livereload when any file in the **src** directory changes:\n\n```bash\ndevd -w ./src http://localhost:8080\n```\n\n\n# Using devd with modd\n\n[Modd](https://github.com/cortesi/modd) is devd's sister project - a dev tool\nthat runs commands and manages daemons in response to filesystem changes. Devd\ncan be used with modd to rebuild a project and reload the browser when\nfilesystem changes are detected.\n\nHere's a quick example of a simple *modd.conf* file to illustrate.\n\n```\nsrc/** {\n    prep: render ./src ./rendered\n}\n\nrendered/*.css ./rendered/*.html {\n    daemon: devd -m ./rendered\n}\n```\n\nThe first block runs the *render* script whenever anything in the *src*\ndirectory changes. The second block starts a devd instance, and triggers\nlivereload with a signal whenever a .css or .html file in the *rendered*\ndirectory changes.\n\nSee the [modd](https://github.com/cortesi/modd) project page for details.\n\n\n# Features\n\n### Cross-platform and self-contained\n\nDevd is a single statically compiled binary with no external dependencies, and\nis released for macOS, Linux and Windows. Don't want to install Node or Python\nin that light-weight Docker instance you're hacking in? Just copy over the devd\nbinary and be done with it.\n\n\n### Designed for the terminal\n\nThis means no config file, no daemonization, and logs that are designed to be\nread in the terminal by a developer. Logs are colorized and log entries span\nmultiple lines. Devd's logs are detailed, warn about corner cases that other\ndaemons ignore, and can optionally include things like detailed timing\ninformation and full headers.\n\n\n### Convenient\n\nTo make quickly firing up an instance as simple as possible, devd automatically\nchooses an open port to run on (unless it's specified), and can open a browser\nwindow pointing to the daemon root for you (the **-o** flag in the example\nabove). It also has utility features like the **-s** flag, which auto-generates\na self-signed certificate for devd, stores it in ~/.devd.certs and enables TLS\nall in one step.\n\n\n### Livereload\n\nWhen livereload is enabled, devd injects a small script into HTML pages, just\nbefore the closing *head* tag. The script listens for change notifications over\na websocket connection, and reloads resources as needed. No browser addon is\nrequired, and livereload works even for reverse proxied apps. If only changes\nto CSS files are seen, devd will only reload external CSS resources, otherwise\na full page reload is done. This serves the current directory with livereload\nenabled:\n\n\u003cpre class=\"terminal\"\u003edevd -l .\u003c/pre\u003e\n\nYou can also trigger livereload for files that are not being served, letting\nyou reload reverse proxied applications when source files change. So, this\ncommand watches the *src* directory tree, and reverse proxies to a locally\nrunning application:\n\n\u003cpre class=\"terminal\"\u003edevd -w ./src http://localhost:8888\u003c/pre\u003e\n\nThe **-x** flag excludes files from triggering livereload based on a [pattern\nspecification](#excluding-files-from-livereload). The following command\ndisables livereload for all files with the \".less\" extension:\n\n\u003cpre class=\"terminal\"\u003edevd -x \"**.less\" -l .\u003c/pre\u003e\n\nWhen livereload is enabled (with the **-L**, **-l** or **-w** flags), devd\nresponds to a SIGHUP by issuing a livereload notice to all connected browsers.\nThis allows external tools, like devd's sister project **modd**, to trigger\nlivereload. If livereload is not enabled, SIGHUP causes the daemon to exit.\n\nThe closing *head* tag must be found within the first 30kb of the remote file,\notherwise livereload is disabled for the file.\n\n\n### Reverse proxy + static file server + flexible routing\n\nModern apps tend to be collections of web servers, and devd caters for this\nwith flexible reverse proxying. You can use devd to overlay a set of services\non a single domain, add livereload to services that don't natively support it,\nadd throttling and latency simulation to existing services, and so forth.\n\nHere's a more complicated example showing how all this ties together - it\noverlays two applications and a tree of static files. Livereload is enabled for\nthe static files (**-l**) and also triggered whenever source files for reverse\nproxied apps change (**-w**):\n\n\u003cpre class=\"terminal\"\u003e\ndevd -l \\\n-w ./src/ \\\n/=http://localhost:8888 \\\n/api/=http://localhost:8889 \\\n/static/=./assets\n\u003c/pre\u003e\n\nThe [route specification syntax](#routes) is compact but powerful enough to cater for most use cases.\n\n### Light-weight virtual hosting\n\nDevd uses a dedicated domain - **devd.io** - to do simple virtual hosting. This\ndomain and all its subdomains resolve to 127.0.0.1, which we use to set up\nvirtual hosting without any changes to */etc/hosts* or other local\nconfiguration. Route specifications that don't start with a leading **/** are\ntaken to be subdomains of **devd.io**. So, the following command serves a\nstatic site from devd.io, and reverse proxies a locally running app on\napi.devd.io:\n\n\u003cpre class=\"terminal\"\u003e\ndevd ./static api=http://localhost:8888\n\u003c/pre\u003e\n\n\n### Latency and bandwidth simulation\n\nWant to know what it's like to use your fancy 5mb HTML5 app from a mobile phone\nin Botswana? Look up the bandwidth and latency\n[here](http://www.cisco.com/c/en/us/solutions/collateral/service-provider/global-cloud-index-gci/CloudIndex_Supplement.html),\nand invoke devd like so (making sure to convert from kilobits per second to\nkilobytes per second and account for the location of your server):\n\n\u003cpre class=\"terminal\"\u003edevd -d 114 -u 51 -n 275 .\u003c/pre\u003e\n\nDevd tries to be reasonably accurate in simulating bandwidth and latency - it\nuses a token bucket implementation for throttling, properly handles concurrent\nrequests, and chunks traffic up so data flow is smooth.\n\n\n## Routes\n\nThe devd command takes one or more route specifications as arguments. Routes\nhave the basic format **root=endpoint**. Roots can be fixed, like\n\"/favicon.ico\", or subtrees, like \"/images/\" (note the trailing slash).\nEndpoints can be filesystem paths or URLs to upstream HTTP servers.\n\nHere's a route that serves the directory *./static* under */assets* on the server:\n\n```\n/assets/=./static\n```\n\nTo use a **devd.io** subdomain (which will resolve to 127.0.0.1), just add it\nto the the front of the root specification. We recognize subdomains by the fact\nthat they don't start with a leading **/**. So, this route serves the\n**/static** directory under **static.devd.io/assets**:\n\n```\nstatic/assets=./static\n```\n\nReverse proxy specifications are similar, but the endpoint specification is a\nURL. The following serves a local URL from the root **app.devd.io/login**:\n\n```\napp/login=http://localhost:8888\n```\n\nIf the **root** specification is omitted, it is assumed to be \"/\", i.e. a\npattern matching all paths. So, a simple directory specification serves the\ndirectory tree directly under **devd.io**:\n\n```\ndevd ./static\n```\n\nSimilarly, a simple reverse proxy can be started like this:\n\n```\ndevd http://localhost:8888\n```\n\nThere is also a shortcut for reverse proxying to localhost:\n\n```\ndevd :8888\n\n```\n\n### Serving default content for files not found\n\nThe **--notfound** flag can be passed multiple times, and specifies a set of\nroutes that are consulted when a requested file is not found by the static file\nserver. The basic syntax is **root=path**, where **root** has the same\nsemantics as route specification. As with routes, the **root=** component is\noptional, and if absent is taken to be equal to **/**. The **path** is always\nrelative to the static directory being served. When it starts with a leading\nslash (**/**), devd will only look for a replacement file in a single location\nrelative to the root of the tree. Otherwise, it will search for a matching file\nby joining the specified **path** with all path components up to the root of\nthe tree.\n\nLet's illustrate this with an example. Say we have a */static* directory as\nfollows:\n\n```\n./static\n├── bar\n│   └── index.html\n└── index.html\n```\n\nWe can specify that devd should look for an *index.html* anywhere on the path\nto the root of the static tree as follows:\n\n```\ndevd --notfound index.html  /static\n```\n\nNow, the following happens:\n\n* A request for */nonexistent.html* returns the contents of */index.html*\n* A request for */bar/nonexistent.html* returns the contents of */bar/index.html*\n* A request for */foo/bar/voing/index.html* returns the contents of */index.html*\n\nWe could instead specify an absolute path in the route, in which case the\ncontents of */index.html* would be returned for all the examples above:\n\n```\ndevd --notfound /index.html  /static\n```\n\nDevd won't serve an over-ride page if the expected type of the incoming request\ndoesn't match that of the override specification. We do this by looking at the\nfile extension and expected MIME types of the over-ride and request, defaulting\nto *text/html* if the type couldn't be positively established. This prevents\nissues where, for instance, an HTML over-ride page might be served where images\nare expected.\n\n\n## Excluding files from livereload\n\nThe **-x** flag supports the following terms:\n\nTerm          | Meaning\n------------- | -------\n`*`           | matches any sequence of non-path-separators\n`**`          | matches any sequence of characters, including path separators\n`?`           | matches any single non-path-separator character\n`[class]`     | matches any single non-path-separator character against a class of characters\n`{alt1,...}`  | matches a sequence of characters if one of the comma-separated alternatives matches\n\nAny character with a special meaning can be escaped with a backslash (`\\`). Character classes support the following:\n\nClass      | Meaning\n---------- | -------\n`[abc]`    | matches any single character within the set\n`[a-z]`    | matches any single character in the range\n`[^class]` | matches any single character which does *not* match the class\n\n\n## About reverse proxying\n\nDevd does not validate upstream SSL certificates when reverse proxying. For our\nuse case, development servers will usually be running locally, often with\nself-signed certificates for testing. You shouldn't use devd in cases where\nupstream cert validation matters.\n\nThe *X-Forwarded-Host* and *X-Forwarded-Proto* headers are set to the devd\nserver's address and protocol for reverse proxied traffic. You might need to\nenable support for this in your application for redirects and the like to work\ncorrectly.\n\n\n# Development\n\nThe scripts used to build this package for distribution can be found\n[here](https://github.com/cortesi/godist). External packages are vendored using\n[dep](https://github.com/golang/dep).\n","funding_links":[],"categories":["Go","Server Applications","Tools","\u003cspan id=\"服务器应用程序-server-applications\"\u003e服务器应用程序 Server Applications\u003c/span\u003e","服务器应用程序","服务端应用","服務器程序","Relational Databases","服务器程序"],"sub_categories":["HTTP Clients","Go","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","HTTP客户端","Contents","Advanced Console UIs","查询语","高級控制台界面","交流","高级控制台界面"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcortesi%2Fdevd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcortesi%2Fdevd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcortesi%2Fdevd/lists"}