├── .gitignore ├── app ├── loading.jade ├── home.jade ├── style.css ├── test1 │ ├── content.jade │ └── index.js ├── test3.jade ├── chunk.jade ├── test2.jade ├── sources.jade ├── pages.js ├── body.jade └── app.js ├── web_modules ├── three │ └── index.js └── mybootstrap │ ├── index.js │ ├── variables.less │ ├── bootstrap.js │ └── bootstrap.less ├── index.html ├── webpack-update2.config.js ├── webpack-update1.config.js ├── fake-update.js ├── README.md ├── package.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | jam 3 | assets 4 | records.json -------------------------------------------------------------------------------- /app/loading.jade: -------------------------------------------------------------------------------- 1 | .progress.progress-striped.active 2 | .bar(style="width: 100%") -------------------------------------------------------------------------------- /web_modules/three/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("exports?THREE!./Three.min.js"); -------------------------------------------------------------------------------- /web_modules/mybootstrap/index.js: -------------------------------------------------------------------------------- 1 | require("./bootstrap.less"); 2 | require("./bootstrap.js"); -------------------------------------------------------------------------------- /app/home.jade: -------------------------------------------------------------------------------- 1 | .alert.alert-success You are on Home 2 | h2 home.jade 3 | pre: code= require("!raw!./home.jade") -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /webpack-update2.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./webpack-update1.config.js"); 2 | module.exports.fakeUpdateVersion = 2; 3 | -------------------------------------------------------------------------------- /app/style.css: -------------------------------------------------------------------------------- 1 | body {} 2 | ------ 3 | .navbar-default { 4 | background: #FFA !important; 5 | } 6 | ------ 7 | .navbar-default { 8 | background: #AFA !important; 9 | } 10 | -------------------------------------------------------------------------------- /webpack-update1.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./webpack.config.js"); 2 | module.exports.output.filename = "ignored"; 3 | module.exports.recordsPath = module.exports.recordsOutputPath; 4 | module.exports.fakeUpdateVersion = 1; 5 | -------------------------------------------------------------------------------- /app/test1/content.jade: -------------------------------------------------------------------------------- 1 | h1 three.js canvas - camera - orthographic example 2 | .three-container 3 | h2 test1/index.js 4 | pre.pre-scrollable: code= require("!raw!./index.js") 5 | h2 test1/content.jade 6 | pre: code= require("!raw!./content.jade") -------------------------------------------------------------------------------- /web_modules/mybootstrap/variables.less: -------------------------------------------------------------------------------- 1 | // Variables.less 2 | // Variables to customize the look and feel of Bootstrap 3 | // ----------------------------------------------------- 4 | 5 | @iconSpritePath: "~bootstrap/img/glyphicons-halflings.png"; 6 | @iconWhiteSpritePath: "~bootstrap/img/glyphicons-halflings-white.png"; 7 | -------------------------------------------------------------------------------- /app/test3.jade: -------------------------------------------------------------------------------- 1 | .alert.alert-error 2 | | This is the 3 | = " " 4 | b last 5 | | test. 6 | ------ 7 | .alert.alert-error 8 | | This is the 9 | = " " 10 | i last 11 | | test. (Updated Version 1) 12 | ------ 13 | .alert.alert-error 14 | | This is the 15 | = " " 16 | b last 17 | | test. (Updated Version 2) 18 | -------------------------------------------------------------------------------- /fake-update.js: -------------------------------------------------------------------------------- 1 | module.exports = function(content) { 2 | var version = this.options.fakeUpdateVersion; 3 | var versions = content.split("\n------"); 4 | var current = ""; 5 | while(!current) { 6 | current = versions[version--]; 7 | if(current) current = current.replace(/^[\r\n]*|[\r\n]*$/g, ""); 8 | } 9 | this.cacheable(); 10 | return current; 11 | } -------------------------------------------------------------------------------- /app/chunk.jade: -------------------------------------------------------------------------------- 1 | - if(self.chunk === 0) 2 | | inital bundle 3 | = " " 4 | span.badge= self.chunk 5 | | ( 6 | code web.js 7 | | ) 8 | | was loaded. (script-tag) 9 | - else 10 | | bundle 11 | = " " 12 | span.badge.badge-success= self.chunk 13 | | ( 14 | code 15 | = self.chunk 16 | | .web.js 17 | | ) 18 | | was loaded. (asynchron) -------------------------------------------------------------------------------- /app/test2.jade: -------------------------------------------------------------------------------- 1 | .alert.alert-warning 2 | span This is the second test. 3 | h2 test2.jade 4 | pre: code= require("!raw!./test2.jade") 5 | ------ 6 | .alert.alert-warning 7 | span This is the second test. (Updated Version 1) 8 | h2 test2.jade 9 | pre: code= require("!raw!./test2.jade") 10 | ------ 11 | .alert.alert-warning 12 | span This is the second test. (Updated Version 2) 13 | h2 test2.jade 14 | pre: code= require("!raw!./test2.jade") 15 | -------------------------------------------------------------------------------- /app/sources.jade: -------------------------------------------------------------------------------- 1 | ul.nav.nav-tabs 2 | li.active 3 | a(href="#app", data-toggle="tab") 4 | i.icon-off 5 | | app.js 6 | li 7 | a(href="#body", data-toggle="tab") 8 | i.icon-leaf 9 | | body.jade 10 | li 11 | a(href="#sources", data-toggle="tab") 12 | i.icon-file 13 | | sources.jade 14 | .tab-content 15 | #app.tab-pane.active 16 | pre.pre-scrollable 17 | code= require("!raw!./app.js") 18 | #body.tab-pane 19 | pre.pre-scrollable 20 | code= require("!raw!./body.jade") 21 | #sources.tab-pane 22 | pre.pre-scrollable 23 | code= require("!raw!./sources.jade") 24 | -------------------------------------------------------------------------------- /web_modules/mybootstrap/bootstrap.js: -------------------------------------------------------------------------------- 1 | // Comment unrequired stuff 2 | 3 | // require("bootstrap/js/bootstrap-alert"); 4 | // require("bootstrap/js/bootstrap-button"); 5 | // require("bootstrap/js/bootstrap-carousel"); 6 | // require("bootstrap/js/bootstrap-collapse"); 7 | // require("bootstrap/js/bootstrap-dropdown"); 8 | // require("bootstrap/js/bootstrap-modal"); 9 | // require("bootstrap/js/bootstrap-tooltip"); 10 | // require("bootstrap/js/bootstrap-popover"); 11 | // require("bootstrap/js/bootstrap-scrollspy"); 12 | require("bootstrap/js/bootstrap-tab"); 13 | require("bootstrap/js/bootstrap-transition"); 14 | // require("bootstrap/js/bootstrap-typeahead"); -------------------------------------------------------------------------------- /app/pages.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | getPage: function(name, callback) { 3 | switch(name) { 4 | case "home": 5 | require([], function() { 6 | callback(require("./home.jade")); 7 | }); 8 | break; 9 | case "test1": 10 | require(["./test1"], function(item) { 11 | callback(item); 12 | }); 13 | break; 14 | case "test2": 15 | require.ensure([], function() { 16 | callback(require("./test2.jade")); 17 | }, "test2+3"); 18 | break; 19 | case "test3": 20 | require.ensure([], function() { 21 | callback(require("./test3.jade")); 22 | }, "test2+3"); 23 | break; 24 | default: callback(null); 25 | } 26 | } 27 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack webapp example 2 | 3 | For demonstration this app uses `npm` and `jam` package manager. 4 | 5 | Install and build this app with: 6 | 7 | ``` text 8 | # You need to have node.js installed 9 | npm install jamjs@0.2.x webpack@1.2.x webpack-dev-server@1.2.x -g 10 | 11 | cd example-app 12 | npm install 13 | jam install 14 | 15 | webpack -p --progress --colors --devtool sourcemap --hot 16 | webpack -p --progress --colors --devtool sourcemap --hot --config webpack-update1.config.js 17 | webpack -p --progress --colors --devtool sourcemap --hot --config webpack-update2.config.js 18 | index.html 19 | ``` 20 | 21 | NOTE: It's a production ready build, so it may take a while. 22 | 23 | For watching and debugging you can alternatively compile with: 24 | 25 | ``` text 26 | webpack -d --progress --colors --watch 27 | ``` 28 | 29 | Or use the development server: 30 | 31 | ``` text 32 | npm start 33 | # which is equal to 34 | webpack-dev-server -d --colors 35 | ``` 36 | 37 | And open [http://localhost:8080](http://localhost:8080). -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-app", 3 | "version": "0.11.0", 4 | "author": "Tobias Koppers @sokra", 5 | "description": "example web app for webpack", 6 | "dependencies": { 7 | "webpack": "1.2.x", 8 | "webpack-dev-server": "1.3.x", 9 | "bootstrap": "https://github.com/twbs/bootstrap/archive/v3.0.2.tar.gz", 10 | "jade-loader": "0.6.x", 11 | "json-loader": "0.5.x", 12 | "url-loader": "0.5.x", 13 | "file-loader": "0.5.x", 14 | "coffee-loader": "0.7.x", 15 | "jshint-loader": "0.6.x", 16 | "bundle-loader": "0.5.x", 17 | "style-loader": "0.6.x", 18 | "css-loader": "0.6.x", 19 | "less-loader": "0.7.x", 20 | "exports-loader": "0.6.x", 21 | "raw-loader": "0.5.x" 22 | }, 23 | "jam": { 24 | "dependencies": { 25 | "jquery": "1.9.1" 26 | } 27 | }, 28 | "licenses": [ 29 | { 30 | "type": "MIT", 31 | "url": "http://www.opensource.org/licenses/mit-license.php" 32 | } 33 | ], 34 | "scripts": { 35 | "start": "webpack-dev-server -d --colors" 36 | }, 37 | "engines": { 38 | "node": ">=0.1.30" 39 | }, 40 | "homepage": "http://github.com/webpack/webpack-example" 41 | } -------------------------------------------------------------------------------- /app/body.jade: -------------------------------------------------------------------------------- 1 | - require("bootstrap/less/bootstrap.less"); 2 | - require("bootstrap/js/dropdown.js"); 3 | - require("bootstrap/js/button.js"); 4 | - require("bootstrap/js/collapse.js"); 5 | - require("bootstrap/js/tab.js"); 6 | nav.navbar.navbar-default.navbar-top 7 | .container 8 | .navbar-header 9 | a.navbar-brand(href="#") webpack 10 | ul.nav.navbar-nav 11 | li: a(href="#").buttons.button-home Home 12 | li: a(href="#").buttons.button-test1 Test1 13 | li: a(href="#").buttons.button-test2 Test2 14 | li: a(href="#").buttons.button-test3 Test3 15 | .container 16 | .row 17 | .col-md-8 18 | .page-header 19 | h1 20 | | webpack 21 | small example app 22 | p Click the navigation items in the top bar to change right content. 23 | p The javascript for the different contents is loaded on demand by the webpack require.ensure method. 24 | p Watch the outgoing requests in your browsers dev tools. 25 | h2 source 26 | - var gh = "http://github.com/webpack/"; 27 | - var sourceExample = gh+"example-app/" 28 | - var sourceWebpack = gh+"webpack/" 29 | p: a(href=sourceExample) 30 | b 31 | | example-app on github 32 | p: a(href=sourceWebpack) 33 | b 34 | | webpack on github 35 | h2 Choosen sources 36 | #choosen-sources!= require("./loading.jade")() 37 | .col-md-4 38 | .page-header 39 | h1 status 40 | small loaded chunks 41 | ul.chunks 42 | li!= require("./chunk.jade")({chunk: 0}) 43 | if module.hot 44 | .page-header 45 | h1 HMR 46 | small hot module replacement 47 | p 48 | b Status: 49 | = " " 50 | span.hot-status idle 51 | p.hot-result 52 | button.btn.btn-default.hot-check Check for update 53 | button.btn.btn-default.hot-apply Apply update 54 | label.checkbox 55 | input.hot-strategy(type="checkbox", checked=true) 56 | | Replace current page 57 | .page-header 58 | h1 content 59 | small some test content 60 | .content -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require("webpack"); 2 | var path = require("path"); 3 | module.exports = { 4 | context: __dirname, 5 | entry: "./app/app.js", 6 | output: { 7 | path: path.join(__dirname, "assets"), 8 | publicPath: "assets/", // relative path for github pages 9 | filename: "main.js", // no hash in main.js because index.html is a static page 10 | chunkFilename: "[hash]/js/[id].js", 11 | hotUpdateMainFilename: "[hash]/update.json", 12 | hotUpdateChunkFilename: "[hash]/js/[id].update.js" 13 | }, 14 | recordsOutputPath: path.join(__dirname, "records.json"), 15 | module: { 16 | loaders: [ 17 | { test: /\.json$/, loader: "json-loader" }, 18 | { test: /\.coffee$/, loader: "coffee-loader" }, 19 | { test: /\.css$/, loader: "style-loader!css-loader" }, 20 | { test: /\.less$/, loader: "style-loader!css-loader!less-loader" }, 21 | { test: /\.jade$/, loader: "jade-loader?self" }, 22 | { test: /\.png$/, loader: "url-loader?prefix=img/&limit=5000" }, 23 | { test: /\.jpg$/, loader: "url-loader?prefix=img/&limit=5000" }, 24 | { test: /\.gif$/, loader: "url-loader?prefix=img/&limit=5000" }, 25 | { test: /\.woff$/, loader: "url-loader?prefix=font/&limit=5000" }, 26 | { test: /\.eot$/, loader: "file-loader?prefix=font/" }, 27 | { test: /\.ttf$/, loader: "file-loader?prefix=font/" }, 28 | { test: /\.svg$/, loader: "file-loader?prefix=font/" }, 29 | ], 30 | preLoaders: [ 31 | { 32 | test: /\.js$/, 33 | include: pathToRegExp(path.join(__dirname, "app")), 34 | loader: "jshint-loader" 35 | }, 36 | { 37 | // Simulate updates to showcase the hot module replacement 38 | test: pathToRegExp(path.join(__dirname, "app")), 39 | loader: path.join(__dirname, "fake-update.js") 40 | } 41 | ] 42 | }, 43 | resolve: { 44 | fallback: path.join(__dirname, "jam") 45 | }, 46 | amd: { jQuery: true }, 47 | plugins: [ 48 | new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 20 }) 49 | ], 50 | fakeUpdateVersion: 0 51 | }; 52 | function escapeRegExpString(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } 53 | function pathToRegExp(p) { return new RegExp("^" + escapeRegExpString(p)); } -------------------------------------------------------------------------------- /web_modules/mybootstrap/bootstrap.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v2.2.2 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | 11 | // CSS Reset 12 | @import "~bootstrap/less/reset.less"; 13 | 14 | // Core variables and mixins 15 | @import "~bootstrap/less/variables.less"; 16 | @import "variables.less"; // Modify this for custom colors, font-sizes, etc 17 | @import "~bootstrap/less/mixins.less"; 18 | 19 | // Grid system and page structure 20 | @import "~bootstrap/less/scaffolding.less"; 21 | @import "~bootstrap/less/grid.less"; 22 | @import "~bootstrap/less/layouts.less"; 23 | 24 | // Base CSS 25 | @import "~bootstrap/less/type.less"; 26 | @import "~bootstrap/less/code.less"; 27 | @import "~bootstrap/less/forms.less"; 28 | @import "~bootstrap/less/tables.less"; 29 | 30 | // Components: common 31 | @import "~bootstrap/less/sprites.less"; 32 | // @import "~bootstrap/less/dropdowns.less"; 33 | // @import "~bootstrap/less/wells.less"; 34 | @import "~bootstrap/less/component-animations.less"; 35 | // @import "~bootstrap/less/close.less"; 36 | 37 | // Components: Buttons & Alerts 38 | @import "~bootstrap/less/buttons.less"; 39 | @import "~bootstrap/less/button-groups.less"; 40 | @import "~bootstrap/less/alerts.less"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less 41 | 42 | // Components: Nav 43 | @import "~bootstrap/less/navs.less"; 44 | @import "~bootstrap/less/navbar.less"; 45 | // @import "~bootstrap/less/breadcrumbs.less"; 46 | // @import "~bootstrap/less/pagination.less"; 47 | @import "~bootstrap/less/pager.less"; 48 | 49 | // Components: Popovers 50 | // @import "~bootstrap/less/modals.less"; 51 | // @import "~bootstrap/less/tooltip.less"; 52 | // @import "~bootstrap/less/popovers.less"; 53 | 54 | // Components: Misc 55 | // @import "~bootstrap/less/thumbnails.less"; 56 | // @import "~bootstrap/less/media.less"; 57 | @import "~bootstrap/less/labels-badges.less"; 58 | @import "~bootstrap/less/progress-bars.less"; 59 | // @import "~bootstrap/less/accordion.less"; 60 | // @import "~bootstrap/less/carousel.less"; 61 | // @import "~bootstrap/less/hero-unit.less"; 62 | 63 | 64 | // Navbar extra padding 65 | body { 66 | padding-top: 70px; 67 | } 68 | 69 | 70 | // RESPONSIVE CLASSES 71 | // ------------------ 72 | 73 | @import "~bootstrap/less/responsive-utilities.less"; 74 | 75 | 76 | // MEDIA QUERIES 77 | // ------------------ 78 | 79 | // Large desktops 80 | @import "~bootstrap/less/responsive-1200px-min.less"; 81 | 82 | // Tablets to regular desktops 83 | @import "~bootstrap/less/responsive-768px-979px.less"; 84 | 85 | // Phones to portrait tablets and narrow desktops 86 | @import "~bootstrap/less/responsive-767px-max.less"; 87 | 88 | 89 | // RESPONSIVE NAVBAR 90 | // ------------------ 91 | 92 | // From 979px and below, show a button to toggle navbar contents 93 | @import "~bootstrap/less/responsive-navbar.less"; 94 | 95 | 96 | // Utility classes 97 | @import "~bootstrap/less/utilities.less"; // Has to be last to override when necessary 98 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | var $ = require("jquery"); 2 | 3 | require("./style.css"); 4 | var body = require("./body.jade")(); 5 | require("bundle!./sources.jade")(function(sources) { 6 | $(function() { 7 | $("#choosen-sources").html(sources()); 8 | }); 9 | }); 10 | $(function() { 11 | document.title = "webpack example-app"; 12 | $("body").html(body); 13 | $(".button-home").click(loadPage.bind(null, "home")); 14 | $(".button-test1").click(loadPage.bind(null, "test1")); 15 | $(".button-test2").click(loadPage.bind(null, "test2")); 16 | $(".button-test3").click(loadPage.bind(null, "test3")); 17 | if(module.hot) { 18 | module.hot.setApplyOnUpdate(false); 19 | var hotResult = $(".hot-result"); 20 | $(".hot-check").click(function() { 21 | try { 22 | module.hot.check(function(err, updatedModules) { 23 | if(err) return hotResult.text(err.toString()); 24 | if(updatedModules) hotResult.text("Updated modules: " + updatedModules.join(", ")); 25 | }); 26 | } catch(e) { hotResult.text(e.toString()); } 27 | }); 28 | $(".hot-apply").click(function() { 29 | try { 30 | module.hot.apply(function(err, renewedModules) { 31 | if(err) return hotResult.text(err.toString()); 32 | if(renewedModules) hotResult.text("Renewed modules: " + renewedModules.join(", ")); 33 | }); 34 | } catch(e) { hotResult.text(e.toString()); } 35 | }); 36 | module.hot.status(function(newStatus, oldStatus) { 37 | $(".hot-status").text(newStatus); 38 | }); 39 | } 40 | }); 41 | 42 | var isLoading = false; 43 | function loading(name) { 44 | if(isLoading) return true; 45 | if($(".button-"+name).parent().hasClass("active")) return true; 46 | isLoading = true; 47 | $(".buttons").parent().removeClass("active"); 48 | $(".button-"+name).parent().addClass("active"); 49 | $(".content").html(require("./loading.jade")); 50 | } 51 | 52 | function finished() { 53 | isLoading = false; 54 | } 55 | 56 | var pages = require("./pages"); 57 | 58 | var currentPage, currentPageName; 59 | function loadPage(name) { 60 | if(loading(name)) return; 61 | pages.getPage(name, function(item) { 62 | currentPageName = name; 63 | currentPage = item; 64 | finished(); 65 | if(typeof item === "function") { 66 | $(".content").html(item()); 67 | } else { 68 | $(".content").html(item.render()); 69 | item.start(); 70 | } 71 | }); 72 | return false; 73 | } 74 | 75 | if(module.hot) { 76 | module.hot.accept("./pages", function() { 77 | pages = require("./pages"); 78 | if(!$(".hot-strategy").prop("checked")) return; 79 | pages.getPage(currentPageName, function(item) { 80 | if(currentPage !== item) { 81 | loading(""); 82 | finished(); 83 | loadPage(currentPageName); 84 | } 85 | }); 86 | }); 87 | } 88 | 89 | // HACK to get chunk loading info 90 | var oldWebpackJsonp = window.webpackJsonp; 91 | var list = []; 92 | window.webpackJsonp = function(chunk, modules) { 93 | list.push(chunk); 94 | $(function() { 95 | append(); 96 | function append() { 97 | if($(".chunks").length === 0) { 98 | return setTimeout(append, 100); 99 | } 100 | if(list.length === 0) return; 101 | var chunk = list.shift(); 102 | var li = $("