You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.3 KiB

  1. <?php namespace Wpstudio\AssetsManifest\Classes\Bundlers;
  2. use Cms\Classes\Theme;
  3. use Illuminate\Support\Collection;
  4. use Wpstudio\AssetsManifest\Classes\AssetsManifestException;
  5. use Config;
  6. use Wpstudio\AssetsManifest\Classes\Bundlers\Vite\ViteEntrypoint;
  7. class ViteBundler extends Bundler
  8. {
  9. private array $assetsInjected = [];
  10. public function getEntrypointAssets(string $entrypointName): string
  11. {
  12. $entrypoint = $this->getViteEntrypoint($entrypointName);
  13. $tags = collect();
  14. if ($entrypoint->hasImports()) {
  15. $entrypoint->getImports()->filter(fn(string $entrypointNameFromImports) => !$this->hasInjected($entrypointNameFromImports))->each(
  16. fn(string $entrypointNameFromImports) => $this->injectAsset(
  17. $entrypointNameFromImports,
  18. $tags,
  19. $this->getEntrypointAssets($entrypointNameFromImports)
  20. )
  21. );
  22. }
  23. if ($entrypoint->hasCss()) {
  24. $entrypoint->getCss()->filter(fn(string $cssAssetRelativeFilePath) => !$this->hasInjected($cssAssetRelativeFilePath))->each(
  25. fn(string $cssAssetRelativeFilePath) => $this->injectAsset(
  26. $cssAssetRelativeFilePath,
  27. $tags,
  28. $this->getStylesheetTag($this->getViteAssetUrl($cssAssetRelativeFilePath))
  29. )
  30. );
  31. }
  32. if (!$this->hasInjected($entrypointName)) {
  33. $this->injectAsset($entrypointName, $tags, $this->getScriptTag($entrypointName, $entrypoint));
  34. }
  35. return $tags->implode(PHP_EOL);
  36. }
  37. public function getViteDevClientScriptTag(): string
  38. {
  39. return sprintf(
  40. '<script type="module" src="%s"></script>',
  41. sprintf(
  42. '%s/@vite/client',
  43. $this->getViteDevServerAddress(),
  44. )
  45. );
  46. }
  47. /**
  48. * @param string $entrypointName
  49. * @return string
  50. * @throws AssetsManifestException
  51. */
  52. public function getEntrypointStylesheets(string $entrypointName): string
  53. {
  54. if ($this->isViteDevEnabled()) {
  55. return '';
  56. }
  57. $entrypoint = $this->getViteEntrypoint($entrypointName);
  58. $stylesheetTags = collect();
  59. if ($entrypoint->hasCss()) {
  60. $entrypoint
  61. ->getCss()
  62. ->filter(fn(string $cssAssetRelativeFilePath) => !$this->hasInjected($cssAssetRelativeFilePath))
  63. ->each(
  64. fn(string $cssAssetRelativeFilePath) => $this->injectAsset(
  65. $cssAssetRelativeFilePath,
  66. $stylesheetTags,
  67. $this->getStylesheetTag($this->getViteAssetUrl($cssAssetRelativeFilePath)
  68. )
  69. )
  70. );
  71. }
  72. return $stylesheetTags->implode(PHP_EOL);
  73. }
  74. private function getStylesheetTag(string $href): string
  75. {
  76. return sprintf(
  77. '<link rel="stylesheet" href="%s">',
  78. $href,
  79. );
  80. }
  81. private function getScriptTag(string $entrypointName, ViteEntrypoint $entrypoint): string
  82. {
  83. return sprintf(
  84. '<script type="module" src="%s" %s></script>',
  85. $this->isViteDevEnabled() ?
  86. sprintf(
  87. '%s/%s',
  88. $this->getViteDevServerAddress(),
  89. $this->getViteEntrypointSrc($entrypointName)
  90. ) :
  91. $this->getViteAssetUrl($entrypoint->getFile()),
  92. !$this->isViteDevEnabled() ? 'async defer' : '',
  93. );
  94. }
  95. private function getViteEntrypointSrc(string $entrypointName): string
  96. {
  97. return sprintf(
  98. '%s/%s/%s',
  99. Config::get('wpstudio.assetsmanifest::vite_path_src'),
  100. Config::get('wpstudio.assetsmanifest::vite_dir_entrypoints'),
  101. $entrypointName,
  102. );
  103. }
  104. private function getViteEntrypoint(string $entrypointName): ViteEntrypoint
  105. {
  106. return new ViteEntrypoint($this->getEntrypoint(
  107. !starts_with($entrypointName, '_') ?
  108. $this->getViteEntrypointSrc($entrypointName) :
  109. $entrypointName
  110. ));
  111. }
  112. private function getViteAssetUrl(string $relativeAssetsFilePath): string
  113. {
  114. return sprintf(
  115. '/themes/%s/%s/%s',
  116. Theme::getActiveTheme()->getDirName(),
  117. Config::get('wpstudio.assetsmanifest::vite_path_build'),
  118. $relativeAssetsFilePath
  119. );
  120. }
  121. public function isViteDevEnabled(): bool
  122. {
  123. return Config::get('wpstudio.assetsmanifest::vite_dev_enabled');
  124. }
  125. private function getViteDevServerAddress(): string
  126. {
  127. return sprintf(
  128. '%s://%s:%s',
  129. Config::get('wpstudio.assetsmanifest::vite_dev_server_protocol'),
  130. Config::get('wpstudio.assetsmanifest::vite_dev_server_host'),
  131. Config::get('wpstudio.assetsmanifest::vite_dev_server_port'),
  132. );
  133. }
  134. private function hasInjected(string $assetsUid): bool
  135. {
  136. return in_array($assetsUid, $this->assetsInjected);
  137. }
  138. private function injectAsset(string $assetsUid, Collection $tags, string $assetTag): void
  139. {
  140. $this->assetsInjected[] = $assetsUid;
  141. $tags->add($assetTag);
  142. }
  143. }