From e6fca326a576557d0a25c14cab9561846a8372ed Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Tue, 26 Sep 2023 12:24:35 +0200 Subject: [PATCH 1/4] BUGFIX: Reduce nodetype schema size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this change the following optimisations are done to improve speed and reduce size of the schema generation: * Abstract nodetypes are not queried anymore for constraints as they are already resolved by the nodetype manager. * Entries in the inheritance map and constraints will be skipped if they don’t contain any data. These optimisations reduce the size of the schema in the Neos.Demo from ~380KB to ~307KB and improve the response time by ~20%. The more nodetypes a project has, the bigger the benefit is. --- .../Classes/Service/NodeTypeSchemaBuilder.php | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php index 50f5347bee2..c9464c20770 100644 --- a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php +++ b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php @@ -12,7 +12,6 @@ */ use Neos\Flow\Annotations as Flow; -use Neos\ContentRepository\Domain\Model\NodeType; /** * Renders the Node Type Schema in a format the User Interface understands; additionally pre-calculating node constraints @@ -54,19 +53,24 @@ public function generateNodeTypeSchema() 'constraints' => $this->generateConstraints() ]; + // We need to include abstract nodetypes as the UI required some basic types like Neos.Neos:Document and Neos.Neos:Content $nodeTypes = $this->nodeTypeManager->getNodeTypes(true); - /** @var NodeType $nodeType */ foreach ($nodeTypes as $nodeTypeName => $nodeType) { if ($nodeType->isAbstract() === false) { $configuration = $nodeType->getFullConfiguration(); $schema['nodeTypes'][$nodeTypeName] = $configuration; $schema['nodeTypes'][$nodeTypeName]['label'] = $nodeType->getLabel(); + + // Remove the postprocessors, as they are not needed in the UI + unset($schema['nodeTypes'][$nodeTypeName]['postprocessors']); } - $schema['inheritanceMap']['subTypes'][$nodeTypeName] = []; - foreach ($this->nodeTypeManager->getSubNodeTypes($nodeType->getName(), true) as $subNodeType) { - /** @var NodeType $subNodeType */ - $schema['inheritanceMap']['subTypes'][$nodeTypeName][] = $subNodeType->getName(); + $subTypes = []; + foreach ($this->nodeTypeManager->getSubNodeTypes($nodeType->getName(), false) as $subNodeType) { + $subTypes[] = $subNodeType->getName(); + } + if ($subTypes) { + $schema['inheritanceMap']['subTypes'][$nodeTypeName] = $subTypes; } } @@ -81,29 +85,31 @@ public function generateNodeTypeSchema() protected function generateConstraints() { $constraints = []; - $nodeTypes = $this->nodeTypeManager->getNodeTypes(true); - /** @var NodeType $nodeType */ + $nodeTypes = $this->nodeTypeManager->getNodeTypes(false); foreach ($nodeTypes as $nodeTypeName => $nodeType) { - if ($nodeType->isAbstract()) { - continue; - } - $constraints[$nodeTypeName] = [ - 'nodeTypes' => [], - 'childNodes' => [] - ]; + $nodeTypeConstraints = []; + $childNodeConstraints = []; + foreach ($nodeTypes as $innerNodeTypeName => $innerNodeType) { if ($nodeType->allowsChildNodeType($innerNodeType)) { - $constraints[$nodeTypeName]['nodeTypes'][$innerNodeTypeName] = true; + $nodeTypeConstraints[$innerNodeTypeName] = true; } } - foreach ($nodeType->getAutoCreatedChildNodes() as $key => $_x) { + foreach (array_keys($nodeType->getAutoCreatedChildNodes()) as $key) { foreach ($nodeTypes as $innerNodeTypeName => $innerNodeType) { if ($nodeType->allowsGrandchildNodeType($key, $innerNodeType)) { - $constraints[$nodeTypeName]['childNodes'][$key]['nodeTypes'][$innerNodeTypeName] = true; + $childNodeConstraints[$key]['nodeTypes'][$innerNodeTypeName] = true; } } } + + if ($nodeTypeConstraints || $childNodeConstraints) { + $constraints[$nodeTypeName] = [ + 'nodeTypes' => $nodeTypeConstraints, + 'childNodes' => $childNodeConstraints, + ]; + } } return $constraints; From 4289980987fc34da4897fb4ea3a958fd8841efb0 Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Fri, 13 Oct 2023 14:09:45 +0200 Subject: [PATCH 2/4] TASK: Ignore abstract nodetypes except the ones required by the Neos.UI --- .../Classes/Service/NodeTypeSchemaBuilder.php | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php index c9464c20770..43c51b5495d 100644 --- a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php +++ b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php @@ -26,6 +26,16 @@ class NodeTypeSchemaBuilder */ protected $nodeTypeManager; + /** + * The Neos UI package needs a few additional abstract nodetypes to be present in the schema. + * This will be properly cleaned up when this service is moved into the Neos.UI package as we only + * need the schema there. + * + * @Flow\InjectConfiguration(path="nodeTypeRoles", package="Neos.Neos.Ui") + * @var array + */ + protected $nodeTypeRoles; + /** * The preprocessed node type schema contains everything we need for the UI: * @@ -53,8 +63,17 @@ public function generateNodeTypeSchema() 'constraints' => $this->generateConstraints() ]; - // We need to include abstract nodetypes as the UI required some basic types like Neos.Neos:Document and Neos.Neos:Content - $nodeTypes = $this->nodeTypeManager->getNodeTypes(true); + // We need skip abstract nodetypes as they are not instantiated by the UI + $nodeTypes = $this->nodeTypeManager->getNodeTypes(false); + + // Get special abstract nodetypes required by the Neos.UI + if ($this->nodeTypeRoles) { + $additionalNodeTypeNames = array_values($this->nodeTypeRoles); + foreach ($additionalNodeTypeNames as $additionalNodeTypeName) { + $nodeTypes[$additionalNodeTypeName] = $this->nodeTypeManager->getNodeType($additionalNodeTypeName); + } + } + foreach ($nodeTypes as $nodeTypeName => $nodeType) { if ($nodeType->isAbstract() === false) { $configuration = $nodeType->getFullConfiguration(); From f0d9b6f0b48c8a73dbb35355304d22e53b9ba9ba Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Mon, 23 Oct 2023 15:46:05 +0200 Subject: [PATCH 3/4] TASK: Unset postprocessors for abstract nodetypes too --- Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php index 43c51b5495d..46a76f65d14 100644 --- a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php +++ b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php @@ -75,15 +75,16 @@ public function generateNodeTypeSchema() } foreach ($nodeTypes as $nodeTypeName => $nodeType) { + // Skip abstract nodetypes which might have been added by the Neos.UI `nodeTypeRoles` configuration if ($nodeType->isAbstract() === false) { $configuration = $nodeType->getFullConfiguration(); $schema['nodeTypes'][$nodeTypeName] = $configuration; $schema['nodeTypes'][$nodeTypeName]['label'] = $nodeType->getLabel(); - - // Remove the postprocessors, as they are not needed in the UI - unset($schema['nodeTypes'][$nodeTypeName]['postprocessors']); } + // Remove the postprocessors, as they are not needed in the UI + unset($schema['nodeTypes'][$nodeTypeName]['postprocessors']); + $subTypes = []; foreach ($this->nodeTypeManager->getSubNodeTypes($nodeType->getName(), false) as $subNodeType) { $subTypes[] = $subNodeType->getName(); From 49da2daa8f0cbcb847f4f52be39ea38bd45d44a7 Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Wed, 25 Oct 2023 12:18:40 +0200 Subject: [PATCH 4/4] =?UTF-8?q?TASK:=20Adjust=20tests=20now=20that=20the?= =?UTF-8?q?=20schema=20doesn=E2=80=99t=20contain=20every=20abstract=20node?= =?UTF-8?q?type=20anymore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Functional/Service/NodeTypeSchemaBuilderTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php b/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php index e2f6ad07c1d..87ebb3cb455 100644 --- a/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php +++ b/Neos.Neos/Tests/Functional/Service/NodeTypeSchemaBuilderTest.php @@ -80,11 +80,11 @@ public function theNodeTypeSchemaIncludesSubTypesInheritanceMap() { $subTypesDefinition = $this->schema['inheritanceMap']['subTypes']; - self::assertContains('Neos.Neos.BackendSchemaControllerTest:Document', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Node']); - self::assertContains('Neos.Neos.BackendSchemaControllerTest:Content', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Node']); - self::assertContains('Neos.Neos.BackendSchemaControllerTest:Page', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Node']); - self::assertContains('Neos.Neos.BackendSchemaControllerTest:SubPage', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Node']); - self::assertContains('Neos.Neos.BackendSchemaControllerTest:Text', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Node']); + self::assertContains('Neos.Neos.BackendSchemaControllerTest:Page', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Document']); + self::assertContains('Neos.Neos.BackendSchemaControllerTest:Folder', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Document']); + self::assertContains('Neos.Neos.BackendSchemaControllerTest:SubPage', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Page']); + self::assertContains('Neos.Neos.BackendSchemaControllerTest:Text', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Content']); + self::assertContains('Neos.Neos.BackendSchemaControllerTest:TwoColumn', $subTypesDefinition['Neos.Neos.BackendSchemaControllerTest:Content']); } /**