├── .gitignore
├── test
├── data
│ ├── entry.js
│ └── index.html
└── suites
│ └── serverTest.js
├── client
├── page.jade
├── live.html
├── package.json
├── webpack.config.js
├── style.css
├── index.js
├── live.js
└── npm-debug.log
├── gulpfile.js
├── package.json
├── README.md
├── src
├── pluginutil.js
└── plugin.js
└── npm-debug.log
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/test/data/entry.js:
--------------------------------------------------------------------------------
1 | console.log("test");
--------------------------------------------------------------------------------
/client/page.jade:
--------------------------------------------------------------------------------
1 | .header
2 | span#okness
3 | = " "
4 | span#status
5 | pre#errors
6 | #warnings
7 | iframe#iframe(src="javascript:;")
--------------------------------------------------------------------------------
/test/data/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/client/live.html:
--------------------------------------------------------------------------------
1 | webpack dev server
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webpackdevserverclient",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "robert",
10 | "license": "ISC",
11 | "dependencies": {
12 | "jquery": "^2.1.3",
13 | "socket.io-client": "^1.3.3"
14 | },
15 | "devDependencies": {
16 | "css-loader": "^0.9.1",
17 | "jade": "^1.9.1",
18 | "jade-loader": "^0.7.1",
19 | "style-loader": "^0.8.3"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require("gulp");
2 | var gutil = require("gulp-util");
3 | var mocha = require("gulp-mocha");
4 | var connect = require('gulp-connect');
5 |
6 | // The development server (the recommended option for development)
7 | gulp.task("default", ["test"]);
8 |
9 | // perform macha tests
10 | gulp.task('test', function () {
11 | return gulp.src('./test/suites/**/*.js', {
12 | read: false
13 | })
14 | .pipe(mocha({
15 | reporter: 'nyan'
16 | }));
17 | });
18 |
19 | gulp.task('mocha-watch', function () {
20 | gulp.watch(['./**/*.js','!./testWebPackApp/**/*'], ['test']);
21 | });
--------------------------------------------------------------------------------
/client/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require("path");
2 | var webpack = require("webpack");
3 |
4 | module.exports = {
5 | entry: {
6 | index: "./index",
7 | live: "./live",
8 | },
9 | output: {
10 | path: path.join(__dirname, ""),
11 | filename: "[name].bundle.js",
12 | chunkFilename: "[chunkhash].[id].js"
13 | },
14 | module: {
15 | loaders: [{
16 | test: /\.css/,
17 | loader: "style-loader!css-loader"
18 | },
19 | {
20 | test: /\.jade$/,
21 | loader: "jade?self"
22 | }
23 | ]
24 | }
25 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hapi-webpack-dev-plugin",
3 | "version": "0.1.1",
4 | "description": "a plugin to integrate the web-pack-dev-server as a hapi plugin into a hapi server instead of using express",
5 | "main": "src/plugin.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "hapi",
11 | "webpack",
12 | "devserver",
13 | "server",
14 | "dev"
15 | ],
16 | "author": "atroo (info@atroo.de)",
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/atroo/hapi-webpack-dev-server-plugin"
20 | },
21 | "license": "ISC",
22 | "devDependencies": {
23 | "chai": "^1.9.2",
24 | "chai-spies": "^0.5.1",
25 | "gulp": "^3.8.10",
26 | "gulp-connect": "^2.2.0",
27 | "gulp-mocha": "^1.1.1",
28 | "gulp-util": "^3.0.1",
29 | "hapi": "8.x.x",
30 | "webpack": "^1.4.12",
31 | "wreck": "^5.0.1"
32 | },
33 | "dependencies": {
34 | "boom": "^2.6.0",
35 | "jquery": "^2.1.1",
36 | "memory-fs": "^0.1.0",
37 | "mime": "^1.2.11",
38 | "socket.io": "^1.3.3"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/client/style.css:
--------------------------------------------------------------------------------
1 | *,
2 | *:before,
3 | *:after {
4 | -webkit-box-sizing: border-box;
5 | -moz-box-sizing: border-box;
6 | box-sizing: border-box;
7 | }
8 |
9 | body,
10 | html {
11 | margin: 0;
12 | padding: 0;
13 | height: 100%;
14 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
15 | }
16 |
17 | .header {
18 | width: 100%;
19 | height: 30px;
20 | padding: 0 10px;
21 | border-left: 10px solid #a3be8c;
22 | font-size: 12px;
23 | line-height: 30px;
24 | color: #eff1f5;
25 | background: #343d46;
26 | overflow: hidden;
27 | }
28 |
29 | #iframe {
30 | position: absolute;
31 | top: 30px;
32 | right: 0;
33 | bottom: 0;
34 | left: 0;
35 | width: 100%;
36 | height: -webkit-calc(100% - 30px);
37 | height: -moz-calc(100% - 30px);
38 | height: -ms-calc(100% - 30px);
39 | height: -o-calc(100% - 30px);
40 | height: calc(100% - 30px);
41 | border: 0;
42 | }
43 |
44 | #errors {
45 | width: 100%;
46 | margin: 0;
47 | padding: 10px;
48 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
49 | font-size: 14px;
50 | line-height: 1.4;
51 | color: #eff1f5;
52 | background: #bf616a;
53 | }
54 |
55 | #okness {
56 | font-weight: bold;
57 | }
58 |
--------------------------------------------------------------------------------
/client/index.js:
--------------------------------------------------------------------------------
1 | var io = require("socket.io-client");
2 | var scriptElements = document.getElementsByTagName("script");
3 | io = io.connect(typeof __resourceQuery === "string" && __resourceQuery ?
4 | __resourceQuery.substr(1) :
5 | scriptElements[scriptElements.length-1].getAttribute("src").replace(/\/[^\/]+$/, "")
6 | );
7 |
8 | var hot = false;
9 | var initial = true;
10 | var currentHash = "";
11 |
12 | io.on("hot", function() {
13 | hot = true;
14 | console.log("[WDS] Hot Module Replacement enabled.");
15 | });
16 |
17 | io.on("invalid", function() {
18 | console.log("[WDS] App updated. Recompiling...");
19 | });
20 |
21 | io.on("hash", function(hash) {
22 | currentHash = hash;
23 | });
24 |
25 | io.on("ok", function() {
26 | if(initial) return initial = false;
27 | reloadApp();
28 | });
29 |
30 | io.on("warnings", function(warnings) {
31 | console.log("[WDS] Warnings while compiling.");
32 | for(var i = 0; i < warnings.length; i++)
33 | console.warn(warnings[i]);
34 | if(initial) return initial = false;
35 | reloadApp();
36 | });
37 |
38 | io.on("errors", function(errors) {
39 | console.log("[WDS] Errors while compiling.");
40 | for(var i = 0; i < errors.length; i++)
41 | console.error(errors[i]);
42 | if(initial) return initial = false;
43 | reloadApp();
44 | });
45 |
46 | io.on("proxy-error", function(errors) {
47 | console.log("[WDS] Proxy error.");
48 | for(var i = 0; i < errors.length; i++)
49 | console.error(errors[i]);
50 | if(initial) return initial = false;
51 | reloadApp();
52 | });
53 |
54 | io.on("disconnect", function() {
55 | console.error("[WDS] Disconnected!");
56 | });
57 |
58 | function reloadApp() {
59 | if(hot) {
60 | console.log("[WDS] App hot update...");
61 | window.postMessage("webpackHotUpdate" + currentHash, "*");
62 | } else {
63 | console.log("[WDS] App updated. Reloading...");
64 | window.location.reload();
65 | }
66 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | hapi-webpack-dev-server-plugin
2 | ==============================
3 |
4 | This is a plugin for hapijs providing the necessary routes to function as a webpack-dev-server for the [awesome webpack project](http://webpack.github.io/) directly in hapijs. The actual [Webpack-dev-server](https://github.com/webpack/webpack-dev-server) is implemented with express.js and since we are heavily using the fabulous [hapijs](http://hapijs.com/) as our main backend framework we found it very useful to have everything right there. This avoids tweaking SOP related things just for dev purposes.
5 |
6 | Just like the original webpack-dev-server we also want to give out a quick warning:
7 |
8 | *DON'T USE THIS PLUGIN IN PRODUCTION!*
9 |
10 | Requirements: hapijs ^8.x.x
11 |
12 | State: In Progress (meaning not hot code replacement at the moment, but auto relaoding works just fine)
13 |
14 | Basic Usage
15 | =====
16 |
17 | we tend to structure our apps like
18 | ```javascript
19 | - server_plugin
20 | index.js
21 | - webpack_frontend
22 | - src
23 | main.js
24 | webpack.config.js
25 | server.js
26 | ```
27 |
28 | with that structure in mind you'd setup the dev-server-plugin in the server.js as follows
29 |
30 | ```javascript
31 | var Webpack = require('webpack');
32 | var Hapi = require('hapi');
33 |
34 | //basic webpack config, see webpack api docs for all options
35 | var webpackConf = require('./webpack_frontend/webpack.config.js');
36 | webpackConf.entry = {
37 | app: './webpack_frontend/src/main.js' //this is needed to have the correct relative paths for the webpack compiler which now runs from the base dir rather than from webpack_frontend
38 | };
39 | webpackConf.devtool = 'source-map';
40 |
41 | //create the webpack compiler
42 | compiler = Webpack(webPackConfig);
43 |
44 | //create hapi server
45 | server = new Hapi.Server();
46 | server.connection({
47 | port: port,
48 | host: address
49 | });
50 |
51 | //start server and register dev server as plugin
52 | server.start(function () {
53 | server.register({
54 | register: require('hapi-webpack-dev-plugin'),
55 | options: {
56 | compiler: compiler,
57 | //no loginfo
58 | quiet: true,
59 | //where is the index.html located
60 | devIndex: ".", //not needed if devView is configured
61 | devView: { //allows to configure a view with whatever engine hapi has been configured to induce e.e. session information on startup
62 | name: 'main.html',
63 | data: function (request) {
64 | var tplData = {
65 | "entrypoint": "dist/app.js"
66 | };
67 | return tplData;
68 | }
69 | }
70 | /*
71 | ,watchDelay: 200
72 | ,noInfo: false
73 | ,headers: {
74 | x-dynamic-content: true
75 | }
76 | */
77 | }
78 | }, function (err) {
79 | console.log(err);
80 | });
81 | });
82 |
83 | ```
84 |
85 | Config Options
86 | ==============
87 |
88 |
89 | - compiler - the webpack compiler
90 | - devIndex - path to the dev index.html file. Is ignored if devView is configured. defaults to index.html in the cwd
91 | - devView
92 |
93 |
94 | ```javascript
95 | {
96 | name: "the name of the view" // mandatory, elsewise the devIndex will be used
97 | data: "tplData" // an object, a function which gets passed in the request, or empty - data is supposed to determine tplData for the view
98 | }
99 | ```
100 |
101 |
102 | -
103 | quiet - turns off webpack compiler logging
104 |
105 | - watchDelay - determines how frequently file changes are monitored
106 | - headers - hash of headers to add to webpack-dev-server-plugin served files
107 |
108 |
109 |
110 | Questions?
111 | ==============
112 |
113 | Feel free to ask questions if anything is badly described!
114 |
115 | info@atroo.de or an Issue!
116 |
117 |
118 |
--------------------------------------------------------------------------------
/client/live.js:
--------------------------------------------------------------------------------
1 | var $ = require("jquery");
2 | var socketIO = require("socket.io-client");
3 | require("./style.css");
4 |
5 | $(function () {
6 | var body = $("body").html(require("./page.jade")());
7 | var status = $("#status");
8 | var okness = $("#okness");
9 | var $errors = $("#errors");
10 | var iframe = $("#iframe");
11 | var header = $(".header");
12 | var hot = false;
13 | var currentHash = "";
14 |
15 | var contentPage = window.location.pathname.substr("/webpack-dev-server".length) + window.location.search;
16 |
17 | status.text("Connecting to socket.io server...");
18 | $errors.hide();
19 | iframe.hide();
20 | header.css({
21 | borderColor: "#96b5b4"
22 | });
23 | io = socketIO('//', {
24 | path: '/webpackdevserversocket',
25 | transports: ['websocket']
26 | });
27 |
28 | io.on("hot", function () {
29 | hot = true;
30 | iframe.attr("src", contentPage + window.location.hash);
31 | });
32 |
33 | io.on("invalid", function () {
34 | okness.text("");
35 | status.text("App updated. Recompiling...");
36 | header.css({
37 | borderColor: "#96b5b4"
38 | });
39 | $errors.hide();
40 | if (!hot) iframe.hide();
41 | });
42 |
43 | io.on("hash", function (hash) {
44 | currentHash = hash;
45 | });
46 |
47 | io.on("ok", function () {
48 | okness.text("");
49 | $errors.hide();
50 | reloadApp();
51 | });
52 |
53 | io.on("warnings", function (warnings) {
54 | okness.text("Warnings while compiling.");
55 | $errors.hide();
56 | reloadApp();
57 | });
58 |
59 | io.on("errors", function (errors) {
60 | status.text("App updated with errors. No reload!");
61 | okness.text("Errors while compiling.");
62 | $errors.text("\n" + errors.join("\n\n\n") + "\n\n");
63 | header.css({
64 | borderColor: "#ebcb8b"
65 | });
66 | $errors.show();
67 | iframe.hide();
68 | });
69 |
70 | io.on("proxy-error", function (errors) {
71 | status.text("Could not proxy to content base target!");
72 | okness.text("Proxy error.");
73 | $errors.text("\n" + errors.join("\n\n\n") + "\n\n");
74 | header.css({
75 | borderColor: "#ebcb8b"
76 | });
77 | $errors.show();
78 | iframe.hide();
79 | });
80 |
81 | io.on("disconnect", function () {
82 | status.text("");
83 | okness.text("Disconnected.");
84 | $errors.text("\n\n\n Lost connection to webpack-dev-server.\n Please restart the server to reestablish connection...\n\n\n\n");
85 | header.css({
86 | borderColor: "#ebcb8b"
87 | });
88 | $errors.show();
89 | iframe.hide();
90 | });
91 |
92 | iframe.load(function () {
93 | status.text("App ready.");
94 | header.css({
95 | borderColor: ""
96 | });
97 | iframe.show();
98 | });
99 |
100 | function reloadApp() {
101 | if (hot) {
102 | status.text("App hot update.");
103 | try {
104 | iframe[0].contentWindow.postMessage("webpackHotUpdate" + currentHash, "*");
105 | } catch (e) {
106 | console.warn(e);
107 | }
108 | iframe.show();
109 | } else {
110 | status.text("App updated. Reloading app...");
111 | header.css({
112 | borderColor: "#96b5b4"
113 | });
114 | try {
115 | var old = iframe[0].contentWindow.location + "";
116 | if (old.indexOf("about") == 0) old = null;
117 | iframe.attr("src", old || (contentPage + window.location.hash));
118 | old && iframe[0].contentWindow.location.reload();
119 | } catch (e) {
120 | iframe.attr("src", contentPage + window.location.hash);
121 | }
122 | }
123 | }
124 |
125 | });
--------------------------------------------------------------------------------
/client/npm-debug.log:
--------------------------------------------------------------------------------
1 | 0 info it worked if it ends with ok
2 | 1 verbose cli [ 'D:\\Programmierung\\tools\\nodejs\\\\node.exe',
3 | 1 verbose cli 'D:\\Programmierung\\tools\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
4 | 1 verbose cli 'install',
5 | 1 verbose cli '--save-dev',
6 | 1 verbose cli 'jade-laoder' ]
7 | 2 info using npm@1.4.28
8 | 3 info using node@v0.10.35
9 | 4 verbose node symlink D:\Programmierung\tools\nodejs\\node.exe
10 | 5 warn package.json webpackdevserverclient@1.0.0 No description
11 | 6 warn package.json webpackdevserverclient@1.0.0 No repository field.
12 | 7 warn package.json webpackdevserverclient@1.0.0 No README data
13 | 8 verbose readDependencies using package.json deps
14 | 9 verbose cache add [ 'jade-laoder', null ]
15 | 10 verbose cache add name=undefined spec="jade-laoder" args=["jade-laoder",null]
16 | 11 verbose parsed url { protocol: null,
17 | 11 verbose parsed url slashes: null,
18 | 11 verbose parsed url auth: null,
19 | 11 verbose parsed url host: null,
20 | 11 verbose parsed url port: null,
21 | 11 verbose parsed url hostname: null,
22 | 11 verbose parsed url hash: null,
23 | 11 verbose parsed url search: null,
24 | 11 verbose parsed url query: null,
25 | 11 verbose parsed url pathname: 'jade-laoder',
26 | 11 verbose parsed url path: 'jade-laoder',
27 | 11 verbose parsed url href: 'jade-laoder' }
28 | 12 silly lockFile e7e97227-jade-laoder jade-laoder
29 | 13 verbose lock jade-laoder C:\Users\Robert\AppData\Roaming\npm-cache\e7e97227-jade-laoder.lock
30 | 14 silly lockFile e7e97227-jade-laoder jade-laoder
31 | 15 silly lockFile e7e97227-jade-laoder jade-laoder
32 | 16 verbose addNamed [ 'jade-laoder', '' ]
33 | 17 verbose addNamed [ null, '*' ]
34 | 18 silly lockFile 7f984613-jade-laoder jade-laoder@
35 | 19 verbose lock jade-laoder@ C:\Users\Robert\AppData\Roaming\npm-cache\7f984613-jade-laoder.lock
36 | 20 silly addNameRange { name: 'jade-laoder', range: '*', hasData: false }
37 | 21 verbose request where is /jade-laoder
38 | 22 verbose request registry https://registry.npmjs.org/
39 | 23 verbose request id 6fbdd129f65d35eb
40 | 24 verbose url raw /jade-laoder
41 | 25 verbose url resolving [ 'https://registry.npmjs.org/', './jade-laoder' ]
42 | 26 verbose url resolved https://registry.npmjs.org/jade-laoder
43 | 27 verbose request where is https://registry.npmjs.org/jade-laoder
44 | 28 info trying registry request attempt 1 at 16:54:11
45 | 29 http GET https://registry.npmjs.org/jade-laoder
46 | 30 http 404 https://registry.npmjs.org/jade-laoder
47 | 31 verbose headers { date: 'Wed, 04 Feb 2015 15:54:10 GMT',
48 | 31 verbose headers server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
49 | 31 verbose headers 'content-type': 'application/json',
50 | 31 verbose headers 'cache-control': 'max-age=0',
51 | 31 verbose headers 'content-length': '52',
52 | 31 verbose headers 'accept-ranges': 'bytes',
53 | 31 verbose headers via: '1.1 varnish',
54 | 31 verbose headers 'x-served-by': 'cache-lcy1134-LCY',
55 | 31 verbose headers 'x-cache': 'MISS',
56 | 31 verbose headers 'x-cache-hits': '0',
57 | 31 verbose headers 'x-timer': 'S1423065249.972725,VS0,VE159',
58 | 31 verbose headers 'keep-alive': 'timeout=10, max=50',
59 | 31 verbose headers connection: 'Keep-Alive' }
60 | 32 silly registry.get cb [ 404,
61 | 32 silly registry.get { date: 'Wed, 04 Feb 2015 15:54:10 GMT',
62 | 32 silly registry.get server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
63 | 32 silly registry.get 'content-type': 'application/json',
64 | 32 silly registry.get 'cache-control': 'max-age=0',
65 | 32 silly registry.get 'content-length': '52',
66 | 32 silly registry.get 'accept-ranges': 'bytes',
67 | 32 silly registry.get via: '1.1 varnish',
68 | 32 silly registry.get 'x-served-by': 'cache-lcy1134-LCY',
69 | 32 silly registry.get 'x-cache': 'MISS',
70 | 32 silly registry.get 'x-cache-hits': '0',
71 | 32 silly registry.get 'x-timer': 'S1423065249.972725,VS0,VE159',
72 | 32 silly registry.get 'keep-alive': 'timeout=10, max=50',
73 | 32 silly registry.get connection: 'Keep-Alive' } ]
74 | 33 silly lockFile 7f984613-jade-laoder jade-laoder@
75 | 34 silly lockFile 7f984613-jade-laoder jade-laoder@
76 | 35 error 404 404 Not Found: jade-laoder
77 | 35 error 404
78 | 35 error 404 'jade-laoder' is not in the npm registry.
79 | 35 error 404 You should bug the author to publish it
80 | 35 error 404 It was specified as a dependency of 'webpackdevserverclient'
81 | 35 error 404
82 | 35 error 404 Note that you can also install from a
83 | 35 error 404 tarball, folder, or http url, or git url.
84 | 36 error System Windows_NT 6.2.9200
85 | 37 error command "D:\\Programmierung\\tools\\nodejs\\\\node.exe" "D:\\Programmierung\\tools\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "--save-dev" "jade-laoder"
86 | 38 error cwd D:\Programmierung\workspaces\brackets\hapi-webpack-dev-server-plugin\client\new
87 | 39 error node -v v0.10.35
88 | 40 error npm -v 1.4.28
89 | 41 error code E404
90 | 42 verbose exit [ 1, true ]
91 |
--------------------------------------------------------------------------------
/test/suites/serverTest.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | var chai = require('chai');
3 | var spies = require('chai-spies');
4 | chai.use(spies);
5 | var Hapi = require('hapi');
6 | var Wreck = require('wreck');
7 | var path = require("path");
8 | var Webpack = require('webpack');
9 |
10 | var expect = chai.expect;
11 | var gutil = require('gulp-util');
12 |
13 | describe("Hapi Weback-Dev Plugin Test", function () {
14 | var server;
15 | var port = 8337;
16 | var address = 'localhost';
17 | var currDone = null;
18 | var compiler;
19 |
20 | var url = function (path) {
21 | return ["http://", address, ":", port, path].join("")
22 | };
23 |
24 |
25 | // ///////////////////////////////////////
26 | beforeEach(function (done) {
27 | server = new Hapi.Server({
28 | debug: {
29 | //request: ["error"]
30 | }
31 | });
32 | server.connection({
33 | port: port,
34 | host: address
35 | });
36 |
37 | server.route({
38 | method: "*",
39 | path: "/",
40 | handler: function (request, reply) {
41 | reply("ok").code(200);
42 | }
43 | });
44 |
45 | //configure the webpack compiler to work with our dummy test app
46 | var webPackConfig = {
47 | cache: true,
48 | devtool: "eval",
49 | debug: true,
50 | entry: {
51 | entry: "./test/data/entry.js"
52 | },
53 | output: {
54 | path: __dirname + "/dist", //the basic build directory
55 | publicPath: "/dist", //the route which the dev server listens for
56 | filename: "[name].js",
57 | chunkFilename: "[chunkhash].[id].js"
58 | }
59 | };
60 |
61 | compiler = Webpack(webPackConfig);
62 |
63 |
64 | server.start(function () {
65 | server.register({
66 | register: require('./../../src/plugin'),
67 | options: {
68 | compiler: compiler,
69 | //no loginfo
70 | quiet: true,
71 | devIndex: "./test/data"
72 | /*
73 | ,watchDelay: 200
74 | ,noInfo: false
75 | ,headers: {
76 | x-dynamic-content: true
77 | }
78 | */
79 | }
80 | }, function (err) {
81 | expect(err).to.not.exist;
82 | done();
83 | });
84 | });
85 |
86 | var apiTestPlugin = function (plugin, options, next) {
87 | plugin.route({
88 | method: '*',
89 | path: '/api/test',
90 | handler: function (request, reply) {
91 | reply(options.message);
92 | }
93 | });
94 | next();
95 | };
96 |
97 | apiTestPlugin.attributes = {
98 | version: "0.0.0",
99 | name: "test"
100 | };
101 |
102 | server.register({
103 | register: apiTestPlugin,
104 | options: {
105 | message: 'testApi Response'
106 | }
107 | }, function (err) {
108 | if (err) {
109 | console.log('Failed loading plugin');
110 | }
111 | });
112 | });
113 |
114 | afterEach(function (done) {
115 | server.stop(function () {
116 | var err = fs.writeFileSync("./test/data/entry.js",'console.log("test");');
117 | if(err) {
118 | console-log("clean up failed");
119 | }
120 | done();
121 | });
122 | });
123 | // ///////////////////////////////////////
124 |
125 |
126 | // ///////////////////////////////////////
127 | it("should intercept requests", function (done) {
128 | Wreck.get(url("/dist/entry.js"), function (err, res, payload) {
129 | expect(res.headers["x-hapi-webpack-dev"]).to.exist;
130 | expect(res.headers["x-hapi-webpack-dev"]).to.equal("true");
131 | done();
132 | });
133 | });
134 |
135 |
136 | it("should notice a change in webpack relevant files", function (done) {
137 | compiler.plugin("done", function () {
138 | done();
139 | });
140 | fs.appendFile("./test/data/entry.js", "console.log('test');", function (err) {
141 | if (err) {
142 | throw "could not edit entry.js file" + err;
143 | }
144 | });
145 | });
146 |
147 | it("should deliver root html", function (done) {
148 | Wreck.get(url("/index.html"), function (err, res, payload) {
149 | expect(res.statusCode).to.equal(200);
150 | done();
151 | });
152 | });
153 |
154 | it("should redirect to host app", function (done) {
155 | Wreck.get(url("/webpack-dev-server"), function (err, res, payload) {
156 | expect(res.statusCode).to.equal(302);
157 | done();
158 | });
159 | });
160 |
161 | it("should serve the bundle js file", function (done) {
162 | Wreck.get(url("/__webpack_dev_server__/live.bundle.js"), function (err, res, payload) {
163 | expect(res.statusCode).to.equal(200);
164 | done();
165 | });
166 | });
167 |
168 | it("should serve the webpackdevserver frontend js file", function (done) {
169 | Wreck.get(url("/webpack-dev-server.js"), function (err, res, payload) {
170 | expect(res.statusCode).to.equal(200);
171 | done();
172 | });
173 | });
174 |
175 | it("should serve dynamic content from the memory filesystem", function (done) {
176 | Wreck.get(url("/dist/entry.js"), function (err, res, payload) {
177 | expect(res.statusCode).to.equal(200);
178 | done();
179 | });
180 | });
181 |
182 | it("should serve an error for unknown files", function (done) {
183 | Wreck.get(url("/dist/entry_undefined.js"), function (err, res, payload) {
184 | expect(res.statusCode).to.equal(404);
185 | done();
186 | });
187 | });
188 |
189 | it("should handle routes correctly", function (done) {
190 | Wreck.get(url("/api/test"), function (err, res, payload) {
191 | expect(res.statusCode).to.equal(200);
192 | Wreck.post(url("/api/test"), function (err, res, payload) {
193 | expect(res.statusCode).to.equal(200);
194 | done();
195 | });
196 | });
197 | });
198 | // ///////////////////////////////////////
199 | });
--------------------------------------------------------------------------------
/src/pluginutil.js:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License http://www.opensource.org/licenses/mit-license.php
3 | Author Tobias Koppers @sokra
4 |
5 | This is an adaptation of sokras great webpack-dev-middle-ware for webpacks compiler state managment as well as default routing working for express as a middleware
6 | This adapation will do a comparable thing for Hapi in context of beeing integrated in a hapi plugin
7 |
8 | Author Robert Krüger +de.robat
9 | */
10 |
11 | var path = require("path");
12 | var MemoryFileSystem = require("memory-fs");
13 | var mime = require("mime");
14 | var Boom = require("boom");
15 |
16 | // constructor for the middlewa
17 | module.exports = function (options) {
18 | var compiler = options.compiler;
19 | if (options.watchDelay === undefined) options.watchDelay = 200;
20 | if (typeof options.stats === "undefined") options.stats = {};
21 | if (!options.stats.context) options.stats.context = process.cwd();
22 |
23 | // store our files in memory
24 | var files = {};
25 | var fs = compiler.outputFileSystem = new MemoryFileSystem();
26 |
27 | compiler.plugin("done", function (stats) {
28 | // We are now on valid state
29 | state = true;
30 | // Do the stuff in nextTick, because bundle may be invalidated
31 | // if a change happend while compiling
32 | process.nextTick(function () {
33 | // check if still in valid state
34 | if (!state) return;
35 | // print webpack output
36 | var displayStats = (!options.quiet && options.stats !== false);
37 | if (displayStats &&
38 | !(stats.hasErrors() || stats.hasWarnings()) &&
39 | options.noInfo)
40 | displayStats = false;
41 | if (displayStats) {
42 | console.log(stats.toString(options.stats));
43 | }
44 | if (!options.noInfo && !options.quiet)
45 | console.info("webpack: bundle is now VALID.");
46 |
47 | // execute callback that are delayed
48 | var cbs = callbacks;
49 | callbacks = [];
50 | cbs.forEach(function continueBecauseBundleAvailible(cb) {
51 | cb();
52 | });
53 | });
54 |
55 | if (forceRebuild) {
56 | forceRebuild = false;
57 | rebuild();
58 | }
59 | });
60 |
61 | // on compiling
62 | function invalidPlugin() {
63 | if (state && (!options.noInfo && !options.quiet))
64 | console.info("webpack: bundle is now INVALID.");
65 | // We are now in invalid state
66 | state = false;
67 | }
68 | compiler.plugin("invalid", invalidPlugin);
69 | compiler.plugin("compile", invalidPlugin);
70 |
71 | // the state, false: bundle invalid, true: bundle valid
72 | var state = false;
73 |
74 | var forceRebuild = false;
75 |
76 | // delayed callback
77 | var callbacks = [];
78 |
79 | // wait for bundle valid
80 | function ready(fn, url) {
81 | if (state) return fn();
82 | if (!options.noInfo && !options.quiet)
83 | console.log("webpack: wait until bundle finished: " + url);
84 | callbacks.push(fn);
85 | }
86 |
87 | var watching = compiler.watch(options.watchDelay, function (err) {
88 | if (err) throw err;
89 | });
90 |
91 | function rebuild() {
92 | if (state) {
93 | state = false;
94 | compiler.run(function (err) {
95 | if (err) throw err;
96 | });
97 | } else {
98 | forceRebuild = true;
99 | }
100 | }
101 |
102 | function pathJoin(a, b) {
103 | return a == "/" ? "/" + b : (a || "") + "/" + b
104 | }
105 |
106 | function getFilenameFromUrl(url) {
107 | // publicPrefix is the folder our bundle should be in
108 | var localPrefix = compiler.options.output.publicPath || "/";
109 | if(localPrefix[0] != "/"){
110 | //the route always starts with a slash even when the publicPath doesnt
111 | localPrefix = "/" + localPrefix;
112 | }
113 | if (url.indexOf(localPrefix) !== 0) {
114 | if (/^(https?:)?\/\//.test(localPrefix)) {
115 | localPrefix = "/" + localPrefix.replace(/^(https?:)?\/\/[^\/]+\//, "");
116 | // fast exit if another directory requested
117 | if (url.indexOf(localPrefix) !== 0) return false;
118 | } else return false;
119 | }
120 | // get filename from request
121 | var filename = url.substr(localPrefix.length);
122 | if (filename.indexOf("?") >= 0) {
123 | filename = filename.substr(0, filename.indexOf("?"));
124 | }
125 | return filename ? pathJoin(compiler.outputPath, filename) : compiler.outputPath;
126 | }
127 |
128 | function beforeRequest(req, reply) {
129 | var filename = getFilenameFromUrl(req.url.path);
130 | if (filename === false) return reply.continue();
131 |
132 | // delay the request until we have a vaild bundle
133 | ready(function () {
134 | try {
135 | var stat = fs.statSync(filename);
136 | if (!stat.isFile()) {
137 | if (stat.isDirectory()) {
138 | filename = path.join(filename, "index.html");
139 | stat = fs.statSync(filename);
140 | if (!stat.isFile()) throw "next";
141 | } else {
142 | throw "next";
143 | }
144 | }
145 | } catch (e) {
146 | return reply.continue();
147 | }
148 |
149 | //reply with a file from the mem fs
150 | var content = fs.readFileSync(filename);
151 | var res = reply(content);
152 |
153 | res.header("Access-Control-Allow-Origin", "*"); // To support XHR, etc.
154 | res.header("x-hapi-webpack-dev", "true"); // allow for unittests
155 | res.header("Content-Type", mime.lookup(filename));
156 |
157 | if (options.headers) {
158 | for (var name in options.headers) {
159 | res.header(name, options.headers[name]);
160 | }
161 | };
162 | }, filename);
163 | };
164 |
165 | return {
166 | beforeRequest: beforeRequest,
167 | getFilenameFromUrl: getFilenameFromUrl,
168 | invalidate: function () {
169 | if (watching) watching.invalidate();
170 | },
171 | close: function (callback) {
172 | callback = callback || function () {};
173 | if (watching) watching.close(callback);
174 | else callback();
175 | },
176 | fileSystem: fs
177 | };
178 | }
--------------------------------------------------------------------------------
/src/plugin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * http://opensource.org/licenses/mit-license.php
3 | * Author Tobias koppers
4 | *
5 | * This is an adaptation of the great work of Tobias Koppers to allow for a HapiJS Server to work as a webpack-dev-server by the help of this plugin as well
6 | *
7 | * Author Robert Krüger +de.robat www.atroo.de
8 | */
9 |
10 | var fs = require("fs");
11 | var path = require("path");
12 | var PluginUtil = require("./pluginutil");
13 | var mime = require("mime");
14 | var Boom = require("boom");
15 |
16 | var compiler,
17 | io,
18 | pluginUtil,
19 | pluginDevOptions,
20 | options,
21 | _stats,
22 | devIndex;
23 |
24 | //before each request make sure that the webpack compiler is in a acceptable state (at least if we have to server files)
25 | function runPreHandlerInterceptor(req, reply) {
26 | try {
27 | pluginUtil.beforeRequest(req, reply);
28 | } catch (e) {
29 | console.error("PreHandler Fault: ", e);
30 | reply(e);
31 | }
32 | };
33 |
34 | function sendStats(socket, stats, force) {
35 | if (!force && stats && stats.assets && stats.assets.every(function (asset) {
36 | return !asset.emitted;
37 | })) return;
38 | socket.emit("hash", stats.hash);
39 | if (stats.errors.length > 0)
40 | socket.emit("errors", stats.errors);
41 | else if (stats.warnings.length > 0)
42 | socket.emit("warnings", stats.warnings);
43 | else
44 | socket.emit("ok");
45 | }
46 |
47 | function serveMagicHtml(req, reply) {
48 | var _path = req.path;
49 | try {
50 | if (!pluginUtil.fileSystem.statSync(pluginUtil.getFilenameFromUrl(_path + ".js")).isFile())
51 | return false;
52 | // Serve a page that executes the javascript
53 | var res = '';
58 | reply(res);
59 | return true;
60 | } catch (e) {
61 | return false
62 | }
63 | }
64 |
65 |
66 | /**
67 | * setup all the necessities for the plugin to work
68 | */
69 | exports.register = function (server, opts, next) {
70 | if (opts && opts.compiler) {
71 |
72 | //general options beeing presented to the whole plugin
73 | options = opts;
74 |
75 | devIndex = opts.devIndex || ".";
76 | //the webpack compiler object to work with
77 | compiler = opts.compiler;
78 |
79 | pluginUtil = PluginUtil(opts);
80 | server.ext("onPreHandler", runPreHandlerInterceptor);
81 |
82 | //if the pack halts, stop the compilers watching task
83 | server.on("stop", function () {
84 | //close down the watch task of the middleware
85 | pluginUtil.close();
86 | });
87 |
88 | var invalidPlugin = function () {
89 | if (io) io.sockets.emit("invalid");
90 | }.bind(this);
91 | compiler.plugin("compile", invalidPlugin);
92 | compiler.plugin("invalid", invalidPlugin);
93 | compiler.plugin("done", function (stats) {
94 | if (!io) return;
95 | sendStats(io.sockets, stats.toJson());
96 | _stats = stats;
97 | }.bind(this));
98 |
99 | //configure some standard routes which are involved in the startup process
100 | //the js file to build the hosting iframe
101 | server.route({
102 | method: "GET",
103 | path: "/__webpack_dev_server__/live.bundle.js",
104 | config: {
105 | auth: false,
106 | handler: function (req, reply) {
107 | reply(fs.createReadStream(path.join(__dirname, "..", "client", "live.bundle.js"))).header("Content-Type", "application/javascript");;
108 | }
109 | }
110 | });
111 |
112 | server.route({
113 | method: "GET",
114 | path: "/webpack-dev-server.js",
115 | config: {
116 | auth: false,
117 | handler: function (req, reply) {
118 | reply(fs.createReadStream(path.join(__dirname, "..", "client", "index.bundle.js"))).header("Content-Type", "application/javascript");
119 | }
120 | }
121 | });
122 |
123 | //the html requesting the live.bundle.js
124 | server.route({
125 | method: "GET",
126 | path: "/webpack-dev-server/{anything*}",
127 | config: {
128 | auth: false,
129 | handler: function (req, reply) {
130 | reply(fs.createReadStream(path.join(__dirname, "..", "client", "live.html"))).header("Content-Type", "text/html");
131 | }
132 | }
133 | });
134 |
135 | //the html requesting the live.bundle.js
136 | server.route({
137 | method: "GET",
138 | path: "/index.html",
139 | config: {
140 | auth: false,
141 | handler: function (req, reply) {
142 | if (options.devView && options.devView.name) {
143 | var data = typeof (options.devView.data) == "function" ? options.devView.data(req) : options.devView.data || {};
144 | reply.view(options.devView.name, data);
145 | } else {
146 | reply.file(path.join(devIndex, "index.html"));
147 | }
148 | }
149 | }
150 | });
151 |
152 | //a listing of whats contained in the dev server
153 | server.route({
154 | method: "GET",
155 | path: "/webpack-dev-server",
156 | config: {
157 | auth: false,
158 | handler: function (req, reply) {
159 | reply.redirect("webpack-dev-server/index.html");
160 | }
161 | }
162 | });
163 |
164 | //register socketio to listen to any server in the pack
165 | var socketIO = require('socket.io');
166 | server.connections.forEach(function (srv) {
167 | io = socketIO.listen(srv.listener, {
168 | serveClient: false,
169 | path: '/webpackdevserversocket',
170 | log: false
171 | });
172 | io.set('transports', ['websocket']);
173 | io.sockets.on("connection", function (socket) {
174 | if (!_stats) {
175 | return;
176 | }
177 | sendStats(socket, _stats.toJson(), true);
178 | }.bind(this));
179 | });
180 |
181 | next();
182 | } else {
183 | next("unsufficient options parameter for hapiWebpackDev Plugin. A Webpack Compiler object is needed!");
184 | }
185 | };
186 |
187 | exports.register.attributes = {
188 | pkg: require('./../package.json')
189 | };
--------------------------------------------------------------------------------
/npm-debug.log:
--------------------------------------------------------------------------------
1 | 0 info it worked if it ends with ok
2 | 1 verbose cli [ 'D:\\Programmierung\\tools\\nodejs\\\\node.exe',
3 | 1 verbose cli 'D:\\Programmierung\\tools\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
4 | 1 verbose cli 'publish',
5 | 1 verbose cli '-r',
6 | 1 verbose cli 'http://registry.atroo.de' ]
7 | 2 info using npm@1.4.28
8 | 3 info using node@v0.10.35
9 | 4 verbose node symlink D:\Programmierung\tools\nodejs\\node.exe
10 | 5 verbose publish [ '.' ]
11 | 6 verbose cache add [ '.', null ]
12 | 7 verbose cache add name=undefined spec="." args=[".",null]
13 | 8 verbose parsed url { protocol: null,
14 | 8 verbose parsed url slashes: null,
15 | 8 verbose parsed url auth: null,
16 | 8 verbose parsed url host: null,
17 | 8 verbose parsed url port: null,
18 | 8 verbose parsed url hostname: null,
19 | 8 verbose parsed url hash: null,
20 | 8 verbose parsed url search: null,
21 | 8 verbose parsed url query: null,
22 | 8 verbose parsed url pathname: '.',
23 | 8 verbose parsed url path: '.',
24 | 8 verbose parsed url href: '.' }
25 | 9 silly lockFile 3a52ce78- .
26 | 10 verbose lock . C:\Users\Robert\AppData\Roaming\npm-cache\3a52ce78-.lock
27 | 11 verbose tar pack [ 'C:\\Users\\Robert\\AppData\\Roaming\\npm-cache\\hapi-webpack-dev-plugin\\0.0.10\\package.tgz',
28 | 11 verbose tar pack '.' ]
29 | 12 verbose tarball C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package.tgz
30 | 13 verbose folder .
31 | 14 info prepublish hapi-webpack-dev-plugin@0.0.10
32 | 15 silly lockFile 1f1177db-tar tar://.
33 | 16 verbose lock tar://. C:\Users\Robert\AppData\Roaming\npm-cache\1f1177db-tar.lock
34 | 17 silly lockFile 12cb8f05-ck-dev-plugin-0-0-10-package-tgz tar://C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package.tgz
35 | 18 verbose lock tar://C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package.tgz C:\Users\Robert\AppData\Roaming\npm-cache\12cb8f05-ck-dev-plugin-0-0-10-package-tgz.lock
36 | 19 silly lockFile 1f1177db-tar tar://.
37 | 20 silly lockFile 1f1177db-tar tar://.
38 | 21 silly lockFile 12cb8f05-ck-dev-plugin-0-0-10-package-tgz tar://C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package.tgz
39 | 22 silly lockFile 12cb8f05-ck-dev-plugin-0-0-10-package-tgz tar://C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package.tgz
40 | 23 silly lockFile f93615a6-ebpack-dev-plugin-0-0-10-package C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package
41 | 24 verbose lock C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package C:\Users\Robert\AppData\Roaming\npm-cache\f93615a6-ebpack-dev-plugin-0-0-10-package.lock
42 | 25 silly lockFile f93615a6-ebpack-dev-plugin-0-0-10-package C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package
43 | 26 silly lockFile f93615a6-ebpack-dev-plugin-0-0-10-package C:\Users\Robert\AppData\Roaming\npm-cache\hapi-webpack-dev-plugin\0.0.10\package
44 | 27 silly lockFile 3a52ce78- .
45 | 28 silly lockFile 3a52ce78- .
46 | 29 silly publish { name: 'hapi-webpack-dev-plugin',
47 | 29 silly publish version: '0.0.10',
48 | 29 silly publish description: 'a plugin to integrate the web-pack-dev-server as a hapi plugin into a hapi server instead of using express',
49 | 29 silly publish main: 'src/plugin.js',
50 | 29 silly publish scripts: { test: 'echo "Error: no test specified" && exit 1' },
51 | 29 silly publish keywords: [ 'hapi', 'webpack', 'devserver', 'server', 'dev' ],
52 | 29 silly publish author: { name: 'atroo', url: 'info@atroo.de' },
53 | 29 silly publish repository:
54 | 29 silly publish { type: 'git',
55 | 29 silly publish url: 'https://github.com/atroo/hapi-webpack-dev-server-plugin' },
56 | 29 silly publish license: 'ISC',
57 | 29 silly publish devDependencies:
58 | 29 silly publish { chai: '^1.9.2',
59 | 29 silly publish 'chai-spies': '^0.5.1',
60 | 29 silly publish gulp: '^3.8.10',
61 | 29 silly publish 'gulp-connect': '^2.2.0',
62 | 29 silly publish 'gulp-mocha': '^1.1.1',
63 | 29 silly publish 'gulp-util': '^3.0.1',
64 | 29 silly publish hapi: '8.x.x',
65 | 29 silly publish webpack: '^1.4.12',
66 | 29 silly publish wreck: '^5.0.1' },
67 | 29 silly publish dependencies:
68 | 29 silly publish { boom: '^2.6.0',
69 | 29 silly publish jquery: '^2.1.1',
70 | 29 silly publish 'memory-fs': '^0.1.0',
71 | 29 silly publish mime: '^1.2.11',
72 | 29 silly publish 'socket.io': '^1.3.3' },
73 | 29 silly publish readme: 'hapi-webpack-dev-server-plugin\r\n==============================\r\n\r\nThis is a plugin for hapijs providing the necessary routes to function as a webpack-dev-server for the [awesome webpack project](http://webpack.github.io/) directly in hapijs. The actual [Webpack-dev-server](https://github.com/webpack/webpack-dev-server) is implemented with express.js and since we are heavily using the fabulous [hapijs](http://hapijs.com/) as our main backend framework we found it very useful to have everything right there. This avoids tweaking SOP related things just for dev purposes.\r\n\r\nJust like the original webpack-dev-server we also want to give out a quick warning: \r\n\r\n*DON\'T USE THIS PLUGIN IN PRODUCTION!*\r\n\r\nRequirements: hapijs ^8.x.x\r\n\r\nState: In Progress (meaning not hot code replacement at the moment, but auto relaoding works just fine)\r\n\r\nBasic Usage\r\n=====\r\n\r\nwe tend to structure our apps like\r\n```javascript\r\n- server_plugin\r\n index.js\r\n- webpack_frontend\r\n - src\r\n main.js\r\n webpack.config.js\r\nserver.js\r\n```\r\n\r\nwith that structure in mind you\'d setup the dev-server-plugin in the server.js as follows\r\n\r\n```javascript\r\nvar Webpack = require(\'webpack\');\r\nvar Hapi = require(\'hapi\');\r\n\r\n//basic webpack config, see webpack api docs for all options\r\nvar webpackConf = require(\'./webpack_frontend/webpack.config.js\');\r\nwebpackConf.entry = {\r\n app: \'./webpack_frontend/src/main.js\' //this is needed to have the correct relative paths for the webpack compiler which now runs from the base dir rather than from webpack_frontend\r\n};\r\nwebpackConf.devtool = \'source-map\';\r\n\r\n//create the webpack compiler\r\ncompiler = Webpack(webPackConfig);\r\n\r\n//create hapi server\r\nserver = new Hapi.Server();\r\nserver.connection({\r\n\tport: port,\r\n\thost: address\r\n});\r\n\r\n//start server and register dev server as plugin\r\nserver.start(function () {\r\n server.register({\r\n register: require(\'hapi-webpack-dev-plugin\'),\r\n options: {\r\n compiler: compiler,\r\n //no loginfo\r\n quiet: true,\r\n //where is the index.html located\r\n devIndex: ".", //not needed if devView is configured\r\n devView: { //allows to configure a view with whatever engine hapi has been configured to induce e.e. session information on startup\r\n name: \'main.html\',\r\n data: function (request) {\r\n var tplData = {\r\n "entrypoint": "dist/app.js"\r\n };\r\n return tplData;\r\n }\r\n }\r\n /*\r\n ,watchDelay: 200\r\n ,noInfo: false\r\n ,headers: {\r\n x-dynamic-content: true\r\n }\r\n */\r\n }\r\n }, function (err) {\r\n console.log(err);\r\n });\r\n});\r\n\r\n```\r\n\r\nConfig Options\r\n==============\r\n\r\n\r\n\t- compiler - the webpack compiler
\r\n\t- devIndex - path to the dev index.html file. Is ignored if devView is configured. defaults to index.html in the cwd
\r\n\t- devView
\r\n
\r\n```javascript\r\n{\r\n\tname: "the name of the view" // mandatory, elsewise the devIndex will be used\r\n\tdata: "tplData" // an object, a function which gets passed in the request, or empty - data is supposed to determine tplData for the view\r\n}\r\n\r\n```\r\n\r\n\t- \r\n\t\tquiet - turns off webpack compiler logging\r\n\t
\r\n\t- watchDelay - determines how frequently file changes are monitored
\r\n\t- headers - hash of headers to add to webpack-dev-server-plugin served files
\r\n
\r\n\r\nQuestions?\r\n==============\r\n\r\nFeel free to ask questions if anything is badly described!\r\n\r\ninfo@atroo.de or an Issue!\r\n\r\n\r\n',
74 | 29 silly publish readmeFilename: 'README.md',
75 | 29 silly publish gitHead: '69e28cb0a08804ccbee575c0d10891d35217a4e0',
76 | 29 silly publish bugs: { url: 'https://github.com/atroo/hapi-webpack-dev-server-plugin/issues' },
77 | 29 silly publish homepage: 'https://github.com/atroo/hapi-webpack-dev-server-plugin',
78 | 29 silly publish _id: 'hapi-webpack-dev-plugin@0.0.10',
79 | 29 silly publish _shasum: '6a13c0c97647d703bed2326ed143510165545697',
80 | 29 silly publish _from: '.' }
81 | 30 verbose request where is /hapi-webpack-dev-plugin
82 | 31 verbose request registry http://registry.atroo.de/
83 | 32 verbose request id 640a287a9713f86d
84 | 33 verbose url raw /hapi-webpack-dev-plugin
85 | 34 verbose url resolving [ 'http://registry.atroo.de/', './hapi-webpack-dev-plugin' ]
86 | 35 verbose url resolved http://registry.atroo.de/hapi-webpack-dev-plugin
87 | 36 verbose request where is http://registry.atroo.de/hapi-webpack-dev-plugin
88 | 37 info trying registry request attempt 1 at 17:02:20
89 | 38 http PUT http://registry.atroo.de/hapi-webpack-dev-plugin
90 | 39 http 409 http://registry.atroo.de/hapi-webpack-dev-plugin
91 | 40 verbose headers { server: 'nginx/1.7.8',
92 | 40 verbose headers date: 'Wed, 04 Feb 2015 16:02:33 GMT',
93 | 40 verbose headers 'content-type': 'application/json; charset=utf-8',
94 | 40 verbose headers 'content-length': '46',
95 | 40 verbose headers connection: 'keep-alive',
96 | 40 verbose headers 'x-powered-by': 'Sinopia/1.0.0',
97 | 40 verbose headers vary: 'Accept-Encoding',
98 | 40 verbose headers 'x-status-cat': 'http://flic.kr/p/aV6jzz' }
99 | 41 verbose request where is /hapi-webpack-dev-plugin?write=true
100 | 42 verbose request registry http://registry.atroo.de/
101 | 43 verbose url raw /hapi-webpack-dev-plugin?write=true
102 | 44 verbose url resolving [ 'http://registry.atroo.de/',
103 | 44 verbose url resolving './hapi-webpack-dev-plugin?write=true' ]
104 | 45 verbose url resolved http://registry.atroo.de/hapi-webpack-dev-plugin?write=true
105 | 46 verbose request where is http://registry.atroo.de/hapi-webpack-dev-plugin?write=true
106 | 47 info trying registry request attempt 1 at 17:02:27
107 | 48 http GET http://registry.atroo.de/hapi-webpack-dev-plugin?write=true
108 | 49 http 200 http://registry.atroo.de/hapi-webpack-dev-plugin?write=true
109 | 50 error publish fail Cannot publish over existing version.
110 | 50 error publish fail Update the 'version' field in package.json and try again.
111 | 50 error publish fail
112 | 50 error publish fail If the previous version was published in error, see:
113 | 50 error publish fail npm help unpublish
114 | 50 error publish fail
115 | 50 error publish fail To automatically increment version numbers, see:
116 | 50 error publish fail npm help version
117 | 51 error System Windows_NT 6.2.9200
118 | 52 error command "D:\\Programmierung\\tools\\nodejs\\\\node.exe" "D:\\Programmierung\\tools\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "publish" "-r" "http://registry.atroo.de"
119 | 53 error cwd D:\Programmierung\workspaces\brackets\hapi-webpack-dev-server-plugin
120 | 54 error node -v v0.10.35
121 | 55 error npm -v 1.4.28
122 | 56 error code EPUBLISHCONFLICT
123 | 57 verbose exit [ 1, true ]
124 |
--------------------------------------------------------------------------------