diff --git a/modules/webform_node/config/install/core.base_field_override.node.webform.promote.yml b/modules/webform_node/config/optional/core.base_field_override.node.webform.promote.yml
similarity index 100%
rename from modules/webform_node/config/install/core.base_field_override.node.webform.promote.yml
rename to modules/webform_node/config/optional/core.base_field_override.node.webform.promote.yml
diff --git a/modules/webform_node/config/install/core.entity_form_display.node.webform.default.yml b/modules/webform_node/config/optional/core.entity_form_display.node.webform.default.yml
similarity index 100%
rename from modules/webform_node/config/install/core.entity_form_display.node.webform.default.yml
rename to modules/webform_node/config/optional/core.entity_form_display.node.webform.default.yml
diff --git a/modules/webform_node/config/install/core.entity_view_display.node.webform.default.yml b/modules/webform_node/config/optional/core.entity_view_display.node.webform.default.yml
similarity index 100%
rename from modules/webform_node/config/install/core.entity_view_display.node.webform.default.yml
rename to modules/webform_node/config/optional/core.entity_view_display.node.webform.default.yml
diff --git a/modules/webform_node/config/install/core.entity_view_display.node.webform.teaser.yml b/modules/webform_node/config/optional/core.entity_view_display.node.webform.teaser.yml
similarity index 100%
rename from modules/webform_node/config/install/core.entity_view_display.node.webform.teaser.yml
rename to modules/webform_node/config/optional/core.entity_view_display.node.webform.teaser.yml
diff --git a/modules/webform_node/config/install/field.field.node.webform.body.yml b/modules/webform_node/config/optional/field.field.node.webform.body.yml
similarity index 100%
rename from modules/webform_node/config/install/field.field.node.webform.body.yml
rename to modules/webform_node/config/optional/field.field.node.webform.body.yml
diff --git a/modules/webform_node/config/install/field.field.node.webform.webform.yml b/modules/webform_node/config/optional/field.field.node.webform.webform.yml
similarity index 100%
rename from modules/webform_node/config/install/field.field.node.webform.webform.yml
rename to modules/webform_node/config/optional/field.field.node.webform.webform.yml
diff --git a/modules/webform_node/config/install/field.storage.node.webform.yml b/modules/webform_node/config/optional/field.storage.node.webform.yml
similarity index 87%
rename from modules/webform_node/config/install/field.storage.node.webform.yml
rename to modules/webform_node/config/optional/field.storage.node.webform.yml
index ee9415de..e736dbbe 100644
--- a/modules/webform_node/config/install/field.storage.node.webform.yml
+++ b/modules/webform_node/config/optional/field.storage.node.webform.yml
@@ -4,6 +4,9 @@ dependencies:
   module:
     - node
     - webform
+  enforced:
+    module:
+      - webform_node
 id: node.webform
 field_name: webform
 entity_type: node
diff --git a/modules/webform_node/config/install/node.type.webform.yml b/modules/webform_node/config/optional/node.type.webform.yml
similarity index 91%
rename from modules/webform_node/config/install/node.type.webform.yml
rename to modules/webform_node/config/optional/node.type.webform.yml
index 7a2f1bf0..3d2a18e4 100644
--- a/modules/webform_node/config/install/node.type.webform.yml
+++ b/modules/webform_node/config/optional/node.type.webform.yml
@@ -3,7 +3,7 @@ status: true
 dependencies:
   enforced:
     module:
-      - webform
+      - webform_node
 name: Webform
 type: webform
 description: 'A basic page with a webform attached.'
