mirror of
https://github.com/django/django.git
synced 2025-03-12 02:12:38 +00:00
Fixed #34322 -- Made ES module support to ManifestStaticFilesStorage optional.
Co-authored-by: Author: Claude Paroz <claude@2xlibre.net>
This commit is contained in:
parent
2ffa815c73
commit
e10c1688f9
@ -47,6 +47,34 @@ class StaticFilesStorage(FileSystemStorage):
|
|||||||
class HashedFilesMixin:
|
class HashedFilesMixin:
|
||||||
default_template = """url("%(url)s")"""
|
default_template = """url("%(url)s")"""
|
||||||
max_post_process_passes = 5
|
max_post_process_passes = 5
|
||||||
|
support_js_module_import_aggregation = False
|
||||||
|
_js_module_import_aggregation_patterns = (
|
||||||
|
"*.js",
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
r"""(?P<matched>import(?s:(?P<import>[\s\{].*?))"""
|
||||||
|
r"""\s*from\s*['"](?P<url>[\.\/].*?)["']\s*;)"""
|
||||||
|
),
|
||||||
|
"""import%(import)s from "%(url)s";""",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(
|
||||||
|
r"""(?P<matched>export(?s:(?P<exports>[\s\{].*?))"""
|
||||||
|
r"""\s*from\s*["'](?P<url>[\.\/].*?)["']\s*;)"""
|
||||||
|
),
|
||||||
|
"""export%(exports)s from "%(url)s";""",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r"""(?P<matched>import\s*['"](?P<url>[\.\/].*?)["']\s*;)""",
|
||||||
|
"""import"%(url)s";""",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r"""(?P<matched>import\(["'](?P<url>.*?)["']\))""",
|
||||||
|
"""import("%(url)s")""",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
patterns = (
|
patterns = (
|
||||||
(
|
(
|
||||||
"*.css",
|
"*.css",
|
||||||
@ -72,34 +100,14 @@ class HashedFilesMixin:
|
|||||||
r"(?m)(?P<matched>)^(//# (?-i:sourceMappingURL)=(?P<url>.*))$",
|
r"(?m)(?P<matched>)^(//# (?-i:sourceMappingURL)=(?P<url>.*))$",
|
||||||
"//# sourceMappingURL=%(url)s",
|
"//# sourceMappingURL=%(url)s",
|
||||||
),
|
),
|
||||||
(
|
|
||||||
(
|
|
||||||
r"""(?P<matched>import(?s:(?P<import>[\s\{].*?))"""
|
|
||||||
r"""\s*from\s*['"](?P<url>[\.\/].*?)["']\s*;)"""
|
|
||||||
),
|
|
||||||
"""import%(import)s from "%(url)s";""",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
(
|
|
||||||
r"""(?P<matched>export(?s:(?P<exports>[\s\{].*?))"""
|
|
||||||
r"""\s*from\s*["'](?P<url>[\.\/].*?)["']\s*;)"""
|
|
||||||
),
|
|
||||||
"""export%(exports)s from "%(url)s";""",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
r"""(?P<matched>import\s*['"](?P<url>[\.\/].*?)["']\s*;)""",
|
|
||||||
"""import"%(url)s";""",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
r"""(?P<matched>import\(["'](?P<url>.*?)["']\))""",
|
|
||||||
"""import("%(url)s")""",
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
keep_intermediate_files = True
|
keep_intermediate_files = True
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
if self.support_js_module_import_aggregation:
|
||||||
|
self.patterns += (self._js_module_import_aggregation_patterns,)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._patterns = {}
|
self._patterns = {}
|
||||||
self.hashed_files = {}
|
self.hashed_files = {}
|
||||||
|
@ -300,6 +300,11 @@ 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`_.
|
||||||
* `Source map`_ comments in CSS and JavaScript files.
|
* `Source map`_ comments in CSS and JavaScript files.
|
||||||
|
|
||||||
|
Subclass ``ManifestStaticFilesStorage`` and set the
|
||||||
|
``support_js_module_import_aggregation`` attribute to ``True``, if you want to
|
||||||
|
use the experimental regular expressions to cover:
|
||||||
|
|
||||||
* The `modules import`_ in JavaScript.
|
* The `modules import`_ in JavaScript.
|
||||||
* The `modules aggregation`_ in JavaScript.
|
* The `modules aggregation`_ in JavaScript.
|
||||||
|
|
||||||
@ -342,8 +347,8 @@ argument. For example::
|
|||||||
|
|
||||||
.. versionchanged:: 4.2
|
.. versionchanged:: 4.2
|
||||||
|
|
||||||
Support for finding paths to JavaScript modules in ``import`` and
|
Experimental optional support for finding paths to JavaScript modules in
|
||||||
``export`` statements was added.
|
``import`` and ``export`` statements was added.
|
||||||
|
|
||||||
.. attribute:: storage.ManifestStaticFilesStorage.manifest_hash
|
.. attribute:: storage.ManifestStaticFilesStorage.manifest_hash
|
||||||
|
|
||||||
|
@ -202,8 +202,10 @@ Minor features
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now
|
* :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now
|
||||||
replaces paths to JavaScript modules in ``import`` and ``export`` statements
|
has experimental support for replacing paths to JavaScript modules in
|
||||||
with their hashed counterparts.
|
``import`` and ``export`` statements with their hashed counterparts. If you
|
||||||
|
want to try it, subclass ``ManifestStaticFilesStorage`` and set the
|
||||||
|
``support_js_module_import_aggregation`` attribute to ``True``.
|
||||||
|
|
||||||
* The new :attr:`.ManifestStaticFilesStorage.manifest_hash` attribute provides
|
* The new :attr:`.ManifestStaticFilesStorage.manifest_hash` attribute provides
|
||||||
a hash over all files in the manifest and changes whenever one of the files
|
a hash over all files in the manifest and changes whenever one of the files
|
||||||
|
@ -177,52 +177,6 @@ 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.55fd6938fbc5.js")
|
|
||||||
tests = [
|
|
||||||
# Relative imports.
|
|
||||||
b'import testConst from "./module_test.477bbebe77f0.js";',
|
|
||||||
b'import relativeModule from "../nested/js/nested.866475c46bb4.js";',
|
|
||||||
b'import { firstConst, secondConst } from "./module_test.477bbebe77f0.js";',
|
|
||||||
# Absolute import.
|
|
||||||
b'import rootConst from "/static/absolute_root.5586327fe78c.js";',
|
|
||||||
# Dynamic import.
|
|
||||||
b'const dynamicModule = import("./module_test.477bbebe77f0.js");',
|
|
||||||
# Creating a module object.
|
|
||||||
b'import * as NewModule from "./module_test.477bbebe77f0.js";',
|
|
||||||
# Aliases.
|
|
||||||
b'import { testConst as alias } from "./module_test.477bbebe77f0.js";',
|
|
||||||
b"import {\n"
|
|
||||||
b" firstVar1 as firstVarAlias,\n"
|
|
||||||
b" $second_var_2 as secondVarAlias\n"
|
|
||||||
b'} from "./module_test.477bbebe77f0.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.55fd6938fbc5.js")
|
|
||||||
tests = [
|
|
||||||
b'export * from "./module_test.477bbebe77f0.js";',
|
|
||||||
b'export { testConst } from "./module_test.477bbebe77f0.js";',
|
|
||||||
b"export {\n"
|
|
||||||
b" firstVar as firstVarAlias,\n"
|
|
||||||
b" secondVar as secondVarAlias\n"
|
|
||||||
b'} from "./module_test.477bbebe77f0.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"],
|
||||||
@ -646,6 +600,68 @@ class TestCollectionSimpleStorage(CollectionTestCase):
|
|||||||
self.assertIn(b"other.deploy12345.css", content)
|
self.assertIn(b"other.deploy12345.css", content)
|
||||||
|
|
||||||
|
|
||||||
|
class JSModuleImportAggregationManifestStorage(storage.ManifestStaticFilesStorage):
|
||||||
|
support_js_module_import_aggregation = True
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": (
|
||||||
|
"staticfiles_tests.test_storage."
|
||||||
|
"JSModuleImportAggregationManifestStorage"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
class TestCollectionJSModuleImportAggregationManifestStorage(CollectionTestCase):
|
||||||
|
hashed_file_path = hashed_file_path
|
||||||
|
|
||||||
|
def test_module_import(self):
|
||||||
|
relpath = self.hashed_file_path("cached/module.js")
|
||||||
|
self.assertEqual(relpath, "cached/module.55fd6938fbc5.js")
|
||||||
|
tests = [
|
||||||
|
# Relative imports.
|
||||||
|
b'import testConst from "./module_test.477bbebe77f0.js";',
|
||||||
|
b'import relativeModule from "../nested/js/nested.866475c46bb4.js";',
|
||||||
|
b'import { firstConst, secondConst } from "./module_test.477bbebe77f0.js";',
|
||||||
|
# Absolute import.
|
||||||
|
b'import rootConst from "/static/absolute_root.5586327fe78c.js";',
|
||||||
|
# Dynamic import.
|
||||||
|
b'const dynamicModule = import("./module_test.477bbebe77f0.js");',
|
||||||
|
# Creating a module object.
|
||||||
|
b'import * as NewModule from "./module_test.477bbebe77f0.js";',
|
||||||
|
# Aliases.
|
||||||
|
b'import { testConst as alias } from "./module_test.477bbebe77f0.js";',
|
||||||
|
b"import {\n"
|
||||||
|
b" firstVar1 as firstVarAlias,\n"
|
||||||
|
b" $second_var_2 as secondVarAlias\n"
|
||||||
|
b'} from "./module_test.477bbebe77f0.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)
|
||||||
|
|
||||||
|
def test_aggregating_modules(self):
|
||||||
|
relpath = self.hashed_file_path("cached/module.js")
|
||||||
|
self.assertEqual(relpath, "cached/module.55fd6938fbc5.js")
|
||||||
|
tests = [
|
||||||
|
b'export * from "./module_test.477bbebe77f0.js";',
|
||||||
|
b'export { testConst } from "./module_test.477bbebe77f0.js";',
|
||||||
|
b"export {\n"
|
||||||
|
b" firstVar as firstVarAlias,\n"
|
||||||
|
b" secondVar as secondVarAlias\n"
|
||||||
|
b'} from "./module_test.477bbebe77f0.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)
|
||||||
|
|
||||||
|
|
||||||
class CustomManifestStorage(storage.ManifestStaticFilesStorage):
|
class CustomManifestStorage(storage.ManifestStaticFilesStorage):
|
||||||
def __init__(self, *args, manifest_storage=None, **kwargs):
|
def __init__(self, *args, manifest_storage=None, **kwargs):
|
||||||
manifest_storage = storage.StaticFilesStorage(
|
manifest_storage = storage.StaticFilesStorage(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user