├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── examples ├── README.md ├── app │ ├── Comment.jsx │ ├── CommentBox.css │ ├── CommentBox.jsx │ ├── CommentForm.jsx │ ├── CommentList.jsx │ └── index.js ├── django │ ├── README.md │ ├── djangosite │ │ ├── __init__.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── example_app │ │ ├── __init__.py │ │ ├── templates │ │ │ └── example_app │ │ │ │ └── index.html │ │ └── urls.py │ ├── manage.py │ └── requirements.txt ├── example.webpack.js ├── flask │ ├── README.md │ ├── example.py │ ├── requirements.txt │ └── templates │ │ └── index.html └── package.json ├── package.json ├── requirements.txt ├── runtests.py ├── setup.py ├── tests ├── __init__.py ├── bundles │ ├── basic │ │ ├── app │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ └── webpack.config.js │ ├── cached │ │ ├── app │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ └── webpack.config.js │ ├── library │ │ ├── app │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ └── webpack.config.js │ ├── multiple_bundles │ │ ├── bundle_1 │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ ├── bundle_2 │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ └── webpack.config.js │ ├── multiple_entry │ │ ├── entry_1 │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ ├── entry_2 │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ ├── entry_3 │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ ├── entry_4 │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ ├── entry_5 │ │ │ ├── entry.js │ │ │ └── require_test.js │ │ └── webpack.config.js │ └── watched_source │ │ ├── app │ │ └── entry.js │ │ └── webpack.config.js ├── django_test_app │ ├── __init__.py │ ├── models.py │ ├── static │ │ └── django_test_app │ │ │ ├── entry.js │ │ │ └── require_test.js │ └── webpack.config.js ├── settings.py ├── test_bundles.py ├── test_django_integration.py ├── test_manifest.py ├── test_watching.py └── utils.py └── webpack ├── __init__.py ├── apps.py ├── build_server.py ├── bundle.py ├── compiler.py ├── conf.py ├── django_integration.py ├── exceptions.py ├── management ├── __init__.py └── commands │ ├── __init__.py │ └── webpack.py ├── manifest.py ├── options.py ├── resolver.py └── templatetags ├── __init__.py └── webpack.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | 56 | node_modules 57 | tests/__STATIC_ROOT__ 58 | .webpack_build_cache 59 | webpack_assets 60 | webpack_manifest.json 61 | db.sqlite3 62 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "2.7" 5 | - "3.4" 6 | 7 | env: 8 | - DJANGO_VERSION=1.7.7 TRAVIS_NODE_VERSION=5.3.0 9 | - DJANGO_VERSION=1.8 TRAVIS_NODE_VERSION=5.3.0 10 | 11 | install: 12 | - "rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION" 13 | - "npm install -g npm" 14 | - "npm install" 15 | - "pip install Django==$DJANGO_VERSION" 16 | - "pip install -r requirements.txt" 17 | 18 | script: python runtests.py 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change log 2 | ========== 3 | 4 | ### 6.0.0 (24/12/2015) 5 | 6 | Updated to support webpack-build@1.0.0. Note that webpack-build needs to be invoked with 7 | the `-s` flag to boot the server. For example, `node_modules/.bin/webpack-build -s`. 8 | 9 | 10 | ### 5.0.0 (12/7/2015) 11 | 12 | #### ADDITIONS 13 | 14 | **API** 15 | 16 | - Added the `populate_manifest_file` function 17 | 18 | **Settings** 19 | 20 | - Added the `HMR` setting, which toggles support for hot module replacement 21 | - Added the `USE_MANIFEST`, `MANIFEST`, `MANIFEST_PATH`, and `MANIFEST_SETTINGS` settings, which provide 22 | support for offline manifests 23 | - Added the `POLL` setting, which toggles the behaviour of webpack's file watcher in non-OSX environments 24 | - Added the `BUILD_URL` setting, which denotes a url to an endpoint exposing webpack-build 25 | - Added the `CONFIG_DIRS` setting, which enables lookups for relative paths to config files 26 | - Added the `CONTEXT` setting, which denotes the default context sent to config functions 27 | - Added the `CACHE` and `CACHE_DIR` settings, which control webpack-build's persistent file cache 28 | 29 | **Dependencies** 30 | 31 | - Added a dependency on the webpack-build JS package 32 | 33 | 34 | #### CHANGES 35 | 36 | **API** 37 | 38 | - `webpack.compiler.webpack` now accepts the signature `(config_file, [context], [settings], [manifest], [compiler])` 39 | 40 | **Settings** 41 | 42 | - `OUTPUT_DIR` now defaults to 'webpack_assets' 43 | - `BUNDLE_URL` is now `STATIC_URL` 44 | - `BUNDLE_ROOT` is now `STATIC_ROOT` 45 | - `WATCH_SOURCE_FILES` is now `WATCH` 46 | - `WATCH_DELAY` is now `AGGREGATE_TIMEOUT` 47 | 48 | 49 | #### REMOVED 50 | 51 | **API** 52 | 53 | - Removed the undocumented config file writer 54 | 55 | **Settings** 56 | 57 | - Removed the BUNDLE_DIR and CONFIG_DIR settings 58 | - Removed the WATCH_CONFIG_FILES setting. In practice it proved to introduced memory leaks leading to 59 | inevitable segmentation faults 60 | 61 | **Dependencies** 62 | 63 | - Removed the js-host dependency. 64 | - Removed the python-js-host dependency. 65 | - Removed the webpack-wrapper dependency. 66 | 67 | 68 | ### 4.1.1 (11/5/2015) 69 | 70 | - Python 3 fixes. 71 | 72 | ### 4.1.0 (11/5/2015) 73 | 74 | - Added a config file writer. 75 | - The directory specified by the BUNDLE_DIR setting is now nested in another directory specified by OUTPUT_DIR. 76 | - Added a setting CONFIG_DIR, which is nested in OUTPUT_DIR. 77 | 78 | ### 4.0.1 (4/5/2015) 79 | 80 | - Fixed an import error when configuring webpack from django. 81 | 82 | ### 4.0.0 (3/5/2015) 83 | 84 | - Renamed the project from django-webpack to python-webpack. 85 | - The django dependency is no longer required, comparable functionality is still preserved if you choose 86 | to use django. 87 | - The project is now imported as `webpack`, formerly it was `django_webpack`. 88 | - Ported the JS dependency from django-node to js-host. 89 | - The django staticfiles helpers are now located in `webpack.django_integration`. 90 | 91 | ### 3.1.0 (21/4/2015) 92 | 93 | - Bug fixes and improvements to the JS service 94 | 95 | ### 3.0.1 (1/4/2015) 96 | 97 | - The API is now oriented around config files, rather than programmatically generating config. 98 | - Updated django-node dependency to latest 99 | 100 | ### 2.1.2 (1/2/2015) 101 | 102 | - Updated django-node dependency to latest 103 | 104 | ### 2.1.1 (1/2/2015) 105 | 106 | - Updated django-node dependency to latest 107 | 108 | ### 2.1.0 (1/2/2015) 109 | 110 | - Python 3 fixes 111 | 112 | ### 2.0.0 (26/12/2014) 113 | 114 | - `django_webpack.webpack.bundle` is now available at `django_webpack.bundle`. 115 | - `django_webpack.models.WebpackBundle` is now available at `django_webpack.WebpackBundle`. 116 | 117 | ### 1.0.1 (14/12/2014) 118 | 119 | - Improving the test harness and updating django-node to the latest. 120 | 121 | ### 1.0.0 (14/12/2014) 122 | 123 | - The default value for `WebpackBundle.devtool` is now defined by a setting, DJANGO_WEBPACK['DEVTOOL'] 124 | - The default value for the `DJANGO_WEBPACK['CACHE']` setting is now toggled by `DJANGO_WEBPACK['DEBUG']`, rather than `django.conf.settings.DEBUG`. 125 | 126 | ### 0.2.0 (14/12/2014) 127 | 128 | - API changes: 129 | - `django_webpack.models.WebpackBundle.output` is now `django_webpack.models.WebpackBundle.path_to_output` 130 | - `django_webpack.models.WebpackBundle.get_output` is now `django_webpack.models.WebpackBundle.get_path_to_output` 131 | - Added an optional in-memory cache, triggered by the setting `DJANGO_REACT['CACHE']`. 132 | 133 | ### 0.1.0 (13/12/2014) 134 | 135 | - django_webpack.models.WebpackBundle can now be invoked directly. `WebpackBundle(entry='path/to/file.js')` 136 | 137 | ### 0.0.2 (11/12/2014) 138 | 139 | - Added a test suite. 140 | - `django_webpack.webpack.bundle` now offers trivial programmatic access to webpack. 141 | - Moved the Webpack configuration settings from settings.py to `django_webpack.models.WebpackBundle`. 142 | 143 | ### 0.0.1 (7/12/2014) 144 | 145 | - Initial release 146 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 Mark Finger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGELOG.md 2 | include LICENSE.txt 3 | include README.md 4 | include requirements.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Unmaintained 2 | ============ 3 | 4 | This project is unmaintained as it's a complicated solution to a simple problem. 5 | 6 | You should try using either https://github.com/owais/django-webpack-loader or https://github.com/markfinger/python-webpack-manifest. 7 | 8 | 9 | python-webpack 10 | ============== 11 | 12 | [![Build Status](https://travis-ci.org/markfinger/python-webpack.svg?branch=master)](https://travis-ci.org/markfinger/python-webpack) 13 | 14 | Python bindings to webpack, via [webpack-build](https://github.com/markfinger/webpack-build) 15 | 16 | 17 | Documentation 18 | ------------- 19 | 20 | - [Installation](#installation) 21 | - [Basic usage](#basic-usage) 22 | - [API](#api) 23 | - [webpack](#webpack) 24 | - [populate_manifest_file](#populate_manifest_file) 25 | - [Config files](#config-files) 26 | - [Config functions](#config-functions) 27 | - [Configuring the build](#configuring-the-build) 28 | - [Passing data to the config layer](#passing-data-to-the-config-layer) 29 | - [Using relative paths to config files](#using-relative-paths-to-config-files) 30 | - [Output paths](#output-paths) 31 | - [Build server](#build-server) 32 | - [Hot module replacement](#hot-module-replacement) 33 | - [Overriding the build server](#overriding-the-build-server) 34 | - [Offline manifests](#offline-manifests) 35 | - [Generating manifests](#generating-manifests) 36 | - [Using context in a manifest](#using-context-in-a-manifest) 37 | - [Manifest keys](#manifest-keys) 38 | - [Overriding the manifest reader](#overriding-the-manifest-reader) 39 | - [Settings](#settings) 40 | - [Django integration](#django-integration) 41 | - [Running the tests](#running-the-tests) 42 | 43 | 44 | Installation 45 | ------------ 46 | 47 | ``` 48 | pip install webpack 49 | ``` 50 | 51 | and install the JS dependencies with 52 | 53 | ``` 54 | npm install webpack webpack-build --save 55 | ``` 56 | 57 | 58 | Basic usage 59 | ----------- 60 | 61 | python-webpack provides a high-level interface to a 62 | [webpack-build server](https://github.com/markfinger/webpack-build#build-server), enabling you to send 63 | build requests and receive an object describing the outcome. 64 | 65 | To start the server, run 66 | 67 | ``` 68 | node_modules/.bin/webpack-build -s 69 | ``` 70 | 71 | Build requests should provide a path to a config file 72 | 73 | ```python 74 | from webpack.compiler import webpack 75 | 76 | bundle = webpack('path/to/webpack.config.js') 77 | ``` 78 | 79 | The object returned can be passed directly into your template layer, enabling you to inject <script> 80 | and <link> elements into your page. The object provides two convenience methods, `render_js` and 81 | `render_css` which emit elements pointing to the generated assets. 82 | 83 | 84 | API 85 | --- 86 | 87 | 88 | ### webpack 89 | 90 | `webpack.compiler.webpack` allows you to request data from the build server and the manifest reader. 91 | 92 | The function requires one argument: 93 | 94 | - `config_file` - a path to a config file 95 | 96 | The following optional arguments are also accepted: 97 | 98 | - `context` - a dictionary that provides context data that is passed to the config file. In most cases, the 99 | `CONTEXT` setting should be used instead as it allows you to set global defaults. 100 | - `settings` - a dictionary of keys which can be used to override settings. In most cases, you'll want to define 101 | settings in `webpack.conf.settings`, but it can be useful to provide overrides without monkey-patching. 102 | - `manifest` - an override for the default manifest reader. Should expose a `read` method. 103 | - `compiler` - an override for the default compiler - a webpack-build build server. Should expose a `build` method. 104 | 105 | 106 | ### populate_manifest_file 107 | 108 | `webpack.manifest.populate_manifest_file` generates a manifest file containing the contents of the `MANIFEST` 109 | setting, at the location specified by the `MANIFEST_PATH` setting. 110 | 111 | If you want to override settings during the build process - for example to provide a different `STATIC_URL` setting - the `MANIFEST_SETTINGS` setting can be used. 112 | 113 | 114 | Config files 115 | ------------ 116 | 117 | For webpack's config reference, refer to the [official docs](https://webpack.github.io/docs/configuration.html). 118 | 119 | 120 | ### Config functions 121 | 122 | webpack-build uses config files which export a function that returns config objects. 123 | 124 | Using config functions provide a number of benefits: 125 | - functions can generate config objects which reflect the data sent from your python system 126 | - functions can generate multiple config objects, enabling your config files to act as templates 127 | - idempotent functions enable webpack-build to safely mutate the object without causing unintended side 128 | effects for successive builds 129 | 130 | If you are already using config files which export an object, wrap the generation of the object in a 131 | function. For example: 132 | 133 | ```javascript 134 | // if you currently have 135 | module.exports = { 136 | // ... 137 | }; 138 | 139 | // rewrite it as 140 | module.exports = function() { 141 | return { 142 | // ... 143 | }; 144 | }; 145 | ``` 146 | 147 | To avoid unintended side-effects and inexplicable behaviour, ensure that your functions are both idempotent and 148 | always return an entirely new object. Extending mutable objects is an easy recipe for unhappiness. 149 | 150 | 151 | ### Configuring the build 152 | 153 | The data sent from python-webpack is available in your config function as the first argument, this enables 154 | you to generate a config object which reflects the state of your python system. 155 | 156 | A typical use-case is injecting loaders that enable hot module replacement. For example, if you always want 157 | to use the `babel-loader`, but you only want `react-hot-loader` when hot module replacement is available: 158 | 159 | ```javascript 160 | module.exports = function(opts) { 161 | return { 162 | // ... 163 | module: { 164 | loaders: [ 165 | { 166 | test: /\.jsx?$/, 167 | exclude: /(node_modules|bower_components)/, 168 | loader: (opts.hmr ? 'react-hot-loader!' : '') + 'babel-loader' 169 | } 170 | ] 171 | } 172 | }; 173 | }; 174 | ``` 175 | 176 | The `opts` object provided to your functions is sent from python-webpack and follows 177 | [webpack-build's build options](https://github.com/markfinger/webpack-build#build-options). 178 | 179 | 180 | ### Passing data to the config layer 181 | 182 | You can send extra data to your config function by specifying the `CONTEXT` setting. 183 | 184 | For example, if your `CONTEXT` setting looked like `{'COMPRESS': True}`, your function could use the 185 | `COMPRESS` flag to activate compression: 186 | 187 | ```javascript 188 | var webpack = require('webpack'); 189 | 190 | module.exports = function(opts) { 191 | var config = { 192 | // ... 193 | }; 194 | 195 | if (opts.context.COMPRESS) { 196 | config.plugins.push( 197 | new webpack.optimize.UglifyJsPlugin() 198 | ); 199 | } 200 | 201 | return config; 202 | }; 203 | ``` 204 | 205 | The `CONTEXT` setting defines global defaults, but you can also specify per-build values by providing 206 | the `context` argument to the `webpack` function. 207 | 208 | Using context allows you to treat config functions as factories or templates, which can assist with 209 | reducing boilerplate and reusing config files across multiple contexts. 210 | 211 | 212 | ### Using relative paths to config files 213 | 214 | If you want to use relative paths to config files, you should specify the `CONFIG_DIRS` setting. When 215 | a relative path is provided, python-webpack looks sequentially through the directories until it finds 216 | a match. 217 | 218 | 219 | ### Output paths 220 | 221 | Be aware that the `output.path` property on config objects is overridden automatically, you can leave 222 | the setting undefined and webpack-build will redirect all output to your `OUTPUT_ROOT`. 223 | 224 | To avoid file name collisions, builds are uniquely identified by hashing the options object sent to 225 | webpack-build. By default, your assets are placed in a directory equivalent to 226 | 227 | ```python 228 | os.path.join(OUTPUT_ROOT, 'webpack_assets', options_hash) 229 | ``` 230 | 231 | 232 | Build server 233 | ------------ 234 | 235 | python-webpack relies on [webpack-build](https://github.com/markfinger/webpack-build) to expose a high-level 236 | API around webpack such that it can be easily integrated into an external system. webpack-build's 237 | [server](https://github.com/markfinger/webpack-build#build-server) is used to provide network access 238 | to the library's functionality. 239 | 240 | A build server can be started with 241 | 242 | ``` 243 | node_modules/.bin/webpack-build -s 244 | ``` 245 | 246 | ### Hot module replacement 247 | 248 | If you set the `HMR` setting to True, assets that are rendered on the client-side will open sockets to the 249 | build server and listen for change notifications. When the assets have been rebuilt, they will attempt to 250 | automatically update themselves within the browser. If they are unable to, they will log to the console 251 | indicating that you will need to refresh for the changes to be applied. 252 | 253 | When `HMR` is True, webpack-build will automatically mutate config objects by: 254 | - adding a HMR client to the generated bundle 255 | - adding a `HotModuleReplacementPlugin` 256 | - defining `output.publicPath` 257 | - defining `recordsPath` 258 | 259 | If you want to change your config for situations where the python layer has requested HMR, use the `hmr` 260 | flag on the options argument provided to config functions. 261 | 262 | 263 | ### Overriding the build server 264 | 265 | If you want to replace the build server with your own compiler, you can use the `compiler` argument on the 266 | `webpack` function. Composing a wrapper around `webpack` is one solution, for example: 267 | 268 | ```python 269 | from webpack.compiler import webpack 270 | 271 | class MyCompiler: 272 | def build(config_file, *args, **kwargs): 273 | # ... 274 | 275 | my_compiler = MyCompiler() 276 | 277 | def my_webpack_function(*args, **kwargs): 278 | kwargs['compiler'] = my_compiler 279 | return webpack(*args, **kwargs) 280 | ``` 281 | 282 | 283 | Offline manifests 284 | ----------------- 285 | 286 | Offline manifests are JSON files which allow python-webpack to cache the output from webpack-build. Manifests 287 | are useful as an optimisation for production environments where you do not want a build server running. 288 | 289 | 290 | ### Generating manifests 291 | 292 | The easiest way to generate manifests is to define the `MANIFEST` and `MANIFEST_PATH` settings. 293 | 294 | The `MANIFEST` setting should an iterable containing config files. For example: 295 | 296 | ```python 297 | ( 298 | 'path/to/some/webpack.config.js', 299 | 'path/to/another/webpack.config.js', 300 | ) 301 | ``` 302 | 303 | The `MANIFEST_PATH` setting should be an absolute path to a file that the manifest will be written to and 304 | read from. For example: 305 | 306 | ```python 307 | os.path.join(os.getcwd(), 'webpack.manifest.json') 308 | ``` 309 | 310 | To generate a manifest, call the `populate_manifest_file` function. For example: 311 | 312 | ```python 313 | from webpack.manifest import populate_manifest_file 314 | 315 | populate_manifest_file() 316 | ``` 317 | 318 | Once your manifest has been generated, the `USE_MANIFEST` setting is used to indicate that all data should 319 | be served from the manifest file. When `USE_MANIFEST` is True, any requests which are not contained within 320 | the manifest will cause errors to be raised. 321 | 322 | 323 | ### Using context in a manifest 324 | 325 | If you want to generate a manifest which contains specific context for each config file, set `MANIFEST` to 326 | a dictionary where the keys are config files and the values are iterables containing context objects. For 327 | example: 328 | 329 | ```python 330 | { 331 | # Build this file with a context 332 | 'path/to/some/webpack.config.js': ( 333 | {'foo': True}, 334 | ), 335 | # Build this file without context 336 | 'path/to/another/webpack.config.js': (), 337 | # Build this file twice, with two different contexts 338 | 'path/to/yet/another/webpack.config.js': ( 339 | {'foo': True}, 340 | {'bar': True}, 341 | ), 342 | } 343 | ``` 344 | 345 | Note: if you call `webpack` with the `USE_MANIFEST` setting activated, you **must** specify the exact same 346 | context as defined in the `MANIFEST` setting. 347 | 348 | 349 | ### Manifest keys 350 | 351 | Manifest keys are the paths to the config files. If you want to deploy your manifests to another environment, 352 | you will likely need to use relative paths in coordination with the `CONFIG_DIRS` setting. 353 | 354 | If have specified context for a config file, the keys are generated by appending a hash of the context to the 355 | path. Hence, you **must** specify the exact same context when calling `webpack`. 356 | 357 | 358 | ### Overriding the manifest reader 359 | 360 | The manifest handler that ships with webpack depends heavily on path resolution and context hashes to map 361 | requests to entries in the manifest. While this behaviour ensures an explicit and deterministic outcome, it 362 | can make it difficult to ensure portablity when deploying manifests to other locations or servers. 363 | 364 | If you want to use your own manifest reader, one solution is to compose a wrapper function around `webpack` 365 | and override the `manifest` argument. For example: 366 | 367 | ```python 368 | from webpack.compiler import webpack 369 | 370 | class MyManifest(): 371 | def read(config_file, context): 372 | """This method is called by the compiler and should return an object""" 373 | # ... 374 | 375 | my_manifest = MyManifest() 376 | 377 | def my_webpack_function(*args, **kwargs): 378 | kwargs['manifest'] = my_manifest 379 | return webpack(*args, **kwargs) 380 | ``` 381 | 382 | 383 | Settings 384 | -------- 385 | 386 | Settings can be defined by calling `webpack.conf.settings.configure` with keyword arguments matching 387 | the setting that you want to define. For example: 388 | 389 | ```python 390 | from webpack.conf import settings 391 | 392 | DEBUG = True 393 | 394 | settings.configure( 395 | OUTPUT_ROOT='/path/to/your/output_root', 396 | STATIC_URL='/static/', 397 | WATCH=DEBUG, 398 | HMR=DEBUG, 399 | ) 400 | ``` 401 | 402 | Note: in a Django project, you should declare the settings as keys in a dictionary named `WEBPACK` within 403 | your settings file. python-webpack introspects Django's settings during startup and will configure itself 404 | from the `WEBPACK` dictionary. 405 | 406 | 407 | ### OUTPUT_ROOT 408 | 409 | An absolute path to the root directory that you use for static assets. For example, 410 | `'/path/to/your/output_root'`. 411 | 412 | This setting **must** be defined. 413 | 414 | Default: `None` 415 | 416 | 417 | ### STATIC_URL 418 | 419 | The root url that your static assets are served from. For example, `'/static/'`. 420 | 421 | This setting **must** be defined. 422 | 423 | Default: `None` 424 | 425 | 426 | ### BUILD_URL 427 | 428 | The url that build requests are sent to, this url should expose webpack-build. 429 | 430 | Default: `'http://127.0.0.1:9009/build'` 431 | 432 | 433 | ### CONFIG_DIRS 434 | 435 | A list of directories that will be used to resolve relative paths to config files. 436 | 437 | Default: `None` 438 | 439 | 440 | ### WATCH 441 | 442 | A boolean flag which indicates that file watchers should be set to watch the assets's source 443 | files. When a change is detected, the files which have changed are recompiled in the background 444 | so that the assets are ready for the next request. Set this to `True` in development environments. 445 | 446 | Default: `False` 447 | 448 | 449 | ### HMR 450 | 451 | A boolean flag indicating that webpack-build should inject a hmr runtime into the generated assets. 452 | Set this to `True` in development environments. 453 | 454 | Default: `False` 455 | 456 | 457 | ### CONTEXT 458 | 459 | The default context provided to config functions - you can use this to pass data and flags down to your 460 | config functions. If defined, the setting should be a dictionary. 461 | 462 | Default: `None` 463 | 464 | 465 | ### CONFIG_DIRS 466 | 467 | An iterable of directories that will be used to resolve relative paths to config files. 468 | 469 | Default: `None` 470 | 471 | 472 | ### MANIFEST 473 | 474 | An object containing config files which are used to populate an offline manifest. Can be either an iterable 475 | of paths or a dictionary mapping paths to context objects. 476 | 477 | Default: `None` 478 | 479 | 480 | ### USE_MANIFEST 481 | 482 | A flag indicating that python-webpack should use the manifest file, rather than opening connections to a 483 | build server. 484 | 485 | Default: `False` 486 | 487 | 488 | ### MANIFEST_PATH 489 | 490 | An absolute path to the file used to store the manifest. 491 | 492 | Default: `None` 493 | 494 | 495 | ### MANIFEST_SETTINGS 496 | 497 | A dictionary of values that are used during manifest generation to override python-webpack's settings. 498 | 499 | Default: 500 | ```python 501 | { 502 | # Force the compiler to connect to the build server 503 | 'USE_MANIFEST': False, 504 | # Ensure that the server does not add a hmr runtime 505 | 'HMR': False, 506 | } 507 | ``` 508 | 509 | 510 | ### CACHE 511 | 512 | A flag indicating that webpack-build should maintain a persistent file cache. The file cache is used to 513 | improve response times for builds that have already been completed. 514 | 515 | Default: `True` 516 | 517 | 518 | ### CACHE_DIR 519 | 520 | An override for the directory that webpack-build uses to store cache files. 521 | 522 | Default: `None` 523 | 524 | 525 | ### OUTPUT_DIR 526 | 527 | The directory in `OUTPUT_ROOT` which webpack will output all assets to. 528 | 529 | Default: `'webpack_assets'` 530 | 531 | 532 | ### AGGREGATE_TIMEOUT 533 | 534 | The delay between the detection of a change in your source files and the start of a compiler's 535 | rebuild process. 536 | 537 | Default: `200` 538 | 539 | 540 | ### POLL 541 | 542 | If defined, this is a flag which indicates that watching compilers should poll for file changes, rather 543 | than relying on the OS for notifications. 544 | 545 | If the compiler is not detecting changes to your files, setting this to `True` may resolve the problem. 546 | 547 | Default: `None` 548 | 549 | 550 | Django integration 551 | ------------------ 552 | 553 | ### Installation and configuration 554 | 555 | The following configuration should be placed in your settings files to enable python-webpack to function 556 | with Django. 557 | 558 | Add `'webpack'` to your `INSTALLED_APPS` 559 | 560 | ```python 561 | INSTALLED_APPS = ( 562 | # ... 563 | 'webpack', 564 | ) 565 | ``` 566 | 567 | Add `'webpack.django_integration.WebpackFinder'` to your `STATICFILES_FINDERS` 568 | 569 | ```python 570 | STATICFILES_FINDERS = ( 571 | # ... 572 | 'webpack.django_integration.WebpackFinder', 573 | ) 574 | ``` 575 | 576 | Configure webpack to respect your project's configuration 577 | 578 | ```python 579 | WEBPACK = { 580 | 'OUTPUT_ROOT': '/path/to/your/output_root', 581 | 'STATIC_URL': STATIC_URL, 582 | 'WATCH': DEBUG, 583 | 'HMR': DEBUG, 584 | } 585 | ``` 586 | 587 | 588 | ### Template tags 589 | 590 | A template tag is provided to integrate webpack at the template layer. 591 | 592 | ```html 593 | {% load webpack %} 594 | 595 | {% webpack 'path/to/webpack.config.js' as bundle %} 596 | 597 | {{ bundle.render_css|safe }} 598 | 599 | {{ bundle.render_js|safe }} 600 | ``` 601 | 602 | 603 | Running the tests 604 | ----------------- 605 | 606 | ```bash 607 | pip install -r requirements.txt 608 | npm install 609 | python runtests.py 610 | ``` 611 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | python-webpack examples 2 | ======================= 3 | 4 | Illustrates how to integrate webpack into a python project. Hot module replacement is activated by default, 5 | so your changes to the js and css files will be applied live. 6 | 7 | Before running any of the examples: 8 | 9 | ``` 10 | # install the dependencies 11 | npm install 12 | 13 | # start the build server 14 | npm start 15 | ``` 16 | 17 | An example Flask project lives in ./flask 18 | 19 | An example Django project lives in ./django 20 | 21 | Both projects use a shared JS codebase, which lives in ./app, and a shared config file, ./example.webpack.js -------------------------------------------------------------------------------- /examples/app/Comment.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default React.createClass({ 4 | render() { 5 | return ( 6 |
7 |

