Permalink
Browse files

Better multi-page support, less configuration required

  • Loading branch information...
sokra committed Jan 9, 2014
1 parent c10ac7c commit c7b0b345b06e11a7086e472bdf1c259b1c93908b
Showing with 82 additions and 48 deletions.
  1. +18 −7 README.md
  2. +12 −10 bin/webpack-dev-server.js
  3. +1 −1 client/live.html
  4. +5 −3 client/live.js
  5. +0 −1 client/main.html
  6. +9 −8 example/README.md
  7. +36 −17 lib/Server.js
  8. +1 −1 package.json
View
@@ -20,23 +20,34 @@ This project is heavily inspirated by [peerigon/nof5](/peerigon/nof5).
Like webpack, but you omit the output filename.
+Additional options:
+
+`--port <number>` Change the port (default: 8080)
+
+`--content-base` Serve HTML content from this directory or URL (default: current directory)
+
+`--noinfo` Less console output
+
+`--quiet` No console output
+
## Usage (javascript)
``` javascript
var Server = require("webpack-dev-server");
var options = {
- content: absoluteFilenameToContentHtmlPage,
- // Content page to display
- // it will default to a simple page
+ contentBase: __dirname + "/directory",
+ // A directory, file or URL
+ // It will be served as content
- contentUrl: "http://...",
- // if set it will load this URL as content page
- // it will default to undefined
+ hot: true,
+ // Enable special support for Hot Module Replacement
+ // Page is no longer updated, but a "webpackHotUpdate" message is send to the content
+ // ...
// webpack-dev-middleware options
// you can use all options of the middleware
};
-new Server(webpack(/*...*/), options).listen(port[, host]);
+new Server(webpack(/*... webpack options ...*/), options).listen(port[, host]);
```
## Contributing
View
@@ -15,9 +15,7 @@ var optimist = require("optimist")
.boolean("quiet").describe("quiet")
- .string("content-page").describe("content-page", "A html page to load")
-
- .string("content-url").describe("content-url", "A url to load")
+ .string("content-base").describe("content-base", "A directory or URL to serve HTML content from.")
.describe("port", "The port").default("port", 8080);
@@ -34,14 +32,16 @@ options.outputPath = wpOpt.output.path = "/";
options.filename = wpOpt.output.filename;
options.hot = wpOpt.hot;
-if(options.publicPath[0] != "/")
+if(options.publicPath[0] !== "/")
options.publicPath = "/" + options.publicPath;
-if(argv["content-page"])
- options.content = path.resolve(argv["content-page"]);
-
-if(argv["content-url"])
- options.contentUrl = argv["content-url"];
+if(argv["content-base"]) {
+ options.contentBase = argv["content-base"];
+ if(!/^(https?:)?\/\//.test(options.contentBase))
+ options.contentBase = path.resolve(options.contentBase);
+} else {
+ options.contentBase = process.cwd();
+}
if(argv["colors"])
options.stats = { colors: true };
@@ -54,5 +54,7 @@ if(argv["quiet"])
new Server(webpack(wpOpt), options).listen(argv.port, function(err) {
if(err) throw err;
- console.log("http://localhost:" + argv.port);
+ console.log("http://localhost:" + argv.port + "/");
+ console.log("webpack result is served from " + options.publicPath);
+ console.log("content is served from " + options.contentBase);
});
View
@@ -1 +1 @@
-<!DOCTYPE html><html><head><meta charset="utf-8"/><script type="text/javascript" charset="utf-8" src="/live.js"></script></head><body></body></html>
+<!DOCTYPE html><html><head><meta charset="utf-8"/><script type="text/javascript" charset="utf-8" src="/__webpack_dev_server__/live.bundle.js"></script></head><body></body></html>
View
@@ -10,14 +10,16 @@ $(function() {
var iframe = $("#iframe");
var hot = false;
+ var contentPage = (window.location.pathname) + "__webpack_dev_server" + window.location.search;
+
status.text("Connecting to socket.io server...");
$errors.hide(); iframe.hide();
body.css({background: "#066"});
io = io.connect();
io.on("hot", function() {
hot = true;
- iframe.attr("src", "/content.html");
+ iframe.attr("src", contentPage + window.location.hash);
});
io.on("invalid", function() {
@@ -77,9 +79,9 @@ $(function() {
try {
var old = iframe[0].contentWindow.location + "";
if(old.indexOf("about") == 0) old = null;
- iframe.attr("src", old || "/content.html");
+ iframe.attr("src", old || (contentPage + window.location.hash));
} catch(e) {
- iframe.attr("src", "/content.html");
+ iframe.attr("src", contentPage + window.location.hash);
}
}
}
View
@@ -1 +0,0 @@
-<!DOCTYPE html><html><head><script type="text/javascript" charset="utf-8" src="/bundle.js"></script></head><body></body></html>
View
@@ -1,31 +1,32 @@
# example
-Try one of these commands and open `http://localhost:8080`.
-
``` text
webpack-dev-server --colors
+http://localhost:8080/bundle
```
The app should display "It's working" with a dotted background.
+There is no file named `bundle` in this directory. The dev server creates a simple html that executes a javascript file: `bundle.js` (`<path>.js`)
+
``` text
-webpack-dev-server --colors --content-page index.html
+webpack-dev-server --colors
+http://localhost:8080/index.html
```
The app should display "It's working" with a green background.
+There is a file named `index.html` in this directory. This file is served as content
+
``` text
webpack-dev-server --colors --config alternative.config.js
+http://localhost:8080/bundle
+http://localhost:8080/index.html
```
The app should be minimized and the image is included with a Data Url.
-``` text
-webpack-dev-server --colors --content-page index.html --config alternative.config.js
-```
-
-Combined.
## Reloading
View
@@ -9,9 +9,7 @@ function Server(compiler, options) {
// Default options
if(!options) options = {};
- this.content = options.content && path.resolve(options.content) ||
- path.join(__dirname, "..", "client", "main.html");
- this.contentUrl = options.contentUrl;
+ this.contentBase = options.contentBase || process.cwd();
this.hot = options.hot;
// Listening for events
@@ -27,7 +25,7 @@ function Server(compiler, options) {
}.bind(this));
// Prepare live html page
- var livePage = new StreamCache();
+ var livePage = this.livePage = new StreamCache();
fs.createReadStream(path.join(__dirname, "..", "client", "live.html")).pipe(livePage);
// Prepare the live js file
@@ -42,16 +40,12 @@ function Server(compiler, options) {
app.use(this.middleware = webpackDevMiddleware(compiler, options));
}.bind(this));
- // route live requests
- app.get("/", function(req, res) {
- livePage.pipe(res);
- });
- app.get("/live.js", function(req, res) {
+ app.get("/__webpack_dev_server__/live.bundle.js", function(req, res) {
liveJs.pipe(res);
});
// route content request
- app.get("/content.html", this.serveContent.bind(this));
+ app.get("*", this.serveContent.bind(this));
}
// delegate listen call and init socket.io
@@ -69,13 +63,38 @@ Server.prototype.listen = function() {
}
Server.prototype.serveContent = function(req, res) {
- if(this.contentUrl) {
- res.writeHead(302, {
- 'Location': this.contentUrl
- });
- res.end();
- } else
- fs.createReadStream(this.content).pipe(res);
+ var _path = req.path;
+ if(/__webpack_dev_server$/.test(_path)) {
+ _path = _path.replace(/__webpack_dev_server$/, "");
+ if(_path === "/") _path = "";
+ var target = this.contentBase + _path;
+ if(/^(https?:)?\/\//.test(target)) {
+ res.writeHead(302, {
+ 'Location': target + (req._parsedUrl.search || "")
+ });
+ res.end();
+ } else {
+ fs.stat(target, function(err, stat) {
+ if(!err && stat.isFile()) {
+ fs.createReadStream(target).pipe(res);
+ } else if(!err && stat.isDirectory()) {
+ res.writeHead(302, {
+ 'Location': req.path.replace(/__webpack_dev_server$/, (/\/$/.test(_path) || !_path ? "index.html__webpack_dev_server" : "/__webpack_dev_server")) + (req._parsedUrl.search || "")
+ });
+ res.end();
+ } else {
+ // Serve a page that executes the javascript
+ res.write('<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body><script type="text/javascript" charset="utf-8" src="');
+ res.write(_path);
+ res.write('.js');
+ res.write(req._parsedUrl.search || "");
+ res.end('"></script></body></html>');
+ }
+ }.bind(this));
+ }
+ } else {
+ this.livePage.pipe(res);
+ }
}
// send stats to a socket or multiple sockets
View
@@ -1,6 +1,6 @@
{
"name": "webpack-dev-server",
- "version": "1.0.2",
+ "version": "1.1.0",
"author": "Tobias Koppers @sokra",
"description": "Serves a webpack app. Updates the browser on changes.",
"peerDependencies": {

0 comments on commit c7b0b34

Please sign in to comment.