Fixed #32319 -- Added ES module support to ManifestStaticFilesStorage.

This commit is contained in:
Gildardo Adrian Maravilla Jacome 2021-01-04 20:28:01 -06:00 committed by Mariusz Felisiak
parent 781b44240a
commit 91e21836f6
8 changed files with 96 additions and 0 deletions

View File

@ -57,6 +57,15 @@ class HashedFilesMixin:
r'(?P<matched>)^(//# (?-i:sourceMappingURL)=(?P<url>.*))$', r'(?P<matched>)^(//# (?-i:sourceMappingURL)=(?P<url>.*))$',
'//# sourceMappingURL=%(url)s', '//# sourceMappingURL=%(url)s',
), ),
(
r"""(?P<matched>import\s+(?s:(?P<imports>.*?))\s*from\s*["'](?P<url>.*?)["'])""",
'import %(imports)s from "%(url)s"',
),
(
r"""(?P<matched>export\s+(?s:(?P<exports>.*?))\s*from\s*["'](?P<url>.*?)["'])""",
'export %(exports)s from "%(url)s"',
),
(r"""(?P<matched>import\(["'](?P<url>.*?)["']\))""", 'import("%(url)s")'),
)), )),
) )
keep_intermediate_files = True keep_intermediate_files = True

View File

@ -295,6 +295,8 @@ method). The regular expressions used to find those paths
* The `@import`_ rule and `url()`_ statement of `Cascading Style Sheets`_. * The `@import`_ rule and `url()`_ statement of `Cascading Style Sheets`_.
* The `source map`_ comment in JavaScript. * The `source map`_ comment in JavaScript.
* The `modules import`_ in JavaScript.
* The `modules aggregation`_ in JavaScript.
For example, the ``'css/styles.css'`` file with this content: For example, the ``'css/styles.css'`` file with this content:
@ -315,6 +317,9 @@ For example, the ``'css/styles.css'`` file with this content:
Support for finding paths in the source map comments was added. Support for finding paths in the source map comments was added.
Support for finding paths to JavaScript modules in ``import`` and
``export`` statements was added.
.. attribute:: storage.ManifestStaticFilesStorage.max_post_process_passes .. attribute:: storage.ManifestStaticFilesStorage.max_post_process_passes
Since static files might reference other static files that need to have their Since static files might reference other static files that need to have their
@ -368,6 +373,8 @@ hashing algorithm.
.. _`url()`: https://www.w3.org/TR/CSS2/syndata.html#uri .. _`url()`: https://www.w3.org/TR/CSS2/syndata.html#uri
.. _`Cascading Style Sheets`: https://www.w3.org/Style/CSS/ .. _`Cascading Style Sheets`: https://www.w3.org/Style/CSS/
.. _`source map`: https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map .. _`source map`: https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map
.. _`modules import`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#importing_features_into_your_script
.. _`modules aggregation`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#aggregating_modules
``ManifestFilesMixin`` ``ManifestFilesMixin``
---------------------- ----------------------

View File

@ -149,6 +149,10 @@ Minor features
replaces paths to JavaScript source map references with their hashed replaces paths to JavaScript source map references with their hashed
counterparts. counterparts.
* :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now
replaces paths to JavaScript modules in ``import`` and ``export`` statements
with their hashed counterparts.
:mod:`django.contrib.syndication` :mod:`django.contrib.syndication`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,2 @@
const rootConst = "root";
export default rootConst;

View File

@ -0,0 +1,22 @@
// Static imports.
import rootConst from "/static/absolute_root.js";
import testConst from "./module_test.js";
import * as NewModule from "./module_test.js";
import { testConst as alias } from "./module_test.js";
import { firstConst, secondConst } from "./module_test.js";
import {
firstVar as firstVarAlias,
secondVar as secondVarAlias
} from "./module_test.js";
import relativeModule from "../nested/js/nested.js";
// Dynamic imports.
const dynamicModule = import("./module_test.js");
// Modules exports to aggregate modules.
export * from "./module_test.js";
export { testConst } from "./module_test.js";
export {
firstVar as firstVarAlias,
secondVar as secondVarAlias
} from "./module_test.js";

View File

@ -0,0 +1,5 @@
export const testConst = "test";
export const firstConst = "first";
export const secondConst = "second";
export var firstVar = "test_1";
export var SecondVar = "test_2";

View File

@ -0,0 +1 @@
export default null;

View File

@ -159,6 +159,52 @@ class TestHashedFiles:
self.assertIn(b"https://", relfile.read()) self.assertIn(b"https://", relfile.read())
self.assertPostCondition() self.assertPostCondition()
def test_module_import(self):
relpath = self.hashed_file_path('cached/module.js')
self.assertEqual(relpath, 'cached/module.91b9cf9935da.js')
tests = [
# Relative imports.
b'import testConst from "./module_test.d489af3cf882.js";',
b'import relativeModule from "../nested/js/nested.866475c46bb4.js";',
b'import { firstConst, secondConst } from "./module_test.d489af3cf882.js";',
# Absolute import.
b'import rootConst from "/static/absolute_root.5586327fe78c.js";',
# Dynamic import.
b'const dynamicModule = import("./module_test.d489af3cf882.js");',
# Creating a module object.
b'import * as NewModule from "./module_test.d489af3cf882.js";',
# Aliases.
b'import { testConst as alias } from "./module_test.d489af3cf882.js";',
b'import {\n'
b' firstVar as firstVarAlias,\n'
b' secondVar as secondVarAlias\n'
b'} from "./module_test.d489af3cf882.js";',
]
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
for module_import in tests:
with self.subTest(module_import=module_import):
self.assertIn(module_import, content)
self.assertPostCondition()
def test_aggregating_modules(self):
relpath = self.hashed_file_path('cached/module.js')
self.assertEqual(relpath, 'cached/module.91b9cf9935da.js')
tests = [
b'export * from "./module_test.d489af3cf882.js";',
b'export { testConst } from "./module_test.d489af3cf882.js";',
b'export {\n'
b' firstVar as firstVarAlias,\n'
b' secondVar as secondVarAlias\n'
b'} from "./module_test.d489af3cf882.js";',
]
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
for module_import in tests:
with self.subTest(module_import=module_import):
self.assertIn(module_import, content)
self.assertPostCondition()
@override_settings( @override_settings(
STATICFILES_DIRS=[os.path.join(TEST_ROOT, 'project', 'loop')], STATICFILES_DIRS=[os.path.join(TEST_ROOT, 'project', 'loop')],
STATICFILES_FINDERS=['django.contrib.staticfiles.finders.FileSystemFinder'], STATICFILES_FINDERS=['django.contrib.staticfiles.finders.FileSystemFinder'],