Python bindings to webpack

Overview

Unmaintained

This project is unmaintained as it's a complicated solution to a simple problem.

You should try using either https://github.com/owais/django-webpack-loader or https://github.com/markfinger/python-webpack-manifest.

python-webpack

Build Status

Python bindings to webpack, via webpack-build

Documentation

Installation

pip install webpack

and install the JS dependencies with

npm install webpack webpack-build --save

Basic usage

python-webpack provides a high-level interface to a webpack-build server, enabling you to send build requests and receive an object describing the outcome.

To start the server, run

node_modules/.bin/webpack-build -s

Build requests should provide a path to a config file

from webpack.compiler import webpack

bundle = webpack('path/to/webpack.config.js')

The object returned can be passed directly into your template layer, enabling you to inject <script> and <link> elements into your page. The object provides two convenience methods, render_js and render_css which emit elements pointing to the generated assets.

API

webpack

webpack.compiler.webpack allows you to request data from the build server and the manifest reader.

The function requires one argument:

  • config_file - a path to a config file

The following optional arguments are also accepted:

  • context - a dictionary that provides context data that is passed to the config file. In most cases, the CONTEXT setting should be used instead as it allows you to set global defaults.
  • settings - a dictionary of keys which can be used to override settings. In most cases, you'll want to define settings in webpack.conf.settings, but it can be useful to provide overrides without monkey-patching.
  • manifest - an override for the default manifest reader. Should expose a read method.
  • compiler - an override for the default compiler - a webpack-build build server. Should expose a build method.

populate_manifest_file

webpack.manifest.populate_manifest_file generates a manifest file containing the contents of the MANIFEST setting, at the location specified by the MANIFEST_PATH setting.

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.

Config files

For webpack's config reference, refer to the official docs.

Config functions

webpack-build uses config files which export a function that returns config objects.

Using config functions provide a number of benefits:

  • functions can generate config objects which reflect the data sent from your python system
  • functions can generate multiple config objects, enabling your config files to act as templates
  • idempotent functions enable webpack-build to safely mutate the object without causing unintended side effects for successive builds

If you are already using config files which export an object, wrap the generation of the object in a function. For example:

// if you currently have
module.exports = {
  // ...
};

// rewrite it as
module.exports = function() {
  return {
    // ...
  };
};

To avoid unintended side-effects and inexplicable behaviour, ensure that your functions are both idempotent and always return an entirely new object. Extending mutable objects is an easy recipe for unhappiness.

Configuring the build

The data sent from python-webpack is available in your config function as the first argument, this enables you to generate a config object which reflects the state of your python system.

A typical use-case is injecting loaders that enable hot module replacement. For example, if you always want to use the babel-loader, but you only want react-hot-loader when hot module replacement is available:

module.exports = function(opts) {
  return {
    // ...
    module: {
      loaders: [
        {
          test: /\.jsx?$/,
      	  exclude: /(node_modules|bower_components)/,
      	  loader: (opts.hmr ? 'react-hot-loader!' : '') + 'babel-loader'
        }
      ]
    }
  };
};

The opts object provided to your functions is sent from python-webpack and follows webpack-build's build options.

Passing data to the config layer

You can send extra data to your config function by specifying the CONTEXT setting.

For example, if your CONTEXT setting looked like {'COMPRESS': True}, your function could use the COMPRESS flag to activate compression:

var webpack = require('webpack');

module.exports = function(opts) {
  var config = {
    // ...
  };
  
  if (opts.context.COMPRESS) {
    config.plugins.push(
      new webpack.optimize.UglifyJsPlugin()
    );
  }
  
  return config;
};

The CONTEXT setting defines global defaults, but you can also specify per-build values by providing the context argument to the webpack function.

Using context allows you to treat config functions as factories or templates, which can assist with reducing boilerplate and reusing config files across multiple contexts.

Using relative paths to config files

If you want to use relative paths to config files, you should specify the CONFIG_DIRS setting. When a relative path is provided, python-webpack looks sequentially through the directories until it finds a match.

Output paths

Be aware that the output.path property on config objects is overridden automatically, you can leave the setting undefined and webpack-build will redirect all output to your OUTPUT_ROOT.

To avoid file name collisions, builds are uniquely identified by hashing the options object sent to webpack-build. By default, your assets are placed in a directory equivalent to

os.path.join(OUTPUT_ROOT, 'webpack_assets', options_hash)

Build server

python-webpack relies on webpack-build to expose a high-level API around webpack such that it can be easily integrated into an external system. webpack-build's server is used to provide network access to the library's functionality.

A build server can be started with

node_modules/.bin/webpack-build -s

Hot module replacement

If you set the HMR setting to True, assets that are rendered on the client-side will open sockets to the build server and listen for change notifications. When the assets have been rebuilt, they will attempt to automatically update themselves within the browser. If they are unable to, they will log to the console indicating that you will need to refresh for the changes to be applied.

When HMR is True, webpack-build will automatically mutate config objects by:

  • adding a HMR client to the generated bundle
  • adding a HotModuleReplacementPlugin
  • defining output.publicPath
  • defining recordsPath

