diff --git a/docs/manual/extending/coderef/index.rst b/docs/manual/extending/coderef/index.rst
index 66bf7762866b3c1058e4b0a61de73bd186ea4a0b..440afcc680df9249fa6b8d3ea499b9b0572823c9 100644
--- a/docs/manual/extending/coderef/index.rst
+++ b/docs/manual/extending/coderef/index.rst
@@ -191,6 +191,8 @@ Extensions
    reviewboard.extensions.base
    reviewboard.extensions.hooks
    reviewboard.extensions.packaging
+   reviewboard.extensions.packaging.setuptools_backend
+   reviewboard.extensions.packaging.static_media
    reviewboard.extensions.testing
    reviewboard.extensions.testing.testcases
 
diff --git a/reviewboard/extensions/packaging/__init__.py b/reviewboard/extensions/packaging/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..df3264b4d078281568ff16234da85788e04c9df0
--- /dev/null
+++ b/reviewboard/extensions/packaging/__init__.py
@@ -0,0 +1,98 @@
+"""Packaging support for Review Board extensions.
+
+Version Changed:
+    7.1:
+    This has been split into sub-modules: Consumers should update any older
+    imports for this module to instead import from
+    :py:mod:`reviewboard.extensions.packaging.setuptools_backend` or
+    :py:mod:`reviewboard.extensions.packaging.static_media`.
+"""
+
+# NOTE: It's important not to import anything directly in this module that
+#       depends on a configured Django environment.
+
+from __future__ import annotations
+
+from housekeeping import ClassMovedMixin, func_moved
+
+from reviewboard.deprecation import RemovedInReviewBoard90Warning
+import reviewboard.extensions.packaging.setuptools_backend as \
+    setuptools_backend
+import reviewboard.extensions.packaging.static_media as static_media
+
+
+class RBStaticMediaBuildContext(ClassMovedMixin,
+                                static_media.RBStaticMediaBuildContext,
+                                warning_cls=RemovedInReviewBoard90Warning):
+    """Context for performing a static media build for an extension.
+
+    This will set up some default NPM workspace paths needed for building
+    Review Board extensions.
+
+    Deprecated:
+        7.1:
+        This has been moved to :py:class:`reviewboard.extensions.packaging.
+        setuptools_backend.RBStaticMediaBuildContext`. The legacy import will
+        be removed in Review Board 9.
+
+    Version Added:
+        7.0
+    """
+
+
+class RBStaticMediaBuilder(ClassMovedMixin,
+                           static_media.RBStaticMediaBuilder,
+                           warning_cls=RemovedInReviewBoard90Warning):
+    """Static media builder for Review Board extensions.
+
+    This will take care of building static media files. As part of this, it
+    will set up Babel, Rollup, and TypeScript configuration files needed to
+    compile against Review Board JavaScript/TypeScript modules.
+
+    Deprecated:
+        7.1:
+        This has been moved to :py:class:`reviewboard.extensions.packaging.
+        setuptools_backend.RBStaticMediaBuilder`. The legacy import will be
+        removed in Review Board 9.
+
+    Version Added:
+        7.0
+    """
+
+
+class BuildStaticFiles(ClassMovedMixin,
+                       setuptools_backend.BuildStaticFiles,
+                       warning_cls=RemovedInReviewBoard90Warning):
+    """Builds static files for the extension.
+
+    This will build the static media files used by the extension. JavaScript
+    bundles will be minified and versioned. CSS bundles will be processed
+    through LessCSS (if using :file:`.less` files), minified and versioned.
+
+    Deprecated:
+        7.1:
+        This has been moved to :py:class:`reviewboard.extensions.packaging.
+        setuptools_backend.RBStaticMediaBuilder`. The legacy import will be
+        removed in Review Board 9.
+
+    Version Added:
+        7.0
+    """
+
+
+@func_moved(RemovedInReviewBoard90Warning,
+            new_func=setuptools_backend.setup)
+def setup(**setup_kwargs):
+    """Build an extension package.
+
+    Deprecated:
+        7.1:
+        This has been moved to :py:class:`reviewboard.extensions.packaging.
+        setuptools_backend.setup`. The legacy import will be removed in
+        Review Board 9.
+
+    Args:
+        **setup_kwargs (dict):
+            Keyword arguments to pass to the main setup method.
+    """
+    return setuptools_backend.setup(**setup_kwargs)
diff --git a/reviewboard/extensions/packaging/setuptools_backend.py b/reviewboard/extensions/packaging/setuptools_backend.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0c2f8210e7bfd91cc79878f8e38fbbda28a42d8
--- /dev/null
+++ b/reviewboard/extensions/packaging/setuptools_backend.py
@@ -0,0 +1,69 @@
+"""Packaging support for Review Board extensions.
+
+Version Added:
+    7.1:
+    This moved from the top-level :py:mod:`reviewboard.packaging`.
+"""
+
+from __future__ import annotations
+
+import os
+import sys
+
+from djblets.extensions.packaging.setuptools_backend import (
+    BuildStaticFiles as DjbletsBuildStaticFiles,
+    build_extension_cmdclass,
+)
+from setuptools import setup as setuptools_setup
+
+from reviewboard.extensions.packaging.static_media import (
+    RBStaticMediaBuilder,
+    RBStaticMediaBuildContext,
+)
+
+
+class BuildStaticFiles(DjbletsBuildStaticFiles):
+    """Builds static files for the extension.
+
+    This will build the static media files used by the extension. JavaScript
+    bundles will be minified and versioned. CSS bundles will be processed
+    through LessCSS (if using :file:`.less` files), minified and versioned.
+
+    Version Changed:
+        7.1:
+        This moved from :py:mod:`reviewboard.extensions.packaging`.
+    """
+
+    extension_entrypoint_group = 'reviewboard.extensions'
+    django_settings_module = 'reviewboard.settings'
+    static_media_builder_cls = RBStaticMediaBuilder
+    static_media_build_context_cls = RBStaticMediaBuildContext
+
+
+def setup(**setup_kwargs):
+    """Build an extension package.
+
+    Version Changed:
+        7.1:
+        This moved from :py:mod:`reviewboard.extensions.packaging`.
+
+    Args:
+        **setup_kwargs (dict):
+            Keyword arguments to pass to the main setup method.
+    """
+    # Add the included conf directory so that there's a settings_local.py
+    # file that can be used to package the static media.
+    extensions_dir = os.path.abspath(os.path.dirname(__file__))
+    sys.path.insert(0, os.path.join(extensions_dir, 'conf'))
+
+    os.environ[str('FORCE_BUILD_MEDIA')] = str('1')
+
+    setup_kwargs.update({
+        'zip_safe': False,
+        'include_package_data': True,
+        'cmdclass': dict(
+            build_extension_cmdclass(build_static_files_cls=BuildStaticFiles),
+            **setup_kwargs.get('cmdclass', {})),
+    })
+
+    setuptools_setup(**setup_kwargs)
diff --git a/reviewboard/extensions/packaging.py b/reviewboard/extensions/packaging/static_media.py
similarity index 80%
rename from reviewboard/extensions/packaging.py
rename to reviewboard/extensions/packaging/static_media.py
index c24166a362db2323da4d70f27b1da82874aca4ad..e218829e3e1e0f5b138f79a06203b5d71d524ae4 100644
--- a/reviewboard/extensions/packaging.py
+++ b/reviewboard/extensions/packaging/static_media.py
@@ -1,22 +1,22 @@
-"""Packaging support for Review Board extensions."""
+
+"""Packaging support for Review Board extensions.
+
+Version Added:
+    7.1:
+    This moved from the top-level :py:mod:`reviewboard.extensions.packaging`.
+"""
 
 from __future__ import annotations
 
 import json
 import os
