diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index 4c59e4be53..b1b7c45db9 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -45,6 +45,8 @@ var optimist = require("optimist") .string("content-base").describe("content-base", "A directory or URL to serve HTML content from.") +.boolean("watch-content-base").describe("watch-content-base", "Enable live-reloading of the content-base.") + .string("content-base-target").describe("content-base-target", "Proxy requests to this target.") .boolean("history-api-fallback").describe("history-api-fallback", "Fallback to /index.html for Single Page Applications.") @@ -125,6 +127,9 @@ if(argv["content-base"]) { options.contentBase = process.cwd(); } +if(argv["watch-content-base"]) + options.watchContentBase = true + if(!options.stats) { options.stats = { cached: false, diff --git a/build_pkg.sh b/build_pkg.sh new file mode 100755 index 0000000000..8a3d3d802d --- /dev/null +++ b/build_pkg.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# This is the script run by buildbot +# (not by any of eventshopper or eventshopper-pull-requests instances) +# It produces an outdeploy-able package, and does not runs tests. + +# START Common expectations for all build scripts. +PACKAGE=$1 +BRANCH=$2 +TAG=$3 +RELEASETYPE=$4 + +if [ -z "$PACKAGE" ] || [ -z "$BRANCH" ] || [ -z "$TAG" ] || [ -z "$RELEASETYPE" ]; then + echo "Usage: $0 package branch tag releasetype" + echo "where:" + echo " - 'package' is the name of the GitHub project. Ex: 'eventshopper'" + echo " - 'branch' is the branch of the GitHub project. Ex: 'master'" + echo " - 'tag' is the release tag. Ex: '1.2.3'" + echo " - 'releasetype' is either 'release', 'prerelease', or 'push'" + exit 1 +fi + +echo "Parameters: $PACKAGE $BRANCH $TAG $RELEASETYPE" +echo "Packaging $PACKAGE-$TAG for Outlaunch" + +set -x + +# We use node version manager to use the right version of node depending on +# the version specified in .nvmrc +NVM_DIR="/home/buildbot/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm +nvm install +NVM_RESULTS=$? +set -e + +rm -rf ./node_modules +RM_RESULTS=$? + +# gyp requires Python >= 2.4, and the default on our build machine is only 2.4 +npm cache clean +npm install --python="/opt/outbox/python2.7/bin/python" +INSTALL_RESULTS=$? + +# build the project files +npm run prepublish +BUILD_RESULTS=$? + +# move project files as specified by project.json to prepare for compression +mkdir -p build +cp lib ssl client bin build + +# Matching structure of regular `setup.py`ed Python packages, having a root +# folder level describing package-version. +tar cvfz "$PACKAGE-$TAG.tar.gz" build +COMPRESS_RESULTS=$? + +# cleanup +rm -rf build + +# put package in dist +mkdir -p dist +mv "$PACKAGE-$TAG.tar.gz" dist + +exit $((NVM_RESULTS || INSTALL_RESULTS || RM_RESULTS || BUILD_RESULTS || COMPRESS_RESULTS)) diff --git a/buildbot.conf b/buildbot.conf new file mode 100644 index 0000000000..93459d4a07 --- /dev/null +++ b/buildbot.conf @@ -0,0 +1,2 @@ +[build] +build_script_path=./build_pkg.sh diff --git a/client/index.js b/client/index.js index e694d3dba5..0a6bd0a9ef 100644 --- a/client/index.js +++ b/client/index.js @@ -62,6 +62,10 @@ var onSocketMsg = { if(initial) return initial = false; reloadApp(); }, + "content-changed": function() { + log("info", "[WDS] Content base changed. Reloading...") + self.location.reload(); + }, warnings: function(warnings) { log("info", "[WDS] Warnings while compiling."); for(var i = 0; i < warnings.length; i++) diff --git a/example/README.md b/example/README.md index 6989a7a5b5..3ee10ecd5d 100644 --- a/example/README.md +++ b/example/README.md @@ -64,3 +64,14 @@ http://localhost:8080/some/url/from/spa ``` The contents of /index.html is served. + +## Watching `devServer.contentBase` + +``` text +webpack-dev-server --inline --content-base assets --watch-content-base +http://localhost:8080/ +``` + +Try to update `assets/index.html`. + +The browser should reflect your changes. diff --git a/example/assets/index.html b/example/assets/index.html new file mode 100644 index 0000000000..a1c356cf65 --- /dev/null +++ b/example/assets/index.html @@ -0,0 +1,11 @@ + + + + + + +

Watch content base

+
+ + + diff --git a/lib/Server.js b/lib/Server.js index dde84fadae..f1de04f841 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -1,4 +1,5 @@ var fs = require("fs"); +var chokidar = require("chokidar"); var path = require("path"); var webpackDevMiddleware = require("webpack-dev-middleware"); var express = require("express"); @@ -23,6 +24,7 @@ function Server(compiler, options) { this.headers = options.headers; this.clientLogLevel = options.clientLogLevel; this.sockets = []; + this.contentBaseWatchers = []; // Listening for events var invalidPlugin = function() { @@ -247,6 +249,19 @@ function Server(compiler, options) { } }.bind(this), + watchContentBase: function() { + var contentBase = options.contentBase || process.cwd(); + if(/^(https?:)?\/\//.test(contentBase) || typeof contentBase === "number") { + throw new Error("Watching remote files is not supported."); + } else if(Array.isArray(contentBase)) { + contentBase.forEach(function(item) { + this._watch(item); + }.bind(this)); + } else { + this._watch(contentBase); + } + }.bind(this), + middleware: function() { // include our middleware to ensure it is able to handle '/index.html' request after redirect app.use(this.middleware); @@ -274,6 +289,8 @@ function Server(compiler, options) { defaultFeatures.push("magicHtml"); if(options.contentBase !== false) defaultFeatures.push("contentBase"); + if(options.watchContentBase) + defaultFeatures.push("watchContentBase"); // compress is placed last and uses unshift so that it will be the first middleware used if(options.compress) defaultFeatures.unshift("compress"); @@ -362,6 +379,10 @@ Server.prototype.close = function() { this.sockets = []; this.middleware.close(); this.listeningApp.close(); + this.contentBaseWatchers.forEach(function(watcher) { + watcher.close(); + }); + this.contentBaseWatchers = []; } Server.prototype.sockWrite = function(sockets, type, data) { @@ -409,6 +430,14 @@ Server.prototype._sendStats = function(sockets, stats, force) { this.sockWrite(sockets, "ok"); } +Server.prototype._watch = function(path) { + var watcher = chokidar.watch(path).on("change", function() { + this.sockWrite(this.sockets, "content-changed"); + }.bind(this)) + + this.contentBaseWatchers.push(watcher); +} + Server.prototype.invalidate = function() { if(this.middleware) this.middleware.invalidate(); } diff --git a/package.json b/package.json index e1fcb57806..b2b4197e2c 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "webpack": ">=1.3.0 <3" }, "dependencies": { + "chokidar": "^1.6.0", "compression": "^1.5.2", "connect-history-api-fallback": "^1.3.0", "express": "^4.13.3",