If you want to change your config for situations where the python layer has requested HMR, use the hmr flag on the options argument provided to config functions.

Overriding the build server

If you want to replace the build server with your own compiler, you can use the compiler argument on the webpack function. Composing a wrapper around webpack is one solution, for example:

from webpack.compiler import webpack

class MyCompiler:
    def build(config_file, *args, **kwargs):
        # ...
    
my_compiler = MyCompiler()
        
def my_webpack_function(*args, **kwargs):
    kwargs['compiler'] = my_compiler
    return webpack(*args, **kwargs)

Offline manifests

Offline manifests are JSON files which allow python-webpack to cache the output from webpack-build. Manifests are useful as an optimisation for production environments where you do not want a build server running.

Generating manifests

The easiest way to generate manifests is to define the MANIFEST and MANIFEST_PATH settings.

The MANIFEST setting should an iterable containing config files. For example:

(
    'path/to/some/webpack.config.js',
    'path/to/another/webpack.config.js',
)

The MANIFEST_PATH setting should be an absolute path to a file that the manifest will be written to and read from. For example:

os.path.join(os.getcwd(), 'webpack.manifest.json')

To generate a manifest, call the populate_manifest_file function. For example:

from webpack.manifest import populate_manifest_file

populate_manifest_file()

Once your manifest has been generated, the USE_MANIFEST setting is used to indicate that all data should be served from the manifest file. When USE_MANIFEST is True, any requests which are not contained within the manifest will cause errors to be raised.

Using context in a manifest

If you want to generate a manifest which contains specific context for each config file, set MANIFEST to a dictionary where the keys are config files and the values are iterables containing context objects. For example:

{
    # Build this file with a context
    'path/to/some/webpack.config.js': (
        {'foo': True},
    ),
    # Build this file without context
    'path/to/another/webpack.config.js': (),
    # Build this file twice, with two different contexts
    'path/to/yet/another/webpack.config.js': (
        {'foo': True},
        {'bar': True},
    ),
}

Note: if you call webpack with the USE_MANIFEST setting activated, you must specify the exact same context as defined in the MANIFEST setting.

Manifest keys

Manifest keys are the paths to the config files. If you want to deploy your manifests to another environment, you will likely need to use relative paths in coordination with the CONFIG_DIRS setting.

If have specified context for a config file, the keys are generated by appending a hash of the context to the path. Hence, you must specify the exact same context when calling webpack.

Overriding the manifest reader

The manifest handler that ships with webpack depends heavily on path resolution and context hashes to map requests to entries in the manifest. While this behaviour ensures an explicit and deterministic outcome, it can make it difficult to ensure portablity when deploying manifests to other locations or servers.

If you want to use your own manifest reader, one solution is to compose a wrapper function around webpack and override the manifest argument. For example:

from webpack.compiler import webpack

class MyManifest():
    def read(config_file, context):
        """This method is called by the compiler and should return an object"""
        # ...
        
my_manifest = MyManifest()
        
def my_webpack_function(*args, **kwargs):
    kwargs['manifest'] = my_manifest
    return webpack(*args, **kwargs)

Settings

Settings can be defined by calling webpack.conf.settings.configure with keyword arguments matching the setting that you want to define. For example:

from webpack.conf import settings

DEBUG = True

settings.configure(
    OUTPUT_ROOT='/path/to/your/output_root',
    STATIC_URL='/static/',
    WATCH=DEBUG,
    HMR=DEBUG,
)

Note: in a Django project, you should declare the settings as keys in a dictionary named WEBPACK within your settings file. python-webpack introspects Django's settings during startup and will configure itself from the WEBPACK dictionary.

OUTPUT_ROOT

An absolute path to the root directory that you use for static assets. For example, '/path/to/your/output_root'.

This setting must be defined.

Default: None

STATIC_URL

The root url that your static assets are served from. For example, '/static/'.

This setting must be defined.

Default: None

BUILD_URL

The url that build requests are sent to, this url should expose webpack-build.

Default: 'http://127.0.0.1:9009/build'

CONFIG_DIRS

A list of directories that will be used to resolve relative paths to config files.

Default: None

WATCH

A boolean flag which indicates that file watchers should be set to watch the assets's source files. When a change is detected, the files which have changed are recompiled in the background so that the assets are ready for the next request. Set this to True in development environments.

Default: False

HMR

A boolean flag indicating that webpack-build should inject a hmr runtime into the generated assets. Set this to True in development environments.

Default: False

CONTEXT

The default context provided to config functions - you can use this to pass data and flags down to your config functions. If defined, the setting should be a dictionary.

Default: None

CONFIG_DIRS

An iterable of directories that will be used to resolve relative paths to config files.

Default: None

MANIFEST

An object containing config files which are used to populate an offline manifest. Can be either an iterable of paths or a dictionary mapping paths to context objects.

Default: None

USE_MANIFEST

A flag indicating that python-webpack should use the manifest file, rather than opening connections to a build server.

Default: False

MANIFEST_PATH

An absolute path to the file used to store the manifest.