diff --git a/modules/webform_node/src/ProxyClass/WebformNodeUninstallValidator.php b/modules/webform_node/src/ProxyClass/WebformNodeUninstallValidator.php
new file mode 100644
index 00000000..9c15e053
--- /dev/null
+++ b/modules/webform_node/src/ProxyClass/WebformNodeUninstallValidator.php
@@ -0,0 +1,88 @@
+<?php
+// @codingStandardsIgnoreFile
+
+/**
+ * This file was generated via php core/scripts/generate-proxy-class.php 'Drupal\webform_node\WebformNodeUninstallValidator' "core/modules/webform_node/src".
+ */
+
+namespace Drupal\webform_node\ProxyClass {
+
+    /**
+     * Provides a proxy class for \Drupal\webform_node\WebformNodeUninstallValidator.
+     *
+     * @see \Drupal\Component\ProxyBuilder
+     */
+    class WebformNodeUninstallValidator implements \Drupal\Core\Extension\ModuleUninstallValidatorInterface
+    {
+
+        use \Drupal\Core\DependencyInjection\DependencySerializationTrait;
+
+        /**
+         * The id of the original proxied service.
+         *
+         * @var string
+         */
+        protected $drupalProxyOriginalServiceId;
+
+        /**
+         * The real proxied service, after it was lazy loaded.
+         *
+         * @var \Drupal\webform_node\WebformNodeUninstallValidator
+         */
+        protected $service;
+
+        /**
+         * The service container.
+         *
+         * @var \Symfony\Component\DependencyInjection\ContainerInterface
+         */
+        protected $container;
+
+        /**
+         * Constructs a ProxyClass Drupal proxy object.
+         *
+         * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+         *   The container.
+         * @param string $drupal_proxy_original_service_id
+         *   The service ID of the original service.
+         */
+        public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
+        {
+            $this->container = $container;
+            $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
+        }
+
+        /**
+         * Lazy loads the real service from the container.
+         *
+         * @return object
+         *   Returns the constructed real service.
+         */
+        protected function lazyLoadItself()
+        {
+            if (!isset($this->service)) {
+                $this->service = $this->container->get($this->drupalProxyOriginalServiceId);
+            }
+
+            return $this->service;
+        }
+
+        /**
+         * {@inheritdoc}
+         */
+        public function validate($module)
+        {
+            return $this->lazyLoadItself()->validate($module);
+        }
+
+        /**
+         * {@inheritdoc}
+         */
+        public function setStringTranslation(\Drupal\Core\StringTranslation\TranslationInterface $translation)
+        {
+            return $this->lazyLoadItself()->setStringTranslation($translation);
+        }
+
+    }
+
+}
diff --git a/modules/webform_node/src/WebformNodeUninstallValidator.php b/modules/webform_node/src/WebformNodeUninstallValidator.php
new file mode 100644
index 00000000..2399c87d
--- /dev/null
+++ b/modules/webform_node/src/WebformNodeUninstallValidator.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Drupal\webform_node;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslationInterface;
+
+/**
+ * Prevents webform_node module from being uninstalled whilst any webform nodes exist.
+ */
+class WebformNodeUninstallValidator implements ModuleUninstallValidatorInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a new WebformNodeUninstallValidator.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
+   *   The string translation service.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
+    $this->entityTypeManager = $entity_type_manager;
+    $this->stringTranslation = $string_translation;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($module) {
+    $reasons = [];
+    if ($module == 'webform_node') {
+      // The webform node type is provided by the Webform node module. Prevent
+      // uninstall if there are any nodes of that type.
+      if ($this->hasWebformNodes()) {
+        $reasons[] = $this->t('To uninstall Webform node, delete all content that has the Webform content type.');
+      }
+    }
+    return $reasons;
+  }
+
+  /**
+   * Determines if there is any webform nodes or not.
+   *
+   * @return bool
+   *   TRUE if there are webform nodes, FALSE otherwise.
+   */
+  protected function hasWebformNodes() {
+    $nodes = $this->entityTypeManager->getStorage('node')->getQuery()
+      ->condition('type', 'webform')
+      ->accessCheck(FALSE)
+      ->range(0, 1)
+      ->execute();
+    return !empty($nodes);
+  }
+
+}
diff --git a/modules/webform_node/tests/modules/book_breadcrumb_test/book_breadcrumb_test.info.yml b/modules/webform_node/tests/modules/book_breadcrumb_test/book_breadcrumb_test.info.yml
new file mode 100644
index 00000000..f75523ad
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_breadcrumb_test/book_breadcrumb_test.info.yml
@@ -0,0 +1,12 @@
+name: 'Book module breadcrumb tests'
+type: module
+description: 'Support module for book module breadcrumb testing.'
+package: Testing
+# version: VERSION
+# core: 8.x
+
+# Information added by Drupal.org packaging script on 2017-03-25
+version: '8.3.0-rc2+36-dev'
+core: '8.x'
+project: 'drupal'
+datestamp: 1490466235
diff --git a/modules/webform_node/tests/modules/book_breadcrumb_test/book_breadcrumb_test.module b/modules/webform_node/tests/modules/book_breadcrumb_test/book_breadcrumb_test.module
new file mode 100644
index 00000000..526da71d
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_breadcrumb_test/book_breadcrumb_test.module
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Test module for testing the book module breadcrumb.
+ */
+
+use Drupal\Core\Access\AccessResultForbidden;
+use Drupal\Core\Access\AccessResultNeutral;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\node\NodeInterface;
+
+/**
+ * Implements hook_node_access().
+ */
+function book_breadcrumb_test_node_access(NodeInterface $node, $operation, AccountInterface $account) {
+  $config = \Drupal::config('book_breadcrumb_test.settings');
+  if ($config->get('hide') && $node->getTitle() == "you can't see me" && $operation == 'view') {
+    $access = new AccessResultForbidden();
+  }
+  else {
+    $access = new AccessResultNeutral();
+  }
+  $access->addCacheableDependency($config);
+  $access->addCacheableDependency($node);
+  return $access;
+}
diff --git a/modules/webform_node/tests/modules/book_breadcrumb_test/config/install/book_breadcrumb_test.settings.yml b/modules/webform_node/tests/modules/book_breadcrumb_test/config/install/book_breadcrumb_test.settings.yml
new file mode 100644
index 00000000..c68e1aec
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_breadcrumb_test/config/install/book_breadcrumb_test.settings.yml
@@ -0,0 +1 @@
+'hide': false
diff --git a/modules/webform_node/tests/modules/book_breadcrumb_test/config/schema/book_breadcrumb_test.schema.yml b/modules/webform_node/tests/modules/book_breadcrumb_test/config/schema/book_breadcrumb_test.schema.yml
new file mode 100644
index 00000000..3baf5441
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_breadcrumb_test/config/schema/book_breadcrumb_test.schema.yml
@@ -0,0 +1,9 @@
+# Schema for the configuration files of the book_breadcrumb_test module.
+
+book_breadcrumb_test.settings:
+  type: config_object
+  label: 'Book Breadcrumb Test module settings'
+  mapping:
+    hide:
+      type: boolean
+      label: 'Setting for hiding content'
diff --git a/modules/webform_node/tests/modules/book_test/book_test.info.yml b/modules/webform_node/tests/modules/book_test/book_test.info.yml
new file mode 100644
index 00000000..f5b5bbb2
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_test/book_test.info.yml
@@ -0,0 +1,12 @@
+name: 'Book module tests'
+type: module
+description: 'Support module for book module testing.'
+package: Testing
+# version: VERSION
+# core: 8.x
+
+# Information added by Drupal.org packaging script on 2017-03-25
+version: '8.3.0-rc2+36-dev'
+core: '8.x'
+project: 'drupal'
+datestamp: 1490466235
diff --git a/modules/webform_node/tests/modules/book_test/book_test.module b/modules/webform_node/tests/modules/book_test/book_test.module
new file mode 100644
index 00000000..939e7562
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_test/book_test.module
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Test module for testing the book module.
+ *
+ * This module's functionality depends on the following state variables:
+ * - book_test.debug_book_navigation_cache_context: Used in NodeQueryAlterTest to enable the
+ *   node_access_all grant realm.
+ *
+ * @see \Drupal\book\Tests\BookTest::testBookNavigationCacheContext()
+ */
+
+/**
+ * Implements hook_page_attachments().
+ */
+function book_test_page_attachments(array &$page) {
+  $page['#cache']['tags'][] = 'book_test.debug_book_navigation_cache_context';
+  if (\Drupal::state()->get('book_test.debug_book_navigation_cache_context', FALSE)) {
+    drupal_set_message(\Drupal::service('cache_contexts_manager')->convertTokensToKeys(['route.book_navigation'])->getKeys()[0]);
+  }
+}
diff --git a/modules/webform_node/tests/modules/book_test_views/book_test_views.info.yml b/modules/webform_node/tests/modules/book_test_views/book_test_views.info.yml
new file mode 100644
index 00000000..83b75b80
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_test_views/book_test_views.info.yml
@@ -0,0 +1,15 @@
+name: 'Book test views'
+type: module
+description: 'Provides default views for views book tests.'
+package: Testing
+# version: VERSION
+# core: 8.x
+dependencies:
+ - book
+ - views
+
+# Information added by Drupal.org packaging script on 2017-03-25
+version: '8.3.0-rc2+36-dev'
+core: '8.x'
+project: 'drupal'
+datestamp: 1490466235
diff --git a/modules/webform_node/tests/modules/book_test_views/test_views/views.view.test_book_view.yml b/modules/webform_node/tests/modules/book_test_views/test_views/views.view.test_book_view.yml
new file mode 100644
index 00000000..3aeb3a6c
--- /dev/null
+++ b/modules/webform_node/tests/modules/book_test_views/test_views/views.view.test_book_view.yml
@@ -0,0 +1,1059 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - node.type.book
+  module:
+    - node
+    - user
+id: test_book_view
+label: Book
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+core: 8.x
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: tag
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_comment: ''
+          query_tags: {  }
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: full
+        options:
+          items_per_page: 10
+          offset: 0
+          id: 0
+          total_pages: null
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+          tags:
+            previous: '‹ previous'
+            next: 'next ›'
+            first: '« first'
+            last: 'last »'
+          quantity: 9
+      style:
+        type: default
+      row:
+        type: fields
+      fields:
+        title:
+          id: title
+          table: node_field_data
+          field: title
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_1:
+          id: title_1
+          table: node_field_data
+          field: title
+          relationship: bid
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_2:
+          id: title_2
+          table: node_field_data
+          field: title
+          relationship: pid
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_3:
+          id: title_3
+          table: node_field_data
+          field: title
+          relationship: p1
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_4:
+          id: title_4
+          table: node_field_data
+          field: title
+          relationship: p2
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_5:
+          id: title_5
+          table: node_field_data
+          field: title
+          relationship: p3
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_6:
+          id: title_6
+          table: node_field_data
+          field: title
+          relationship: p4
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_7:
+          id: title_7
+          table: node_field_data
+          field: title
+          relationship: p5
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_8:
+          id: title_8
+          table: node_field_data
+          field: title
+          relationship: p6
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_9:
+          id: title_9
+          table: node_field_data
+          field: title
+          relationship: p7
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_10:
+          id: title_10
+          table: node_field_data
+          field: title
+          relationship: p8
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+        title_11:
+          id: title_11
+          table: node_field_data
+          field: title
+          relationship: p9
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+      filters:
+        status:
+          value: '1'
+          table: node_field_data
+          field: status
+          plugin_id: boolean
+          entity_type: node
+          entity_field: status
+          id: status
+          expose:
+            operator: ''
+          group: 1
+        type:
+          id: type
+          table: node_field_data
+          field: type
+          value:
+            book: book
+          entity_type: node
+          entity_field: type
+          plugin_id: bundle
+      sorts:
+        created:
+          id: created
+          table: node_field_data
+          field: created
+          order: DESC
+          entity_type: node
+          entity_field: created
+          plugin_id: date
+          relationship: none
+          group_type: group
+          admin_label: ''
+          exposed: false
+          expose:
+            label: ''
+          granularity: second
+      title: ''
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships:
+        p1:
+          id: p1
+          table: book
+          field: p1
+          relationship: none
+          group_type: group
+          admin_label: 'Book 1st parent'
+          required: false
+          plugin_id: standard
+        p2:
+          id: p2
+          table: book
+          field: p2
+          relationship: none
+          group_type: group
+          admin_label: 'Book 2nd parent'
+          required: false
+          plugin_id: standard
+        p3:
+          id: p3
+          table: book
+          field: p3
+          relationship: none
+          group_type: group
+          admin_label: 'Book 3rd parent'
+          required: false
+          plugin_id: standard
+        p4:
+          id: p4
+          table: book
+          field: p4
+          relationship: none
+          group_type: group
+          admin_label: 'Book 4th parent'
+          required: false
+          plugin_id: standard
+        p5:
+          id: p5
+          table: book
+          field: p5
+          relationship: none
+          group_type: group
+          admin_label: 'Book 5th parent'
+          required: false
+          plugin_id: standard
+        p6:
+          id: p6
+          table: book
+          field: p6
+          relationship: none
+          group_type: group
+          admin_label: 'Book 6th parent'
+          required: false
+          plugin_id: standard
+        p7:
+          id: p7
+          table: book
+          field: p7
+          relationship: none
+          group_type: group
+          admin_label: 'Book 7th parent'
+          required: false
+          plugin_id: standard
+        p8:
+          id: p8
+          table: book
+          field: p8
+          relationship: none
+          group_type: group
+          admin_label: 'Book 8th parent'
+          required: false
+          plugin_id: standard
+        p9:
+          id: p9
+          table: book
+          field: p9
+          relationship: none
+          group_type: group
+          admin_label: 'Book 9th parent'
+          required: false
+          plugin_id: standard
+        pid:
+          id: pid
+          table: book
+          field: pid
+          relationship: none
+          group_type: group
+          admin_label: 'Book Parent'
+          required: false
+          plugin_id: standard
+        bid:
+          id: bid
+          table: book
+          field: bid
+          relationship: none
+          group_type: group
+          admin_label: Book
+          required: false
+          plugin_id: standard
+      arguments:
+        nid:
+          id: nid
+          table: node_field_data
+          field: nid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          default_action: default
+          exception:
+            value: all
+            title_enable: false
+            title: All
+          title_enable: false
+          title: ''
+          default_argument_type: top_level_book
+          default_argument_options: {  }
+          default_argument_skip_url: false
+          summary_options:
+            base_path: ''
+            count: true
+            items_per_page: 25
+            override: false
+          summary:
+            sort_order: asc
+            number_of_records: 0
+            format: default_summary
+          specify_validation: false
+          validate:
+            type: none
+            fail: 'not found'
+          validate_options: {  }
+          break_phrase: false
+          not: false
+          entity_type: node
+          entity_field: nid
+          plugin_id: numeric
+      display_extenders: {  }
+    cache_metadata:
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - 'url.query_args.pagers:0'
+        - 'user.node_grants:view'
+        - user.permissions
+      cacheable: false
+  page_1:
+    display_plugin: page
+    id: page_1
+    display_title: Page
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: test-book
+    cache_metadata:
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - 'url.query_args.pagers:0'
+        - 'user.node_grants:view'
+        - user.permissions
+      cacheable: false
diff --git a/modules/webform_node/tests/src/Kernel/WebformNodeUninstallTest.php b/modules/webform_node/tests/src/Kernel/WebformNodeUninstallTest.php
new file mode 100644
index 00000000..42698a4b
--- /dev/null
+++ b/modules/webform_node/tests/src/Kernel/WebformNodeUninstallTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Drupal\Tests\webform_node\Kernel;
+
+use Drupal\node\Entity\Node;
+use Drupal\node\Entity\NodeType;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests that the Webform node module cannot be uninstalled if webform nodes exist.
+ *
+ * @group webform_node
+ */
+class WebformNodeUninstallTest extends KernelTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['system', 'field', 'filter', 'text', 'user', 'node', 'webform', 'webform_node'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('webform');
+    $this->installEntitySchema('webform_submission');
+    $this->installSchema('node', ['node_access']);
+    $this->installConfig(['system', 'node', 'webform', 'webform_node']);
+    // For uninstall to work.
+    $this->installSchema('user', ['users_data']);
+  }
+
+  /**
+   * Tests the webform_node_uninstall() method.
+   */
+  public function testWebformNodeUninstall() {
+    module_load_include('install', 'webform_node');
+
+    // Check that webform node module can not be installed.
+    $this->assertNotEmpty(webform_node_requirements('install'), 'Webform node module can not be installed.');
+
+    // No nodes exist.
+    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(['webform_node']);
+    $this->assertEqual([], $validation_reasons, 'The webform_node module is not required.');
+
+    $node = Node::create(['title' => $this->randomString(), 'type' => 'webform']);
+    $node->save();
+
+    // Check webform node module can't be ininstalled.
+    $validation_reasons = \Drupal::service('module_installer')->validateUninstall(['webform_node']);
+    $this->assertEqual(['To uninstall Webform node, delete all content that has the Webform content type.'], $validation_reasons['webform_node']);
+
+    $node->delete();
+
+    // Uninstall the Webform node module and check that all webform node have been deleted.
+    \Drupal::service('module_installer')->uninstall(['webform_node']);
+    $this->assertNull(NodeType::load('webform'), "The webform node type does not exist.");
+
+    // Check that webform node module can be installed.
+    $this->assertEmpty(webform_node_requirements('install'), 'Webform node module can be installed.');
+  }
+
+}
diff --git a/modules/webform_node/tests/src/Unit/WebformNodeUninstallValidatorTest.php b/modules/webform_node/tests/src/Unit/WebformNodeUninstallValidatorTest.php
new file mode 100644
index 00000000..487c6cf3
--- /dev/null
+++ b/modules/webform_node/tests/src/Unit/WebformNodeUninstallValidatorTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Drupal\Tests\webform_node\Unit;
+
+use Drupal\simpletest\AssertHelperTrait;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\webform_node\WebformNodeUninstallValidator
+ * @group webform
+ */
+class WebformNodeUninstallValidatorTest extends UnitTestCase {
+
+  use AssertHelperTrait;
+
+  /**
+   * @var \Drupal\webform_node\WebformNodeUninstallValidator|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $webformNodeUninstallValidator;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->webformNodeUninstallValidator = $this->getMockBuilder('Drupal\webform_node\WebformNodeUninstallValidator')
+      ->disableOriginalConstructor()
+      ->setMethods(['hasWebformNodes'])
+      ->getMock();
+    $this->webformNodeUninstallValidator->setStringTranslation($this->getStringTranslationStub());
+  }
+
+  /**
+   * @covers ::validate
+   */
+  public function testValidateNotWebformNode() {
+    $this->webformNodeUninstallValidator->expects($this->never())
+      ->method('hasWebformNodes');
+
+    $module = 'not_webform_node';
+    $expected = [];
+    $reasons = $this->webformNodeUninstallValidator->validate($module);
+    $this->assertSame($expected, $this->castSafeStrings($reasons));
+  }
+
+  /**
+   * @covers ::validate
+   */
+  public function testValidateEntityQueryWithoutResults() {
+    $this->webformNodeUninstallValidator->expects($this->once())
+      ->method('hasWebformNodes')
+      ->willReturn(FALSE);
+
+    $module = 'webform_node';
+    $expected = [];
+    $reasons = $this->webformNodeUninstallValidator->validate($module);
+    $this->assertSame($expected, $this->castSafeStrings($reasons));
+  }
+
+  /**
+   * @covers ::validate
+   */
+  public function testValidateEntityQueryWithResults() {
+    $this->webformNodeUninstallValidator->expects($this->once())
+      ->method('hasWebformNodes')
+      ->willReturn(TRUE);
+
+    $module = 'webform_node';
+    $expected = ['To uninstall Webform node, delete all content that has the Webform content type.'];
+    $reasons = $this->webformNodeUninstallValidator->validate($module);
+    $this->assertSame($expected, $this->castSafeStrings($reasons));
+  }
+
+}
diff --git a/modules/webform_node/webform_node.install b/modules/webform_node/webform_node.install
index 27bb646d..52501807 100644
--- a/modules/webform_node/webform_node.install
+++ b/modules/webform_node/webform_node.install
@@ -5,8 +5,6 @@
  * Install, update and uninstall functions for the webform node module.
  */
 
