diff --git a/README.md b/README.md
index 5d8bb7db..2c52ad24 100644
--- a/README.md
+++ b/README.md
@@ -70,14 +70,16 @@ var BundleTracker = require('webpack-bundle-tracker');
module.exports = {
context: __dirname,
- entry: './assets/js/index',
+ entry: {
+ './assets/js/index',
+ './assets/exported_assets.js'
output: {
path: path.resolve('./assets/webpack_bundles/'),
filename: "[name]-[hash].js"
},
plugins: [
- new BundleTracker({filename: './webpack-stats.json'})
+ new BundleTracker({filename: './webpack-stats.json', assetsIdentifier: "exported_assets"})
]
}
```
@@ -92,6 +94,7 @@ WEBPACK_LOADER = {
'CACHE': not DEBUG,
'BUNDLE_DIR_NAME': 'webpack_bundles/', # must end with slash
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
+ 'ASSETS_IDENTIFIER': 'exported_assets',
'POLL_INTERVAL': 0.1,
'TIMEOUT': None,
'IGNORE': ['.+\.hot-update.js', '.+\.map']
@@ -136,7 +139,8 @@ If the bundle generates a file called `main-cf4b5fab6e00a404e0c7.js` and your ST
```python
WEBPACK_LOADER = {
'DEFAULT': {
- 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json')
+ 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
+ 'ASSETS_IDENTIFIER': 'exported_assets',
}
}
```
@@ -151,6 +155,25 @@ and your webpack config is located at `/home/src/webpack.config.js`, then the va
+#### ASSETS_IDENTIFIER
+```python
+WEBPACK_LOADER = {
+ 'DEFAULT': {
+ 'ASSETS_IDENTIFIER': 'exported_assets',
+ }
+}
+```
+
+`ASSETS_IDENTIFIER` is the key at which the assets will be generated in the `webpack-stats.json`. This is configurable on both ends, javascript being in charge of generating the right key while in python one should know where to read from. If you initialize `webpack-bundle-tracker` plugin like this
+
+```javacsript
+new BundleTracker({filename: "webpack-stats.json", assetsIdentifier: "exported_assets"});
+```
+
+you will get all your assets included through the exported_assets file on the key exported_assets in `webpack-stats.json`.
+
+
+
#### IGNORE
`IGNORE` is a list of regular expressions. If a file generated by webpack matches one of the expressions, the file will not be included in the template.
@@ -228,10 +251,12 @@ WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'bundles/',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
+ 'ASSETS_IDENTIFIER': 'exported_assets' # you can have the same name, hence different files
},
'DASHBOARD': {
'BUNDLE_DIR_NAME': 'dashboard_bundles/',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-dashboard.json'),
+ 'ASSETS_IDENTIFIER': 'exported_assets' # you can have the same name, hence different files
}
}
```
@@ -293,6 +318,25 @@ In the below example, `logo.png` can be any static asset shipped with any npm or
```
+### File paths from webpack's bundler
+
+Basically, if you need to access the public path of a file that has been bundled with webpack, you can easily do that with `webpack_asset_path`. To do so, you have to properly load them within the `exported_assets.js` file, that should be specified in the `webpack.config.js`. If that's done properly and `exported_assets.js` has
+
+```javascript
+require('./assets/image.png');
+```
+
+then you should easily refer the bundled assets as follows:
+
+```HTML+Django
+{% load webpack_asset_path from webpack_loader %}
+
+
+
+
+
+
## How to use in Production
diff --git a/tests/app/tests/test_webpack.py b/tests/app/tests/test_webpack.py
index 6945b820..e5252d5e 100644
--- a/tests/app/tests/test_webpack.py
+++ b/tests/app/tests/test_webpack.py
@@ -103,6 +103,22 @@ def test_code_spliting(self):
vendor = chunks['vendor']
self.assertEqual(vendor[0]['path'], os.path.join(settings.BASE_DIR, 'assets/bundles/vendor.js'))
+ def test_assets_extract(self):
+ self.compile_bundles('webpack.config.assets.js')
+
+ assets = get_loader(DEFAULT_CONFIG).get_assets()
+ self.assertEqual(assets['status'], 'done')
+ self.assertIn('exported_assets', assets)
+
+ assets = get_loader(DEFAULT_CONFIG).get_exported_asset('./test.png')
+ images_diff = call([
+ 'diff',
+ '/Users/devil/Contributions/django-webpack-loader/tests/assets/test.png',
+ assets['path']
+ ])
+ self.assertEqual(images_diff, 0)
+ self.assertEqual(assets['path'], os.path.join(settings.BASE_DIR, 'assets/bundles/' + assets['name']))
+
def test_templatetags(self):
self.compile_bundles('webpack.config.simple.js')
self.compile_bundles('webpack.config.app2.js')
@@ -217,7 +233,7 @@ def test_bad_status_in_production(self):
def test_request_blocking(self):
# FIXME: This will work 99% time but there is no garauntee with the
- # 4 second thing. Need a better way to detect if request was blocked on
+ # 4 second thing. Need a better way to detect if request was blocked or
# not.
wait_for = 3
view = TemplateView.as_view(template_name='home.html')
diff --git a/tests/assets/exported_assets.js b/tests/assets/exported_assets.js
new file mode 100644
index 00000000..007a8415
--- /dev/null
+++ b/tests/assets/exported_assets.js
@@ -0,0 +1 @@
+require('./test.png');
\ No newline at end of file
diff --git a/tests/assets/test.png b/tests/assets/test.png
new file mode 100644
index 00000000..c31c8e4e
Binary files /dev/null and b/tests/assets/test.png differ
diff --git a/tests/package.json b/tests/package.json
index f94fec28..5c9f4ef2 100644
--- a/tests/package.json
+++ b/tests/package.json
@@ -11,11 +11,12 @@
"babel-loader": "^5.1.3",
"css-loader": "^0.14.1",
"extract-text-webpack-plugin": "^0.8.0",
+ "file-loader": "^0.9.0",
"node-libs-browser": "^0.5.0",
"react": "^0.13.3",
"style-loader": "^0.12.3",
"webpack": "^1.9.8",
- "webpack-bundle-tracker": "0.0.8",
+ "webpack-bundle-tracker": "git+https://github.com/EmilLuta/webpack-bundle-tracker.git#5e1b73fa592aba396211c29c2f36686d403e51f4",
"webpack-dev-server": "^1.9.0",
"webpack-split-by-path": "0.0.1"
}
diff --git a/tests/webpack.config.assets.js b/tests/webpack.config.assets.js
new file mode 100644
index 00000000..c966b954
--- /dev/null
+++ b/tests/webpack.config.assets.js
@@ -0,0 +1,30 @@
+var path = require("path");
+var webpack = require('webpack');
+var BundleTracker = require('webpack-bundle-tracker');
+var ExtractTextPlugin = require("extract-text-webpack-plugin");
+
+
+module.exports = {
+ context: __dirname,
+ entry: {
+ exported_assets: './assets/exported_assets.js'
+ },
+ output: {
+ path: path.resolve('./assets/bundles/'),
+ filename: "[name].js"
+ },
+
+ plugins: [
+ new ExtractTextPlugin("styles.css"),
+ new BundleTracker({filename: "webpack-stats.json", assetsIdentifier: "exported_assets"}),
+ ],
+
+ module: {
+ loaders: [
+ // we pass the output from babel loader to react-hot loader
+ { test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel'], },
+ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") },
+ { test: /\.png$/, loader: "file-loader" }
+ ],
+ }
+}
diff --git a/webpack_loader/config.py b/webpack_loader/config.py
index 39ff2b1a..a65ad38a 100644
--- a/webpack_loader/config.py
+++ b/webpack_loader/config.py
@@ -11,6 +11,7 @@
'CACHE': not settings.DEBUG,
'BUNDLE_DIR_NAME': 'webpack_bundles/',
'STATS_FILE': 'webpack-stats.json',
+ 'ASSETS_IDENTIFIER': 'exported_assets',
# FIXME: Explore usage of fsnotify
'POLL_INTERVAL': 0.1,
'TIMEOUT': None,
diff --git a/webpack_loader/loader.py b/webpack_loader/loader.py
index faf5fb42..4cac9d84 100644
--- a/webpack_loader/loader.py
+++ b/webpack_loader/loader.py
@@ -30,32 +30,18 @@ def _load_assets(self):
'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_chunks(self, chunks):
- for chunk in chunks:
- ignore = any(regex.match(chunk['name'])
- for regex in self.config['ignores'])
- if not ignore:
- chunk['url'] = self.get_chunk_url(chunk)
- yield chunk
-
- def get_chunk_url(self, chunk):
- public_path = chunk.get('publicPath')
- if public_path:
- return public_path
-
- relpath = '{0}{1}'.format(
- self.config['BUNDLE_DIR_NAME'], chunk['name']
- )
- return staticfiles_storage.url(relpath)
-
- def get_bundle(self, bundle_name):
+ def _get_bundle(self, bucket, bundle_name):
+ """Collects the bundle withing each bucket based on its bundle name.
+
+ Arguments:
+ bucket:
+ The key on which you are extracting data from ('chunks', 'exported_assets')
+ bundle_name:
+ The name of the specific asset in the given bucket
+
+ Returns:
+ A data dictionary containing all the data for the given chunk/ asset.
+ """
assets = self.get_assets()
# poll when debugging and block request until bundle is compiled
@@ -77,10 +63,13 @@ def get_bundle(self, bundle_name):
)
if assets.get('status') == 'done':
- chunks = assets['chunks'].get(bundle_name, None)
+ chunks = assets[bucket].get(bundle_name)
if chunks is None:
raise WebpackBundleLookupError('Cannot resolve bundle {0}.'.format(bundle_name))
- return self.filter_chunks(chunks)
+ if bucket == self.config['ASSETS_IDENTIFIER']:
+ return chunks
+ else:
+ return self.filter_chunks(chunks)
elif assets.get('status') == 'error':
if 'file' not in assets:
@@ -97,3 +86,34 @@ def get_bundle(self, bundle_name):
"The stats file does not contain valid data. Make sure "
"webpack-bundle-tracker plugin is enabled and try to run "
"webpack again.")
+
+ 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_chunks(self, chunks):
+ for chunk in chunks:
+ ignore = any(regex.match(chunk['name'])
+ for regex in self.config['ignores'])
+ if not ignore:
+ chunk['url'] = self.get_chunk_url(chunk)
+ yield chunk
+
+ def get_chunk_url(self, chunk):
+ public_path = chunk.get('publicPath')
+ if public_path:
+ return public_path
+
+ relpath = '{0}{1}'.format(
+ self.config['BUNDLE_DIR_NAME'], chunk['name']
+ )
+ return staticfiles_storage.url(relpath)
+
+ def get_bundle(self, bundle_name):
+ return self._get_bundle('chunks', bundle_name)
+
+ def get_exported_asset(self, bundle_name):
+ return self._get_bundle(self.config['ASSETS_IDENTIFIER'], bundle_name)
diff --git a/webpack_loader/templatetags/webpack_loader.py b/webpack_loader/templatetags/webpack_loader.py
index 002294dd..0c94e008 100644
--- a/webpack_loader/templatetags/webpack_loader.py
+++ b/webpack_loader/templatetags/webpack_loader.py
@@ -28,16 +28,16 @@ def render_as_tags(bundle, attrs):
return mark_safe('\n'.join(tags))
-def _get_bundle(bundle_name, extension, config):
- bundle = get_loader(config).get_bundle(bundle_name)
+def _get_content(bundle_name, extension, config, loader_function):
+ content = getattr(get_loader(config), loader_function)(bundle_name)
if extension:
- bundle = filter_by_extension(bundle, extension)
- return bundle
+ content = filter_by_extension(content, extension)
+ return content
@register.simple_tag
def render_bundle(bundle_name, extension=None, config='DEFAULT', attrs=''):
- return render_as_tags(_get_bundle(bundle_name, extension, config), attrs)
+ return render_as_tags(_get_content(bundle_name, extension, config, 'get_bundle'), attrs)
@register.simple_tag
@@ -49,6 +49,9 @@ def webpack_static(asset_name, config='DEFAULT'):
asset_name
)
+@register.simple_tag
+def webpack_asset_path(bundle_name, config='DEFAULT'):
+ return _get_content(bundle_name, None, config, 'get_exported_asset')['publicPath']
assignment_tag = register.simple_tag if VERSION >= (1, 9) else register.assignment_tag
@assignment_tag
@@ -65,4 +68,4 @@ def get_files(bundle_name, extension=None, config='DEFAULT'):
:param config: (optional) the name of the configuration
:return: a list of matching chunks
"""
- return list(_get_bundle(bundle_name, extension, config))
+ return list(_get_content(bundle_name, extension, config, 'get_bundle'))