-
Notifications
You must be signed in to change notification settings - Fork 337
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
148 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import re | ||
|
||
from django.conf import settings | ||
|
||
|
||
__all__ = ('load_config',) | ||
|
||
|
||
DEFAULT_CONFIG = { | ||
'DEFAULT': { | ||
'CACHE': not settings.DEBUG, | ||
'BUNDLE_DIR_NAME': 'webpack_bundles/', | ||
'STATS_FILE': 'webpack-stats.json', | ||
# FIXME: Explore usage of fsnotify | ||
'POLL_INTERVAL': 0.1, | ||
'IGNORE': ['.+\.hot-update.js', '.+\.map'] | ||
} | ||
} | ||
|
||
user_config = getattr(settings, 'WEBPACK_LOADER', DEFAULT_CONFIG) | ||
|
||
user_config = dict( | ||
(name, dict(DEFAULT_CONFIG['DEFAULT'], **cfg)) | ||
for name, cfg in user_config.items() | ||
) | ||
|
||
for entry in user_config.values(): | ||
entry['ignores'] = [re.compile(I) for I in entry['IGNORE']] | ||
|
||
|
||
def load_config(name): | ||
return user_config[name] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
__all__ = ('WebpackError', 'WebpackLoaderBadStatsError') | ||
|
||
|
||
class WebpackError(Exception): | ||
pass | ||
|
||
|
||
class WebpackLoaderBadStatsError(Exception): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import json | ||
import time | ||
|
||
from django.conf import settings | ||
from django.contrib.staticfiles.storage import staticfiles_storage | ||
|
||
from .exceptions import WebpackError, WebpackLoaderBadStatsError | ||
from .config import load_config | ||
|
||
|
||
class WebpackLoader(object): | ||
_assets = {} | ||
|
||
def __init__(self, name='DEFAULT'): | ||
self.name = name | ||
self.config = load_config(self.name) | ||
|
||
def _load_assets(self): | ||
try: | ||
with open(self.config['STATS_FILE']) as f: | ||
return json.load(f) | ||
except IOError: | ||
raise IOError( | ||
'Error reading {0}. Are you sure webpack has generated ' | ||
'the file and the path is correct?'.format( | ||
self.config['STATS_FILE'])) | ||
|
||
def get_assets(self): | ||
if self.config['CACHE']: | ||
if self.name not in self._assets: | ||
self._assets[self.name] = self._load_assets() | ||
return self._assets[self.name] | ||
return self._load_assets() | ||
|
||
def filter_files(self, files): | ||
for F in files: | ||
filename = F['name'] | ||
ignore = ( | ||
any(regex.match(filename) for regex in self.config['ignores']) | ||
) | ||
if not ignore: | ||
relpath = '{0}{1}'.format( | ||
self.config['BUNDLE_DIR_NAME'], filename | ||
) | ||
F['url'] = staticfiles_storage.url(relpath) | ||
yield F | ||
|
||
|
||
def get_bundle(self, bundle_name): | ||
assets = self.get_assets() | ||
|
||
if settings.DEBUG: | ||
# poll when debugging and block request until bundle is compiled | ||
# TODO: support timeouts | ||
while assets['status'] == 'compiling': | ||
time.sleep(self.config['POLL_INTERVAL']) | ||
assets = self.get_assets() | ||
|
||
if assets.get('status') == 'done': | ||
files = assets['chunks'][bundle_name] | ||
return self.filter_files(files) | ||
|
||
elif assets.get('status') == 'error': | ||
if 'file' not in assets: | ||
assets['file'] = '' | ||
error = u""" | ||
{error} in {file} | ||
{message} | ||
""".format(**assets) | ||
raise WebpackError(error) | ||
|
||
raise WebpackLoaderBadStatsError( | ||
"The stats file does not contain valid data. Make sure " | ||
"webpack-bundle-tracker plugin is enabled and try to run " | ||
"webpack again.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,10 @@ | ||
import re | ||
import json | ||
import time | ||
from .loader import WebpackLoader | ||
|
||
from django.conf import settings | ||
from django.contrib.staticfiles.storage import staticfiles_storage | ||
|
||
_loaders = {} | ||
|
||
__all__ = ('get_assets', 'get_config', 'get_bundle',) | ||
|
||
|
||
DEFAULT_CONFIG = { | ||
'DEFAULT': { | ||
'BUNDLE_DIR_NAME': 'webpack_bundles/', | ||
'STATS_FILE': 'webpack-stats.json', | ||
# FIXME: Explore usage of fsnotify | ||
'POLL_INTERVAL': 0.1, | ||
'IGNORE': ['.+\.hot-update.js', '.+\.map'] | ||
} | ||
} | ||
|
||
|
||
user_config = getattr(settings, 'WEBPACK_LOADER', DEFAULT_CONFIG) | ||
|
||
user_config = dict( | ||
(name, dict(DEFAULT_CONFIG['DEFAULT'], **cfg)) | ||
for name, cfg in user_config.items() | ||
) | ||
|
||
for entry in user_config.values(): | ||
entry['ignores'] = [re.compile(I) for I in entry['IGNORE']] | ||
|
||
|
||
class WebpackError(Exception): | ||
pass | ||
|
||
|
||
class WebpackLoaderBadStatsError(Exception): | ||
pass | ||
|
||
|
||
def get_config(config_name): | ||
return user_config[config_name] | ||
|
||
|
||
def get_assets(config): | ||
try: | ||
with open(config['STATS_FILE']) as f: | ||
return json.load(f) | ||
except IOError: | ||
raise IOError( | ||
'Error reading {0}. Are you sure webpack has generated the file ' | ||
'and the path is correct?'.format(config['STATS_FILE'])) | ||
|
||
|
||
def filter_files(files, config): | ||
for F in files: | ||
filename = F['name'] | ||
ignore = any(regex.match(filename) for regex in config['ignores']) | ||
if not ignore: | ||
relpath = '{0}{1}'.format(config['BUNDLE_DIR_NAME'], filename) | ||
F['url'] = staticfiles_storage.url(relpath) | ||
yield F | ||
|
||
|
||
def get_bundle(bundle_name, config): | ||
assets = get_assets(config) | ||
|
||
if settings.DEBUG: | ||
# poll when debugging and block request until bundle is compiled | ||
# TODO: support timeouts | ||
while assets['status'] == 'compiling': | ||
time.sleep(config['POLL_INTERVAL']) | ||
assets = get_assets(config) | ||
|
||
if assets.get('status') == 'done': | ||
files = assets['chunks'][bundle_name] | ||
return filter_files(files, config) | ||
|
||
elif assets.get('status') == 'error': | ||
if 'file' not in assets: | ||
assets['file'] = '' | ||
error = u""" | ||
{error} in {file} | ||
{message} | ||
""".format(**assets) | ||
raise WebpackError(error) | ||
|
||
raise WebpackLoaderBadStatsError( | ||
"The stats file does not contain valid data. Make sure " | ||
"webpack-bundle-tracker plugin is enabled and try to run " | ||
"webpack again.") | ||
def get_loader(config_name): | ||
if config_name not in _loaders: | ||
_loaders[config_name] = WebpackLoader(config_name) | ||
return _loaders[config_name] |