-import sys
 from pathlib import Path
 from typing import TYPE_CHECKING
 
-from djblets.extensions.packaging.setuptools_backend import (
-    BuildStaticFiles as DjbletsBuildStaticFiles,
-    build_extension_cmdclass,
-)
 from djblets.extensions.packaging.static_media import (
     StaticMediaBuilder,
     StaticMediaBuildContext,
 )
-from setuptools import setup as setuptools_setup
 
 import reviewboard
 from reviewboard import VERSION
@@ -34,6 +34,10 @@ class RBStaticMediaBuildContext(StaticMediaBuildContext):
     This will set up some default NPM workspace paths needed for building
     Review Board extensions.
 
+    Version Changed:
+        7.1:
+        This moved from :py:mod:`reviewboard.extensions.packaging`.
+
     Version Added:
         7.0
     """
@@ -83,6 +87,10 @@ class RBStaticMediaBuilder(StaticMediaBuilder):
     will set up Babel, Rollup, and TypeScript configuration files needed to
     compile against Review Board JavaScript/TypeScript modules.
 
+    Version Changed:
+        7.1:
+        This moved from :py:mod:`reviewboard.extensions.packaging`.
+
     Version Added:
         7.0
     """
@@ -172,36 +180,3 @@ class RBStaticMediaBuilder(StaticMediaBuilder):
                             f'{packaging_js_modpath}/rollup-extensions.mjs',
                         'static_dir': rel_static_dir,
                     })
-
-
-class BuildStaticFiles(DjbletsBuildStaticFiles):
-    """Builds static files for the extension.
-
-    This will build the static media files used by the extension. JavaScript
-    bundles will be minified and versioned. CSS bundles will be processed
-    through LessCSS (if using :file:`.less` files), minified and versioned.
-    """
-
-    extension_entrypoint_group = 'reviewboard.extensions'
-    django_settings_module = 'reviewboard.settings'
-    static_media_builder_cls = RBStaticMediaBuilder
-    static_media_build_context_cls = RBStaticMediaBuildContext
-
-
-def setup(**setup_kwargs):
-    # Add the included conf directory so that there's a settings_local.py
-    # file that can be used to package the static media.
-    extensions_dir = os.path.abspath(os.path.dirname(__file__))
-    sys.path.insert(0, os.path.join(extensions_dir, 'conf'))
-
-    os.environ[str('FORCE_BUILD_MEDIA')] = str('1')
-
-    setup_kwargs.update({
-        'zip_safe': False,
-        'include_package_data': True,
-        'cmdclass': dict(
-            build_extension_cmdclass(build_static_files_cls=BuildStaticFiles),
-            **setup_kwargs.get('cmdclass', {})),
-    })
-
-    setuptools_setup(**setup_kwargs)