Default: None

MANIFEST_SETTINGS

A dictionary of values that are used during manifest generation to override python-webpack's settings.

Default:

{
	# Force the compiler to connect to the build server
	'USE_MANIFEST': False,
	# Ensure that the server does not add a hmr runtime
	'HMR': False,
}

CACHE

A flag indicating that webpack-build should maintain a persistent file cache. The file cache is used to improve response times for builds that have already been completed.

Default: True

CACHE_DIR

An override for the directory that webpack-build uses to store cache files.

Default: None

OUTPUT_DIR

The directory in OUTPUT_ROOT which webpack will output all assets to.

Default: 'webpack_assets'

AGGREGATE_TIMEOUT

The delay between the detection of a change in your source files and the start of a compiler's rebuild process.

Default: 200

POLL

If defined, this is a flag which indicates that watching compilers should poll for file changes, rather than relying on the OS for notifications.

If the compiler is not detecting changes to your files, setting this to True may resolve the problem.

Default: None

Django integration

Installation and configuration

The following configuration should be placed in your settings files to enable python-webpack to function with Django.

Add 'webpack' to your INSTALLED_APPS

INSTALLED_APPS = (
    # ...
    'webpack',
)

Add 'webpack.django_integration.WebpackFinder' to your STATICFILES_FINDERS

STATICFILES_FINDERS = (
    # ...
    'webpack.django_integration.WebpackFinder',
)

Configure webpack to respect your project's configuration

WEBPACK = {
    'OUTPUT_ROOT': '/path/to/your/output_root',
    'STATIC_URL': STATIC_URL,
    'WATCH': DEBUG,
    'HMR': DEBUG,
}

Template tags

A template tag is provided to integrate webpack at the template layer.

{% load webpack %}

{% webpack 'path/to/webpack.config.js' as bundle %}

{{ bundle.render_css|safe }}

{{ bundle.render_js|safe }}

Running the tests

pip install -r requirements.txt
npm install
python runtests.py
Owner
Mark Finger
Mark Finger
Peak.py - An awesome tool to keep you up about servers and websites status

An In-house API Powered GUI App To Check Server Stats, Generate Logs And More Features To Be Added Soon.

3 Feb 24, 2022
https://django-storages.readthedocs.io/

Installation Installing from PyPI is as easy as doing: pip install django-storages If you'd prefer to install from source (maybe there is a bugfix in

Josh Schneier 2.3k Jan 05, 2023
Manage your activities as well as possible.

ToDo-List Manage your activities as well as possible. Create workspace Create many boards for different topics Add unlimited tasks About me Full name:

Matin Ardestani 10 Sep 11, 2022
Pipeline is an asset packaging library for Django.

Pipeline Pipeline is an asset packaging library for Django, providing both CSS and JavaScript concatenation and compression, built-in JavaScript templ

Jazzband 1.4k Dec 26, 2022
Transparently use webpack with django

django-webpack-loader Read http://owaislone.org/blog/webpack-plus-reactjs-and-django/ for a detailed step by step guide on setting up webpack with dja

2.4k Jan 06, 2023
django-systemjs

Django SystemJS Django SystemJS brings the Javascript of tomorrow to Django, today. It leverages JSPM (https://jspm.io) to do the heavy lifting for yo

Sergei Maertens 42 Jan 11, 2022
A django compressor tool that bundles css, js files to a single css, js file with webpack and updates your html files with respective css, js file path.

django-webpacker's documentation: Introduction: django-webpacker is a django compressor tool which bundles css, js files to a single css, js file with

MicroPyramid 72 Aug 18, 2022
Compresses linked and inline javascript or CSS into a single cached file.

Django Compressor Django Compressor processes, combines and minifies linked and inline Javascript or CSS in a Django template into cacheable static fi

2.6k Jan 03, 2023
Compresses linked and inline javascript or CSS into a single cached file.

Django Compressor Django Compressor processes, combines and minifies linked and inline Javascript or CSS in a Django template into cacheable static fi

2.6k Jan 03, 2023
Python bindings to webpack

Unmaintained This project is unmaintained as it's a complicated solution to a simple problem. You should try using either https://github.com/owais/dja

Mark Finger 62 Apr 15, 2022
A faster collectstatic command.

Collectfast A faster collectstatic command. Features Efficiently decide what files to upload using cached checksums Parallel file uploads Supported St

Anton Agestam 405 Dec 27, 2022
Asset management for Python web development.

Asset management application for Python web development - use it to merge and compress your JavaScript and CSS files. Documentation: https://webassets

Michael Elsdörfer 912 Dec 25, 2022
Photonix Photo Manager - a photo management application based on web technologies

A modern, web-based photo management server. Run it on your home server and it will let you find the right photo from your collection on any device. Smart filtering is made possible by object recogni

Photonix Photo Manager 1.5k Jan 01, 2023
HTML minifier for Python frameworks (not only Django, despite the name).

django-htmlmin django-html is an HTML minifier for Python, with full support for HTML 5. It supports Django, Flask and many other Python web framework

Cobra Team 536 Dec 25, 2022