Skip to content

SKalt/flask-webpack

 
 

Repository files navigation

Flask-Webpack

PyPI PyPI - License build status Code style: black

Manage frontend assets with Webpack, use them with flask

Webpack can produce hashed asset bundles ( like index.bundle.md5h4sh3d.js ). Flask-Webpack provides global jinja2 templates that look up your your hashed bundles by name in an asset map.

Installation

pip install flask-webpack # from pypi
# or
pip install git+https://github.com/nickjj/flask-webpack#egg=flask_webpack
Quickstart
  # webpack quickstart
  npm install --save-dev webpack webpack-cli webpack-manifest-plugin
  npm install --save lodash
  npx webpack \
    --output-filename [name].[chunkhash].js \
    --plugin webpack-manifest-plugin
  # looks for ./src/index.js for js assets, puts their compiled results in
  # ./dist/
// src/index.js
import _ from 'lodash'
console.log(_.join(['hello', 'webpack'], ' '))
# app.py
from flask import Flask
from flask_webpack import Webpack

webpack = Webpack()

app = Flask(__name__, static_folder="./dist")
webpack.init_app(app)
<!-- templates/index.html -->
{{ javascript_tag("index.js") }}

If you have a webpack entrypoint named index.js, the template will complile to

  <script src="index.h4sh3d.js"></script>

Now you can happily tell your frontend proxy to cache that hamburger image for an entire year. If you ever change the hamburger, the md5 will change but you do not need to change any of your templates because the asset_url_for tag knows how to look it up.

Global template tags

asset_url_for

Signature:

def assets_url_for(asset_name: str) -> jinja2.Markup: ...

resolves the hashed url for an asset name. Quotes not included.

javascript_tag

Signature:

def javascript_tag(
    *assets: str,
    unique: bool = True,
    attrs: Dict[str, Union[str, bool, int]] = {},
    **more_attrs: Union[str, bool, int]
) -> jinja2.Markup: ...

produces a <script> tag for each passed asset name. Each tag will have the HTML attributes described in the attrs and more_attrs dicts. If you need to duplicate a script, pass unique=False. If you need to use a reserved keyword as a HTML attribute on your script tag, (i.e. async, attrs, unique), put the desired prop in into the attrs dict.

stylesheet_tag

Signature:

def stylesheet_tag(
    *assets: str,
    unique: bool = True,
    attrs: Dict[str, Union[str, bool, int]] = {},
    **more_attrs: Union[str, bool, int]
) -> jinja2.Markup: ...

Writes out a <link rel="stylesheet"> tag for each passed asset. Each tag will have the HTML attributes described in the attrs and more_attrs dicts. If you need to duplicate a script, pass unique=False. If you need to use a reserved keyword as a HTML attribute on your script tag, (i.e. async, attrs, unique), put the desired prop in into the attrs dict.

You can view a complete working example in the test app.

There's also a blog post and short video explaining how to use this extension.

Building your asset map Flask-Webpack requires a JSON file `manifest.json` mapping the name of each of your bundles to its hashed equivalent. You can build this manifest file using webpack-manifest-plugin or manifest-revision-plugin
Configuration

Flask-Webpack resolves its configuration options with this order of priority:

  1. app.config[OPTION_NAME] trumps all
  2. a named option in the asset_map
  3. flask_webpack.Webpack(**{"option_name": option_value})

Here are the available configuration options:

(
  app.config["WEBPACK_MANIFEST_PATH"]
  or flask_webpack.Webpack(manifest_path=None)
)

default: None

Required: any valid path to a JSON asset map. An idiomatic location might be ./dist/manifest.json relative to your package.json.

(
  app.config["WEBPACK_ASSETS_URL"]
  or json_asset_map["publicPath"]
  or json_asset_map["public_path"]
  or flask_webpack.Webpack(assets_url=None)
)

default: "/"

Optional: A URL to prepend to your hashed asset names. In production, you can set this to your full domain name or CDN. In development, you might to point to a webpack-dev-server on another port. You can control this in python switching os.environ.get("FLASK_ENV") == "development" or by changing the value of the publicPath key in the generation of your asset map.

⚠️ warning: this does not automatically join the URL and your asset name. You must provide the joining /.

⚠️ warning: prepending a different asset_url/public_path to your assets may cause them not to work in production url(./relative/path/to/style/asset)

app.config.get("WEBPACK_MANIFEST_ASSETS_ONLY")

default: False

Optional: Assume the manifest file only contains the assets and not "publicPath" or "public_path". Otherwise, flask_webpack will handle both flat asset maps and asset maps with an "asset" key.

(
  app.config.get("WEBPACK_LOG_LEVEL")
  or 'DEBUG' if (
    os.environ.get("FLASK_DEBUG")
    or os.environ.get("FLASK_ENV") == 'development'
  )
  else 'ERROR'
)

default: "ERROR" Optional One of the .string python logging levels. The higher/more serious the level, more visible a missing asset will become.

error level missing asset yields
DEBUG <-- comment about missing asset -->
if level == "DEBUG":
return "<!-- {} -->".format(message.replace("-->", "")

|INFO|console.warn| |WARNING|console.error| |ERROR+|werkzeug.routing.BuildError|

Development
git clone https://github.com/nickjj/flask-webpack.git
cd flask-webpack

# having created a fresh virtualenv with a tool of your choice..
source activate flask-webpack
pip install -r requirements.txt
pip install -r devRequirements.txt

pre-push, please run:

flake8 .      # check the style
pip install . # check it builds
pyre check    # run the static type checker
pytest ./tests/unit.py ./tests/test_app_wp1/tests
pip uninstall flask-webpack

Contributors

About

A Flask extension to manage assets with Webpack.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 78.8%
  • JavaScript 19.7%
  • Other 1.5%