-use Drupal\node\Entity\NodeType;
-
 /**
  * Implements hook_requirements().
  */
@@ -16,16 +14,8 @@ function webform_node_requirements($phase) {
   // happen during a D7 to D8 content migration.
   // @see https://www.drupal.org/node/2856599
   if ($phase == 'install') {
-    // We have to put the check in a try catch.. otherwise it raise a
-    // NoCorrespondingEntityClassException if this module is a
-    // dependency in a installation profile.
-    try {
-      $node_type = NodeType::load('webform');
-    }
-    catch (Exception $e) {
-      // Do nothing.
-    }
-    if ($node_type) {
+    $manager = \Drupal::entityTypeManager();
+    if ($manager->hasDefinition('node_type') && ($node_type = $manager->getStorage('node_type')->load('webform'))) {
       $requirements['webform_node'] = [
         'title' => t('Webform Node'),
         'description' => t('%title content type already exists, please delete the %title content type before installing the Webform node module.', ['%title' => $node_type->label()]),
@@ -36,20 +26,3 @@ function webform_node_requirements($phase) {
   }
   return $requirements;
 }
-
-/**
- * Implements hook_uninstall().
- */
-function webform_node_uninstall() {
-  // Delete the webform node type.
-  if ($node_type = NodeType::load('webform')) {
-    $node_type->delete();
-  }
-
-  // Delete field storage if it is no longer being used by any bundles.
-  if ($field_storage = \Drupal::entityTypeManager()->getStorage('field_storage_config')->load('node.webform')) {
-    if (!$field_storage->getBundles()) {
-      $field_storage->delete();
-    }
-  }
-}
diff --git a/modules/webform_node/webform_node.module b/modules/webform_node/webform_node.module
index 26f2966b..31fa60c2 100644
--- a/modules/webform_node/webform_node.module
+++ b/modules/webform_node/webform_node.module
@@ -9,6 +9,7 @@ use Drupal\Core\Session\AccountInterface;
 use Drupal\node\NodeInterface;
 use Drupal\Core\Access\AccessResult;
 use Drupal\webform\Plugin\Field\FieldType\WebformEntityReferenceItem;
+use Drupal\Core\Extension\Extension;
 
 /**
  * Implements hook_node_access().
diff --git a/modules/webform_node/webform_node.services.yml b/modules/webform_node/webform_node.services.yml
new file mode 100644
index 00000000..8a98b957
--- /dev/null
+++ b/modules/webform_node/webform_node.services.yml
@@ -0,0 +1,7 @@
+services:
+  webform_node.uninstall_validator:
+    class: Drupal\webform_node\WebformNodeUninstallValidator
+    tags:
+      - { name: module_install.uninstall_validator }
+    arguments: ['@entity_type.manager', '@string_translation']
+    lazy: true
