diff --git a/.jshintignore b/.jshintignore
index 3efe38d3b6..089bd1f5ef 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -2,5 +2,6 @@ appengine/kraken/public/components/**
appengine/sails/config/**
appengine/sails/tasks/**
appengine/sails/assets/**
+appengine/webpack/dist/**
**/node_modules/**
coverage/
\ No newline at end of file
diff --git a/appengine/webpack/.gitignore b/appengine/webpack/.gitignore
new file mode 100644
index 0000000000..77738287f0
--- /dev/null
+++ b/appengine/webpack/.gitignore
@@ -0,0 +1 @@
+dist/
\ No newline at end of file
diff --git a/appengine/webpack/README.md b/appengine/webpack/README.md
new file mode 100644
index 0000000000..fb90d91468
--- /dev/null
+++ b/appengine/webpack/README.md
@@ -0,0 +1,11 @@
+## Express.js + Webpack on Google App Engine
+
+> [Webpack][1] is a module bundler
+>
+> – webpack.github.io
+
+This sample application demonstrates how to use [Webpack][1] to bundle frontend
+code and then serve it with [Express.js][2] on Google App Engine.
+
+[1]: http://webpack.github.io/
+[2]: http://expressjs.com/
diff --git a/appengine/webpack/app.yaml b/appengine/webpack/app.yaml
new file mode 100644
index 0000000000..03acf33b16
--- /dev/null
+++ b/appengine/webpack/app.yaml
@@ -0,0 +1,14 @@
+# Copyright 2015, Google, Inc.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+runtime: nodejs
+vm: true
diff --git a/appengine/webpack/package.json b/appengine/webpack/package.json
new file mode 100644
index 0000000000..97fc523368
--- /dev/null
+++ b/appengine/webpack/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "appengine-webpack",
+ "description": "An example of using Webpack with Node.js on Google App Engine.",
+ "version": "0.0.1",
+ "private": true,
+ "license": "Apache Version 2.0",
+ "engines": {
+ "node": "~4.2"
+ },
+ "scripts": {
+ "bundle": "webpack --config webpack.config.js",
+ "prestart": "npm run bundle",
+ "start": "node server.js",
+ "deploy": "gcloud preview app deploy app.yaml"
+ },
+ "dependencies": {
+ "express": "^4.13.3",
+ "jade": "^1.11.0",
+ "webpack": "^1.12.6"
+ }
+}
diff --git a/appengine/webpack/public/app.js b/appengine/webpack/public/app.js
new file mode 100644
index 0000000000..2e1be7a44e
--- /dev/null
+++ b/appengine/webpack/public/app.js
@@ -0,0 +1,19 @@
+// Copyright 2015, Google, Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/* global document:true */
+'use strict';
+
+var foo = require('./foo.js');
+
+document.getElementById('module-name').innerText = foo.name;
diff --git a/appengine/webpack/public/foo.js b/appengine/webpack/public/foo.js
new file mode 100644
index 0000000000..dcba093f4c
--- /dev/null
+++ b/appengine/webpack/public/foo.js
@@ -0,0 +1,18 @@
+// Copyright 2015, Google, Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+module.exports = {
+ name: 'foo'
+};
diff --git a/appengine/webpack/server.js b/appengine/webpack/server.js
new file mode 100644
index 0000000000..affb6b4aaf
--- /dev/null
+++ b/appengine/webpack/server.js
@@ -0,0 +1,39 @@
+// Copyright 2015, Google, Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+var express = require('express');
+var path = require('path');
+
+var app = express();
+
+// Setup view engine
+app.set('view engine', 'jade');
+
+app.use(express.static(__dirname + '/dist'));
+
+app.get('/', function(req, res) {
+ res.render('index');
+});
+
+var server = app.listen(
+ process.env.PORT || 8080,
+ '0.0.0.0',
+ function () {
+ var address = server.address().address;
+ var port = server.address().port;
+ console.log('App listening at http://%s:%s', address, port);
+ console.log('Press Ctrl+C to quit.');
+ }
+);
diff --git a/appengine/webpack/views/index.jade b/appengine/webpack/views/index.jade
new file mode 100644
index 0000000000..28bbeec963
--- /dev/null
+++ b/appengine/webpack/views/index.jade
@@ -0,0 +1,23 @@
+// Copyright 2015, Google, Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+doctype html
+html
+ head
+ title= title
+ body
+ h1 Hello World!
+ p Express.js + Webpack on Google App Engine.
+ hr
+ p Loaded module via Webpack.
+ script(type='text/javascript', src='app.js')
diff --git a/appengine/webpack/webpack.config.js b/appengine/webpack/webpack.config.js
new file mode 100644
index 0000000000..f45f55d69d
--- /dev/null
+++ b/appengine/webpack/webpack.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ entry: './public/app.js',
+ output: {
+ filename: './dist/app.js'
+ }
+};
diff --git a/test/appengine/all.test.js b/test/appengine/all.test.js
index bb13f2426f..c458e86fde 100644
--- a/test/appengine/all.test.js
+++ b/test/appengine/all.test.js
@@ -102,6 +102,13 @@ var sampleTests = [
args: ['server.js'],
msg: 'Hello World! Restify.js on Google App Engine.',
TRAVIS_NODE_VERSION: 'stable'
+ },
+ {
+ dir: 'webpack',
+ deploy: false,
+ cmd: 'node',
+ args: ['server.js'],
+ msg: 'Loaded module foo via Webpack.'
}
];