{this.props.author}

8 | {this.props.text} 9 |
10 | ); 11 | } 12 | }); -------------------------------------------------------------------------------- /examples/app/CommentBox.css: -------------------------------------------------------------------------------- 1 | h2 { 2 | border-bottom: 1px solid #eee; 3 | } 4 | 5 | form label { 6 | display: block; 7 | } 8 | 9 | form button { 10 | margin-left: 5px; 11 | } -------------------------------------------------------------------------------- /examples/app/CommentBox.jsx: -------------------------------------------------------------------------------- 1 | import 'bootstrap/dist/css/bootstrap.css'; 2 | import './CommentBox.css' 3 | import React from 'react'; 4 | import CommentList from './CommentList.jsx'; 5 | import CommentForm from './CommentForm.jsx'; 6 | 7 | export default React.createClass({ 8 | render() { 9 | return ( 10 |
11 | 12 | 13 |
14 | ); 15 | } 16 | }); -------------------------------------------------------------------------------- /examples/app/CommentForm.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default React.createClass({ 4 | handleSubmit(event) { 5 | event.preventDefault(); 6 | 7 | this.props.onCommentSubmit({ 8 | author: this.refs.author.getDOMNode().value.trim() || '...', 9 | text: this.refs.text.getDOMNode().value.trim() || '...' 10 | }); 11 | 12 | this.refs.author.getDOMNode().value = ''; 13 | this.refs.text.getDOMNode().value = ''; 14 | }, 15 | render() { 16 | return ( 17 |
18 |

Submit a comment

19 |
20 | 24 |
25 |
26 |