From 9812eb3b36f63b3d23ebc8b83845a0f6c0fcd233 Mon Sep 17 00:00:00 2001 From: Emil Luta Date: Wed, 7 Dec 2016 16:46:50 +0200 Subject: [PATCH 1/6] Added support for assets Assets may be accessible on the tag get_asset, therefore, anything that goes in webpack in exported-assets.js may be accessible here, by the same url linked into the js file retrieving the public_path of the file --- webpack_loader/config.py | 1 + webpack_loader/loader.py | 65 +++++++++++-------- webpack_loader/templatetags/webpack_loader.py | 15 +++-- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/webpack_loader/config.py b/webpack_loader/config.py index 39ff2b1a..7187a2a2 100644 --- a/webpack_loader/config.py +++ b/webpack_loader/config.py @@ -30,4 +30,5 @@ def load_config(name): + uc = user_config return user_config[name] diff --git a/webpack_loader/loader.py b/webpack_loader/loader.py index faf5fb42..de27db6f 100644 --- a/webpack_loader/loader.py +++ b/webpack_loader/loader.py @@ -30,32 +30,7 @@ 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): assets = self.get_assets() # poll when debugging and block request until bundle is compiled @@ -77,10 +52,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, None) if chunks is None: raise WebpackBundleLookupError('Cannot resolve bundle {0}.'.format(bundle_name)) - return self.filter_chunks(chunks) + if bucket == 'exported_assets': + return chunks + else: + return self.filter_chunks(chunks) elif assets.get('status') == 'error': if 'file' not in assets: @@ -97,3 +75,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('exported_assets', bundle_name) diff --git a/webpack_loader/templatetags/webpack_loader.py b/webpack_loader/templatetags/webpack_loader.py index 002294dd..2aa41a53 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 get_asset(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')) From 28555962aada19ebb74ada31571b1f5d426d43b5 Mon Sep 17 00:00:00 2001 From: Emil Luta Date: Wed, 7 Dec 2016 16:50:48 +0200 Subject: [PATCH 2/6] Cleanup --- webpack_loader/config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/webpack_loader/config.py b/webpack_loader/config.py index 7187a2a2..39ff2b1a 100644 --- a/webpack_loader/config.py +++ b/webpack_loader/config.py @@ -30,5 +30,4 @@ def load_config(name): - uc = user_config return user_config[name] From 32a730ea2d21c1361b46eaf5ff3f943f3b5fb714 Mon Sep 17 00:00:00 2001 From: Emil Luta Date: Mon, 12 Dec 2016 10:22:24 +0200 Subject: [PATCH 3/6] Added general support for the assets identifier --- webpack_loader/config.py | 1 + webpack_loader/loader.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) 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 de27db6f..0244c29e 100644 --- a/webpack_loader/loader.py +++ b/webpack_loader/loader.py @@ -55,7 +55,7 @@ def _get_bundle(self, bucket, bundle_name): chunks = assets[bucket].get(bundle_name, None) if chunks is None: raise WebpackBundleLookupError('Cannot resolve bundle {0}.'.format(bundle_name)) - if bucket == 'exported_assets': + if bucket == self.config['ASSETS_IDENTIFIER']: return chunks else: return self.filter_chunks(chunks) @@ -105,4 +105,4 @@ def get_bundle(self, bundle_name): return self._get_bundle('chunks', bundle_name) def get_exported_asset(self, bundle_name): - return self._get_bundle('exported_assets', bundle_name) + return self._get_bundle(self.config['ASSETS_IDENTIFIER'], bundle_name) From b266a74bc8f971043d7e820cde451e83f6fcc2a5 Mon Sep 17 00:00:00 2001 From: Emil Luta Date: Mon, 12 Dec 2016 12:55:12 +0200 Subject: [PATCH 4/6] Updated readme and changed tag name Updated the readme with use information based on the webpack_static_path and furthermore, changed static_assets -> webpack_static_path. --- README.md | 50 +++++++++++++++++-- webpack_loader/templatetags/webpack_loader.py | 2 +- 2 files changed, 48 insertions(+), 4 deletions(-) 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/webpack_loader/templatetags/webpack_loader.py b/webpack_loader/templatetags/webpack_loader.py index 2aa41a53..0c94e008 100644 --- a/webpack_loader/templatetags/webpack_loader.py +++ b/webpack_loader/templatetags/webpack_loader.py @@ -50,7 +50,7 @@ def webpack_static(asset_name, config='DEFAULT'): ) @register.simple_tag -def get_asset(bundle_name, config='DEFAULT'): +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 From 3ed8aa6945484f093066bbb36ea1b619d1e6fcbe Mon Sep 17 00:00:00 2001 From: Emil Luta Date: Mon, 12 Dec 2016 14:15:55 +0200 Subject: [PATCH 5/6] Cleanup --- webpack_loader/loader.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/webpack_loader/loader.py b/webpack_loader/loader.py index 0244c29e..4cac9d84 100644 --- a/webpack_loader/loader.py +++ b/webpack_loader/loader.py @@ -31,6 +31,17 @@ def _load_assets(self): self.config['STATS_FILE'])) 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 @@ -52,7 +63,7 @@ def _get_bundle(self, bucket, bundle_name): ) if assets.get('status') == 'done': - chunks = assets[bucket].get(bundle_name, None) + chunks = assets[bucket].get(bundle_name) if chunks is None: raise WebpackBundleLookupError('Cannot resolve bundle {0}.'.format(bundle_name)) if bucket == self.config['ASSETS_IDENTIFIER']: From b451ed0d347b3585962f88626686a9bd9ab64f47 Mon Sep 17 00:00:00 2001 From: Emil Luta Date: Mon, 12 Dec 2016 16:41:26 +0200 Subject: [PATCH 6/6] Added tests for get_exported_assets --- tests/app/tests/test_webpack.py | 18 +++++++++++++++++- tests/assets/exported_assets.js | 1 + tests/assets/test.png | Bin 0 -> 11728 bytes tests/package.json | 3 ++- tests/webpack.config.assets.js | 30 ++++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 tests/assets/exported_assets.js create mode 100644 tests/assets/test.png create mode 100644 tests/webpack.config.assets.js 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 0000000000000000000000000000000000000000..c31c8e4e4fdc3fb9d99c2b45c29d6ea1c5fd911a GIT binary patch literal 11728 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 ZpeJ2MsYz4;v|PjVbxbb4)Vg~6e*h#B17ZLG literal 0 HcmV?d00001 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" } + ], + } +}