diff --git a/src/Entity/JavaScriptComponent.php b/src/Entity/JavaScriptComponent.php
index e9d72dbd1d9e35442520fac2de8a938ba2349411..326508d03fb44ad300e647171475f1994570b86a 100644
--- a/src/Entity/JavaScriptComponent.php
+++ b/src/Entity/JavaScriptComponent.php
@@ -168,9 +168,9 @@ final class JavaScriptComponent extends ConfigEntityBase implements XbAssetInter
       ]);
     }
 
+    $violation_list = new EntityConstraintViolationList($this);
     if (array_key_exists('source_code_js', $data) || array_key_exists('compiled_js', $data)) {
       if (!array_key_exists('imported_js_components', $data)) {
-        $violation_list = new EntityConstraintViolationList($this);
         $violation_list->add(new ConstraintViolation(
           "The 'imported_js_components' field is required when 'source_code_js' or 'compiled_js' is provided",
           "The 'imported_js_components' field is required when 'source_code_js' or 'compiled_js' is provided",
@@ -181,6 +181,22 @@ final class JavaScriptComponent extends ConfigEntityBase implements XbAssetInter
         ));
         throw new ConstraintViolationException($violation_list);
       }
+      foreach ($data['imported_js_components'] as $key => $js_component_name) {
+        // Test that the imported_js_components are valid names.
+        if (!preg_match('/^[a-z0-9_-]+$/', $js_component_name)) {
+          $violation_list->add(new ConstraintViolation(
+            "The 'imported_js_components' contains an invalid component name.",
+            "The 'imported_js_components' contains an invalid component name.",
+            [],
+            NULL,
+            "imported_js_components",
+            NULL
+          ));
+        }
+      }
+      if ($violation_list->count() > 0) {
+        throw new ConstraintViolationException($violation_list);
+      }
       // The client calculates imported JavaScript components dependencies. This
       // value is never returned to the client as it will always recalculate it
       // based off source_code_js.
@@ -358,8 +374,8 @@ final class JavaScriptComponent extends ConfigEntityBase implements XbAssetInter
       $js_component = JavaScriptComponent::load($js_component_name);
       if (!$js_component) {
         $violation_list->add(new ConstraintViolation(
-          "The JavaScript component with machine name '$js_component_name' does not exist.",
-          "The JavaScript component with machine name '$js_component_name' does not exist.",
+          "The JavaScript component with the machine name '$js_component_name' does not exist.",
+          "The JavaScript component with the machine name '$js_component_name' does not exist.",
           [],
           NULL,
           "imported_js_components.$key",
@@ -437,4 +453,12 @@ final class JavaScriptComponent extends ConfigEntityBase implements XbAssetInter
     return self::loadMultiple($js_component_ids);
   }
 
+  public function getCacheTags() {
+    $cache_tags = parent::getCacheTags();
+    if ($dependencies = $this->getDependencies()) {
+      $cache_tags = array_merge($cache_tags, array_map(fn($dependency) => "config:$dependency", $dependencies['config'] ?? []));
+    }
+    return $cache_tags;
+  }
+
 }
diff --git a/src/Plugin/ExperienceBuilder/ComponentSource/JsComponent.php b/src/Plugin/ExperienceBuilder/ComponentSource/JsComponent.php
index d624af72cbfe554ac320b4684512592af8a930dd..92ce9e429047e88fc2df382e4c2bf1a94867ef21 100644
--- a/src/Plugin/ExperienceBuilder/ComponentSource/JsComponent.php
+++ b/src/Plugin/ExperienceBuilder/ComponentSource/JsComponent.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace Drupal\experience_builder\Plugin\ExperienceBuilder\ComponentSource;
 
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
 use Drupal\Core\Extension\ExtensionPathResolver;
 use Drupal\Core\File\FileUrlGeneratorInterface;
@@ -165,7 +166,16 @@ final class JsComponent extends GeneratedFieldExplicitInputUxComponentSourceBase
       \assert($autoSave->data !== NULL);
       $component = $component->forAutoSavePreview($autoSave->data);
     }
+    if ($isPreview) {
+      $build['#cache']['tags'][] = AutoSaveManager::CACHE_TAG;
+    }
+
     $valid_props = $component->getProps() ?? [];
+
+    CacheableMetadata::createFromRenderArray($build)
+      ->addCacheableDependency($component)
+      ->applyTo($build);
+
     return $build + [
       '#type' => 'astro_island',
       '#uuid' => $componentUuid,
diff --git a/tests/modules/xb_test_code_components/config/install/experience_builder.component.js.xb_test_code_components_using_imports.yml b/tests/modules/xb_test_code_components/config/install/experience_builder.component.js.xb_test_code_components_using_imports.yml
new file mode 100644
index 0000000000000000000000000000000000000000..185f06f147f7c51da66013c7875feef4d06b661f
--- /dev/null
+++ b/tests/modules/xb_test_code_components/config/install/experience_builder.component.js.xb_test_code_components_using_imports.yml
@@ -0,0 +1,14 @@
+uuid: dd1e8922-118a-4ff7-b83c-bc8543efdc5a
+langcode: en
+status: true
+dependencies:
+  config:
+    - experience_builder.js_component.xb_test_code_components_using_imports
+label: 'Component using imports'
+id: js.xb_test_code_components_using_imports
+provider: null
+source: js
+category: '@todo'
+settings:
+  local_source_id: xb_test_code_components_using_imports
+  prop_field_definitions: {  }
diff --git a/tests/modules/xb_test_code_components/config/install/experience_builder.js_component.xb_test_code_components_using_imports.yml b/tests/modules/xb_test_code_components/config/install/experience_builder.js_component.xb_test_code_components_using_imports.yml
new file mode 100644
index 0000000000000000000000000000000000000000..66c15c7aa9fb67e5e9fb174fe9c762c932289b0b
--- /dev/null
+++ b/tests/modules/xb_test_code_components/config/install/experience_builder.js_component.xb_test_code_components_using_imports.yml
@@ -0,0 +1,88 @@
+uuid: 82d79d93-c4b8-4413-9b76-f89ffe432bc1
+langcode: en
+status: true
+dependencies:
+  enforced:
+    config:
+      - experience_builder.js_component.xb_test_code_components_with_no_props
+      - experience_builder.js_component.xb_test_code_components_with_props
+machineName: xb_test_code_components_using_imports
+name: 'Component using imports'
+block_override: null
+required: {  }
+props: {  }
+slots: {  }
+js:
+  original: |
+    import WithNoProps from '@/components/xb_test_code_components_with_no_props';
+    import WithProps from '@/components/xb_test_code_components_with_props';
+    import FormattedText from "@/lib/FormattedText";
+    import { cn } from "@/lib/utils";
+
+    const UsingImports = ({
+      title = "<h3>Component using imports</h3>",
+    }) => {
+      return (
+        <div className="test-component-using-specific-imports">
+          <h2>This component imports specific components</h2>
+          <div className="imported-components">
+            <div className="no-props-component">
+              <h3>Component with no props:</h3>
+              <WithNoProps />
+            </div>
+            <div className="props-component">
+              <h3>Component with props:</h3>
+              <WithProps name="Imported Name" age={25} />
+            </div>
+          </div>
+        </div>
+      );
+    };
+
+    export default UsingImports;
+  compiled: |
+    import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
+    import WithNoProps from '@/components/xb_test_code_components_with_no_props';
+    import WithProps from '@/components/xb_test_code_components_with_props';
+    import FormattedText from "@/lib/FormattedText";
+    import { cn } from "@/lib/utils";
+    const UsingImports = ({ title = "<h3>Component using imports</h3>" })=>{
+        return /*#__PURE__*/ _jsxs("div", {
+            className: "test-component-using-specific-imports",
+            children: [
+                /*#__PURE__*/ _jsx("h2", {
+                    children: "This component imports specific components"
+                }),
+                /*#__PURE__*/ _jsxs("div", {
+                    className: "imported-components",
+                    children: [
+                        /*#__PURE__*/ _jsxs("div", {
+                            className: "no-props-component",
+                            children: [
+                                /*#__PURE__*/ _jsx("h3", {
+                                    children: "Component with no props:"
+                                }),
+                                /*#__PURE__*/ _jsx(WithNoProps, {})
+                            ]
+                        }),
+                        /*#__PURE__*/ _jsxs("div", {
+                            className: "props-component",
+                            children: [
+                                /*#__PURE__*/ _jsx("h3", {
+                                    children: "Component with props:"
+                                }),
+                                /*#__PURE__*/ _jsx(WithProps, {
+                                    name: "Imported Name",
+                                    age: 25
+                                })
+                            ]
+                        })
+                    ]
+                })
+            ]
+        });
+    };
+    export default UsingImports;
+css:
+  original: ''
+  compiled: ''
diff --git a/tests/src/Functional/PropSourceEndpointTest.php b/tests/src/Functional/PropSourceEndpointTest.php
index 9cdc6a55efa10e6c86c65d2504281066355194aa..f9ac34dd7e52482f4c4589afd3b340f35b103d05 100644
--- a/tests/src/Functional/PropSourceEndpointTest.php
+++ b/tests/src/Functional/PropSourceEndpointTest.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace Drupal\Tests\experience_builder\Functional;
 
 use Drupal\Component\Serialization\Json;
+use Drupal\experience_builder\AutoSave\AutoSaveManager;
 use Drupal\experience_builder\Entity\Component;
 use Drupal\node\Entity\Node;
 use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
@@ -60,6 +61,7 @@ class PropSourceEndpointTest extends FunctionalTestBase {
       'comment_list',
       'config:component_list',
       'config:core.extension',
+      'config:experience_builder.js_component.my-cta',
       'config:search.settings',
       'config:system.menu.account',
       'config:system.menu.admin',
@@ -77,6 +79,7 @@ class PropSourceEndpointTest extends FunctionalTestBase {
       'user:0',
       'user:1',
       'user_list',
+      AutoSaveManager::CACHE_TAG,
     ];
 
     $expected_contexts = [
diff --git a/tests/src/Functional/XbConfigEntityHttpApiTest.php b/tests/src/Functional/XbConfigEntityHttpApiTest.php
index b6695464103d0646b402d27b072426a32762602f..dde73fb6f69ae8834d244efc91273d6045f295a6 100644
--- a/tests/src/Functional/XbConfigEntityHttpApiTest.php
+++ b/tests/src/Functional/XbConfigEntityHttpApiTest.php
@@ -4,9 +4,10 @@ declare(strict_types=1);
 
 namespace Drupal\Tests\experience_builder\Functional;
 
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Url;
 use Drupal\experience_builder\Audit\ComponentAudit;
 use Drupal\experience_builder\AutoSave\AutoSaveManager;
-use Drupal\Core\Url;
 use Drupal\experience_builder\Entity\AssetLibrary;
 use Drupal\experience_builder\Entity\Component;
 use Drupal\experience_builder\Entity\ComponentInterface;
@@ -583,7 +584,7 @@ class XbConfigEntityHttpApiTest extends HttpApiTestBase {
     $this->assertSame([
       'errors' => [
         [
-          'detail' => "The JavaScript component with machine name 'missing' does not exist.",
+          'detail' => "The JavaScript component with the machine name 'missing' does not exist.",
           'source' => ['pointer' => 'imported_js_components.0'],
         ],
       ],
@@ -873,8 +874,16 @@ class XbConfigEntityHttpApiTest extends HttpApiTestBase {
     // @see docs/config-management.md#3.2.1
     $this->assertNotNull(Component::load('js.test'));
     $this->assertTrue(Component::load('js.test')->status());
-    $this->assertExposedCodeComponents(['js.test'], 'MISS', $request_options);
-    $this->assertExposedCodeComponents(['js.test'], 'HIT', $request_options);
+    $this->assertExposedCodeComponents(['js.test'], 'MISS', $request_options, [
+      AutoSaveManager::CACHE_TAG,
+      'config:experience_builder.js_component.another_component',
+      'config:experience_builder.js_component.test',
+    ]);
+    $this->assertExposedCodeComponents(['js.test'], 'HIT', $request_options, [
+      AutoSaveManager::CACHE_TAG,
+      'config:experience_builder.js_component.another_component',
+      'config:experience_builder.js_component.test',
+    ]);
     // Confirm that there STILL is an auto-save, and its `status` was updated!
     $auto_save_data['status'] = TRUE;
     $this->assertCurrentAutoSave(200, $auto_save_data, JavaScriptComponent::ENTITY_TYPE_ID, 'test');
@@ -1090,7 +1099,7 @@ class XbConfigEntityHttpApiTest extends HttpApiTestBase {
     ], json_decode((string) $response->getBody(), TRUE));
   }
 
-  private function assertExposedCodeComponents(array $expected, string $expected_dynamic_page_cache, array $request_options): void {
+  private function assertExposedCodeComponents(array $expected, string $expected_dynamic_page_cache, array $request_options, array $additional_expected_cache_tags = []): void {
     assert(in_array($expected_dynamic_page_cache, ['HIT', 'MISS'], TRUE));
     $expected_contexts = [
       'languages:language_content',
@@ -1107,7 +1116,7 @@ class XbConfigEntityHttpApiTest extends HttpApiTestBase {
       // @see \Drupal\experience_builder\Controller\ApiComponentsController::getCacheableClientSideInfo()
       'user.roles:anonymous',
     ];
-    $body = $this->assertExpectedResponse('GET', Url::fromUri('base:/xb/api/v0/config/component'), $request_options, 200, $expected_contexts, [
+    $expected_cache_tags = [
       'CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form',
       'config:component_list',
       'config:core.extension',
@@ -1127,7 +1136,11 @@ class XbConfigEntityHttpApiTest extends HttpApiTestBase {
       'user:1',
       'user:2',
       'user_list',
-    ], 'UNCACHEABLE (request policy)', $expected_dynamic_page_cache);
+    ];
+    // If expected adds new components, those components add additional cache tags. If those cache tags are not
+    // present, the test will fail. This array is used to add those additional expected cache tags.
+    $expected_cache_tags = Cache::mergeTags($expected_cache_tags, $additional_expected_cache_tags);
+    $body = $this->assertExpectedResponse('GET', Url::fromUri('base:/xb/api/v0/config/component'), $request_options, 200, $expected_contexts, $expected_cache_tags, 'UNCACHEABLE (request policy)', $expected_dynamic_page_cache);
     self:self::assertNotNull($body);
     $component_config_entity_ids = array_keys($body);
     self::assertSame(
diff --git a/tests/src/Kernel/Config/JavaScriptComponentValidationTest.php b/tests/src/Kernel/Config/JavaScriptComponentValidationTest.php
index 71cb9fd3bd4fd38b1e0b7cdb4cd7d0ac8e87cf18..3a27df11d23fd0011139bbe2a75b010d0d102b52 100644
--- a/tests/src/Kernel/Config/JavaScriptComponentValidationTest.php
+++ b/tests/src/Kernel/Config/JavaScriptComponentValidationTest.php
@@ -4,9 +4,11 @@ declare(strict_types=1);
 
 namespace Drupal\Tests\experience_builder\Kernel\Config;
 
-// cspell:ignore sofie
+// cspell:ignore sofie componente extraño
 
 use Drupal\experience_builder\Entity\JavaScriptComponent;
+use Drupal\experience_builder\Exception\ConstraintViolationException;
+use Drupal\Tests\experience_builder\Traits\BetterConfigDependencyManagerTrait;
 
 /**
  * Tests validation of JavaScriptComponent entities.
@@ -17,6 +19,8 @@ use Drupal\experience_builder\Entity\JavaScriptComponent;
  */
 class JavaScriptComponentValidationTest extends BetterConfigEntityValidationTestBase {
 
+  use BetterConfigDependencyManagerTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -56,9 +60,7 @@ class JavaScriptComponentValidationTest extends BetterConfigEntityValidationTest
    */
   protected function setUp(): void {
     parent::setUp();
-
-    $this->entity = JavaScriptComponent::create([
-      'machineName' => 'test',
+    $javascript_component_base = [
       'name' => 'Test',
       'status' => TRUE,
       'props' => [
@@ -86,10 +88,48 @@ class JavaScriptComponentValidationTest extends BetterConfigEntityValidationTest
         'original' => '.test { display: none; }',
         'compiled' => '.test{display:none;}',
       ],
+    ];
+    JavaScriptComponent::create([...$javascript_component_base, 'machineName' => 'other'])->save();
+    $this->entity = JavaScriptComponent::create([
+      ...$javascript_component_base,
+      'machineName' => 'test',
+      'dependencies' => [
+        'enforced' => [
+          'config' => [
+            // @phpstan-ignore-next-line
+            JavaScriptComponent::load('other')->getConfigDependencyName(),
+          ],
+        ],
+      ],
     ]);
     $this->entity->save();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function testEntityIsValid(): void {
+    parent::testEntityIsValid();
+
+    // Beyond validity, validate config dependencies are computed correctly.
+    $this->assertSame(
+      [
+        'config' => [
+          'experience_builder.js_component.other',
+        ],
+      ],
+      $this->entity->getDependencies()
+    );
+    $this->assertSame([
+      'config' => [
+        'experience_builder.js_component.other',
+      ],
+      'module' => [
+        'experience_builder',
+      ],
+    ], $this->getAllDependencies($this->entity));
+  }
+
   /**
    * @testWith [true, true, []]
    *           [true, false, {"": "Prop \"silly\" is required, but does not have example value"}]
@@ -164,6 +204,24 @@ class JavaScriptComponentValidationTest extends BetterConfigEntityValidationTest
     $this->assertValidationErrors($expected_validation_errors);
   }
 
+  /**
+   * @testWith ["missing", "The JavaScript component with the machine name 'missing' does not exist."]
+   *           ["", "The 'imported_js_components' contains an invalid component name."]
+   *           ["🚀", "The 'imported_js_components' contains an invalid component name."]
+   *           ["componente_extraño", "The 'imported_js_components' contains an invalid component name."]
+   *           [";", "The 'imported_js_components' contains an invalid component name."]
+   */
+  public function testNonExistingJsDependencies(string $component_id, string $expected_exception_message): void {
+    \assert($this->entity instanceof JavaScriptComponent);
+    $this->expectException(ConstraintViolationException::class);
+    $this->expectExceptionMessage($expected_exception_message);
+
+    \assert($this->entity instanceof JavaScriptComponent);
+    $client_values = $this->entity->normalizeForClientSide()->values;
+    $client_values['imported_js_components'] = [$component_id];
+    $this->entity->updateFromClientSide($client_values);
+  }
+
   public static function providerInvalidEnumsAndExamples(): array {
     return [
       'Invalid string' => [
diff --git a/tests/src/Kernel/Config/JavascriptComponentTest.php b/tests/src/Kernel/Config/JavascriptComponentTest.php
index b5628ec268707a270c3c43b4f2991579bc5dd309..9618b5af2376a98f452599abca38920bc2fbc85b 100644
--- a/tests/src/Kernel/Config/JavascriptComponentTest.php
+++ b/tests/src/Kernel/Config/JavascriptComponentTest.php
@@ -40,6 +40,9 @@ class JavascriptComponentTest extends KernelTestBase {
     $js_component = JavaScriptComponent::createFromClientSide($client_data);
     $this->assertSame(SAVED_NEW, $js_component->save());
     $this->assertCount(0, $js_component->getDependencies());
+    $this->assertSame([
+      'config:experience_builder.js_component.test',
+    ], $js_component->getCacheTags());
 
     // Create another component that will be imported by the first one.
     $client_data_2 = $client_data;
@@ -48,6 +51,9 @@ class JavascriptComponentTest extends KernelTestBase {
     $js_component2 = JavaScriptComponent::createFromClientSide($client_data_2);
     $this->assertSame(SAVED_NEW, $js_component2->save());
     $this->assertCount(0, $js_component2->getDependencies());
+    $this->assertSame([
+      'config:experience_builder.js_component.test2',
+    ], $js_component2->getCacheTags());
 
     // Adding a component to `imported_js_components` should add this component
     // to the dependencies.
@@ -60,6 +66,10 @@ class JavascriptComponentTest extends KernelTestBase {
       ],
       $js_component->getDependencies()
     );
+    $this->assertSame([
+      'config:experience_builder.js_component.test',
+      'config:experience_builder.js_component.test2',
+    ], $js_component->getCacheTags());
 
     // Ensure missing components are will throw a validation error.
     $client_data['imported_js_components'] = [$js_component2->id(), 'missing'];
@@ -74,7 +84,7 @@ class JavascriptComponentTest extends KernelTestBase {
       $this->assertCount(1, $violations);
       $violation = $violations->get(0);
       $this->assertSame('imported_js_components.1', $violation->getPropertyPath());
-      $this->assertSame("The JavaScript component with machine name 'missing' does not exist.", $violation->getMessage());
+      $this->assertSame("The JavaScript component with the machine name 'missing' does not exist.", $violation->getMessage());
     }
 
     // Ensure not sending `imported_js_components` will throw an error.
@@ -99,6 +109,9 @@ class JavascriptComponentTest extends KernelTestBase {
     $js_component->updateFromClientSide($client_data);
     $this->assertSame(SAVED_UPDATED, $js_component->save());
     $this->assertSame([], $js_component->getDependencies());
+    $this->assertSame([
+      'config:experience_builder.js_component.test',
+    ], $js_component->getCacheTags());
   }
 
 }
diff --git a/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php b/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php
index 41ecfb797b1e4bde6ff005055b6df12b1c7dd4f3..390d0ff7f7a364558470f20efeefe31c65e83260 100644
--- a/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php
+++ b/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php
@@ -11,6 +11,7 @@ use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Render\Markup;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\Core\TypedData\TypedDataManagerInterface;
+use Drupal\experience_builder\AutoSave\AutoSaveManager;
 use Drupal\experience_builder\Element\RenderSafeComponentContainer;
 use Drupal\experience_builder\Entity\Page;
 use Drupal\experience_builder\Plugin\DataType\ComponentTreeStructure;
@@ -884,7 +885,10 @@ HTML,
                                     '#component' => [
                                       '#type' => 'astro_island',
                                       '#cache' => [
-                                        'tags' => ['config:experience_builder.component.js.my-cta'],
+                                        'tags' => [
+                                          'config:experience_builder.js_component.my-cta',
+                                          'config:experience_builder.component.js.my-cta',
+                                        ],
                                         'contexts' => [],
                                         'max-age' => Cache::PERMANENT,
                                       ],
@@ -941,7 +945,10 @@ HTML,
                                     '#component' => [
                                       '#type' => 'astro_island',
                                       '#cache' => [
-                                        'tags' => ['config:experience_builder.component.js.my-cta-with-auto-save'],
+                                        'tags' => [
+                                          'config:experience_builder.js_component.my-cta-with-auto-save',
+                                          'config:experience_builder.component.js.my-cta-with-auto-save',
+                                        ],
                                         'contexts' => [],
                                         'max-age' => Cache::PERMANENT,
                                       ],
@@ -1118,13 +1125,16 @@ HTML,
       'expected_cache_tags' => [
         'config:experience_builder.component.sdc.xb_test_sdc.props-slots',
         'config:experience_builder.component.sdc.xb_test_sdc.props-no-slots',
+        'config:experience_builder.js_component.my-cta-with-auto-save',
         'config:experience_builder.component.js.my-cta-with-auto-save',
+        'config:experience_builder.js_component.my-cta',
         'config:experience_builder.component.js.my-cta',
         'config:system.site',
         'config:experience_builder.component.block.system_branding_block',
       ],
     ];
     yield 'component tree with complex nesting' => [...$component_tree_with_complex_nesting, 'isPreview' => FALSE];
+
     $path_to_auto_saved_js_component = [
       ComponentTreeStructure::ROOT_UUID,
       'uuid-in-root',
@@ -1136,12 +1146,53 @@ HTML,
       'uuid-js-component-auto-save',
       '#component',
     ];
+    $path_to_js_component = [
+      ComponentTreeStructure::ROOT_UUID,
+      'uuid-in-root',
+      '#component', '#slots', 'the_body',
+      'uuid-level-1',
+      '#component', '#slots', 'the_body',
+      'uuid-level-2',
+      '#component', '#slots', 'the_body',
+      'uuid-js-component',
+      '#component',
+    ];
     yield 'component tree with complex nesting in preview' => [
       ...self::overwriteRenderableExpectations(
         self::setIsPreviewPropertyRecursively($component_tree_with_complex_nesting, TRUE),
         [
-          ['parents' => [...$path_to_auto_saved_js_component, '#name'], 'value' => 'My Code Component with Auto-Save - Draft'],
-          ['parents' => [...$path_to_auto_saved_js_component, '#component_url'], 'value' => '/xb/api/v0/auto-saves/js/js_component/my-cta-with-auto-save'],
+          [
+            'parents' => [...$path_to_auto_saved_js_component, '#name'],
+            'value' => 'My Code Component with Auto-Save - Draft',
+          ],
+          [
+            'parents' => [...$path_to_auto_saved_js_component, '#component_url'],
+            'value' => '/xb/api/v0/auto-saves/js/js_component/my-cta-with-auto-save',
+          ],
+          [
+            'parents' => [...$path_to_auto_saved_js_component, '#cache'],
+            'value' => [
+              'tags' => [
+                AutoSaveManager::CACHE_TAG,
+                'config:experience_builder.js_component.my-cta-with-auto-save',
+                'config:experience_builder.component.js.my-cta-with-auto-save',
+              ],
+              'contexts' => [],
+              'max-age' => Cache::PERMANENT,
+            ],
+          ],
+          [
+            'parents' => [...$path_to_js_component, '#cache'],
+            'value' => [
+              'tags' => [
+                AutoSaveManager::CACHE_TAG,
+                'config:experience_builder.js_component.my-cta',
+                'config:experience_builder.component.js.my-cta',
+              ],
+              'contexts' => [],
+              'max-age' => Cache::PERMANENT,
+            ],
+          ],
         ],
       ),
       'expected_html' => <<<HTML
@@ -1208,7 +1259,19 @@ HTML,
 <!-- xb-end-uuid-in-root -->
 HTML,
       'isPreview' => TRUE,
+      'expected_cache_tags' => [
+        'config:experience_builder.component.sdc.xb_test_sdc.props-slots',
+        'config:experience_builder.component.sdc.xb_test_sdc.props-no-slots',
+        AutoSaveManager::CACHE_TAG,
+        'config:experience_builder.js_component.my-cta-with-auto-save',
+        'config:experience_builder.component.js.my-cta-with-auto-save',
+        'config:experience_builder.js_component.my-cta',
+        'config:experience_builder.component.js.my-cta',
+        'config:system.site',
+        'config:experience_builder.component.block.system_branding_block',
+      ],
     ];
+
   }
 
   /**
diff --git a/tests/src/Kernel/DataType/ComponentTreeHydratedWithBlockOverrideTest.php b/tests/src/Kernel/DataType/ComponentTreeHydratedWithBlockOverrideTest.php
index 860c373581798cd7ecbe4866e69a040ed8b63996..257934df6b878e96b36ac08c4b323bba4229a3fd 100644
--- a/tests/src/Kernel/DataType/ComponentTreeHydratedWithBlockOverrideTest.php
+++ b/tests/src/Kernel/DataType/ComponentTreeHydratedWithBlockOverrideTest.php
@@ -7,6 +7,7 @@ namespace Drupal\Tests\experience_builder\Kernel\DataType;
 // cspell:ignore ttxgk xpzur
 
 use Drupal\Core\Render\Element;
+use Drupal\experience_builder\AutoSave\AutoSaveManager;
 use Drupal\experience_builder\Entity\JavaScriptComponent;
 use Drupal\experience_builder\Plugin\DataType\ComponentTreeStructure;
 use Drupal\Component\Utility\NestedArray;
@@ -140,6 +141,7 @@ HTML,
             'config:experience_builder.js_component.site_branding',
             'config:system.site',
             'config:experience_builder.component.block.system_branding_block',
+            AutoSaveManager::CACHE_TAG,
           ],
         ] + $original_test_case,
 
@@ -241,7 +243,9 @@ HTML,
           'expected_cache_tags' => [
             'config:experience_builder.component.sdc.xb_test_sdc.props-slots',
             'config:experience_builder.component.sdc.xb_test_sdc.props-no-slots',
+            'config:experience_builder.js_component.my-cta-with-auto-save',
             'config:experience_builder.component.js.my-cta-with-auto-save',
+            'config:experience_builder.js_component.my-cta',
             'config:experience_builder.component.js.my-cta',
             'config:experience_builder.js_component.site_branding',
             'config:system.site',
@@ -347,7 +351,10 @@ HTML,
           'expected_cache_tags' => [
             'config:experience_builder.component.sdc.xb_test_sdc.props-slots',
             'config:experience_builder.component.sdc.xb_test_sdc.props-no-slots',
+            AutoSaveManager::CACHE_TAG,
+            'config:experience_builder.js_component.my-cta-with-auto-save',
             'config:experience_builder.component.js.my-cta-with-auto-save',
+            'config:experience_builder.js_component.my-cta',
             'config:experience_builder.component.js.my-cta',
             'config:experience_builder.js_component.site_branding',
             'config:system.site',
diff --git a/tests/src/Kernel/Plugin/ExperienceBuilder/ComponentSource/JsComponentTest.php b/tests/src/Kernel/Plugin/ExperienceBuilder/ComponentSource/JsComponentTest.php
index 14c9316db90db6bd535a87a031720474b97e187d..f7746354b90ced59b28c0b0772ea6264b9ff58e5 100644
--- a/tests/src/Kernel/Plugin/ExperienceBuilder/ComponentSource/JsComponentTest.php
+++ b/tests/src/Kernel/Plugin/ExperienceBuilder/ComponentSource/JsComponentTest.php
@@ -11,6 +11,7 @@ use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Asset\AssetResolverInterface;
 use Drupal\Core\Asset\AttachedAssets;
+use Drupal\Core\Cache\CacheableDependencyInterface;
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\File\FileUrlGeneratorInterface;
 use Drupal\Core\Site\Settings;
@@ -123,6 +124,10 @@ final class JsComponentTest extends ComponentSourceTestBase {
 
   public static function getExpectedSettings(): array {
     return [
+      'js.xb_test_code_components_using_imports' => [
+        'local_source_id' => 'xb_test_code_components_using_imports',
+        'prop_field_definitions' => [],
+      ],
       'js.xb_test_code_components_vanilla_image' => [
         'local_source_id' => 'xb_test_code_components_vanilla_image',
         'prop_field_definitions' => [
@@ -183,7 +188,7 @@ final class JsComponentTest extends ComponentSourceTestBase {
     // rendering.
     // @see ::testRenderComponent()
     $rendered_without_html = array_map(
-      fn ($expectations) => array_diff_key($expectations, ['html' => NULL]),
+      fn($expectations) => array_diff_key($expectations, ['html' => NULL]),
       $rendered,
     );
 
@@ -192,17 +197,30 @@ final class JsComponentTest extends ComponentSourceTestBase {
       'theme',
       'user.permissions',
     ];
+
     $default_cacheability = (new CacheableMetadata())
       ->setCacheContexts($default_render_cache_contexts);
+
     $this->assertEquals([
+      'js.xb_test_code_components_using_imports' => [
+        'cacheability' => (clone $default_cacheability)
+          ->setCacheTags([
+            'config:experience_builder.js_component.xb_test_code_components_using_imports',
+            'config:experience_builder.js_component.xb_test_code_components_with_no_props',
+            'config:experience_builder.js_component.xb_test_code_components_with_props',
+          ]),
+      ],
       'js.xb_test_code_components_vanilla_image' => [
-        'cacheability' => $default_cacheability,
+        'cacheability' => (clone $default_cacheability)
+          ->setCacheTags(['config:experience_builder.js_component.xb_test_code_components_vanilla_image']),
       ],
       'js.xb_test_code_components_with_no_props' => [
-        'cacheability' => $default_cacheability,
+        'cacheability' => (clone $default_cacheability)
+          ->setCacheTags(['config:experience_builder.js_component.xb_test_code_components_with_no_props']),
       ],
       'js.xb_test_code_components_with_props' => [
-        'cacheability' => $default_cacheability,
+        'cacheability' => (clone $default_cacheability)
+          ->setCacheTags(['config:experience_builder.js_component.xb_test_code_components_with_props']),
       ],
     ], $rendered_without_html);
   }
@@ -211,18 +229,21 @@ final class JsComponentTest extends ComponentSourceTestBase {
    * For JavaScript components, auto-saves create an extra testing dimension!
    *
    * @depends testDiscovery
-   * @testWith [false, false, "live"]
-   *           [false, true, "live"]
-   *           [true, false, "live"]
-   *           [true, true, "draft"]
+   * @testWith [false, false, "live", []]
+   *           [false, true, "live", []]
+   *           [true, false, "live", ["experience_builder__auto_save"]]
+   *           [true, true, "draft", ["experience_builder__auto_save"]]
    */
-  public function testRenderJsComponent(bool $preview_requested, bool $auto_save_exists, string $expected_result, array $component_ids): void {
+  public function testRenderJsComponent(bool $preview_requested, bool $auto_save_exists, string $expected_result, array $additional_expected_cache_tags, array $component_ids): void {
     $this->generateComponentConfig();
     foreach ($this->componentStorage->loadMultiple($component_ids) as $component) {
       assert($component instanceof Component);
       $source = $component->getComponentSource();
       \assert($source instanceof JsComponent);
-      $this->assertRenderedAstroIsland($component, $preview_requested, $auto_save_exists, $expected_result);
+      $expected_cacheability = (new CacheableMetadata())
+        ->addCacheTags($additional_expected_cache_tags)
+        ->addCacheableDependency($source->getJavaScriptComponent());
+      $this->assertRenderedAstroIsland($component, $preview_requested, $auto_save_exists, $expected_result, $expected_cacheability);
     }
   }
 
@@ -241,6 +262,7 @@ final class JsComponentTest extends ComponentSourceTestBase {
     bool $preview_requested,
     bool $auto_save_exists,
     string $expected_result,
+    CacheableDependencyInterface $expected_cacheability,
   ): void {
     $source = $component->getComponentSource();
     \assert($source instanceof JsComponent);
@@ -254,18 +276,28 @@ final class JsComponentTest extends ComponentSourceTestBase {
     if ($auto_save_exists) {
       $this->container->get(AutoSaveManager::class)
         ->save(
-          $source->getJavaScriptComponent(),
+          $js_component,
           // 'imported_js_components' is a value sent by the client that is used to
           // determine Javascript Code component dependencies and is not saved
           // directly on the backend.
+          // Ensure that the current set of imported JS components continues to
+          // be respected.
           // @see \Drupal\experience_builder\Entity\JavaScriptComponent::addJavaScriptComponentsDependencies().
-          $source->getJavaScriptComponent()->normalizeForClientSide()->values + ['imported_js_components' => []],
+          $js_component->normalizeForClientSide()->values + [
+            'imported_js_components' => array_map(
+              fn (string $config_name): string => str_replace('experience_builder.js_component.', '', $config_name),
+              $js_component->toArray()['dependencies']['enforced']['config'] ?? []
+            ),
+          ],
         );
     }
 
     $island = $source->renderComponent([
       'props' => $expected_component_props,
     ], 'some-uuid', $preview_requested);
+
+    $this->assertEquals($expected_cacheability, CacheableMetadata::createFromRenderArray($island));
+
     $crawler = $this->crawlerForRenderArray($island);
 
     $element = $crawler->filter('astro-island');
@@ -332,6 +364,11 @@ final class JsComponentTest extends ComponentSourceTestBase {
    */
   public function testCalculateDependencies(array $component_ids): void {
     self::assertSame([
+      'js.xb_test_code_components_using_imports' => [
+        'config' => [
+          'experience_builder.js_component.xb_test_code_components_using_imports',
+        ],
+      ],
       'js.xb_test_code_components_vanilla_image' => [
         'module' => [
           'image',
@@ -611,6 +648,17 @@ final class JsComponentTest extends ComponentSourceTestBase {
    */
   public static function getExpectedClientSideInfo(): array {
     return [
+      'js.xb_test_code_components_using_imports' => [
+        'expected_output_selectors' => [
+          'astro-island[opts*="using imports"]',
+          'script[blocking="render"][src*="/ui/lib/astro-hydration/dist/client.js"]',
+        ],
+        'source' => 'Code component',
+        'metadata' => ['slots' => []],
+        'propSources' => [],
+        'dynamic_prop_source_candidates' => [],
+        'transforms' => [],
+      ],
       'js.xb_test_code_components_vanilla_image' => [
         'expected_output_selectors' => [
           'astro-island[opts*="Vanilla Image"][props*="placehold.co"]',