Repository: symfony/ux
Pull request #2304 (2024-10-26 10:12:41)

[StimulusBundle] Check controllers source files for laziness
| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| Issues        | Fix https://github.com/sensiolabs/minify-bundle/issues/10
| License       | MIT

The StimulusBundle allows to mark a controller as lazy using a `/* stimulusFetch: 'lazy' */` comment, but it will be searched in said controller’s *compiled* content. If the compilation removes that comment (it typically happens when using minifiers), then the controller is no longer considered lazy by the `ControllersMapGenerator`.

This PR makes the comment searched in source files, so that its presence doesn’t depend on the compilation’s result.

MatTheCat: I guess it would break compilers wanting to interact with the StimulusBundle by adding or removing the `/* stimulusFetch: 'lazy' */` comment from controllers. Would these have a reason to exist? :thinking: 
smnandre: It feels to me a very internal matter... and a very logical change.

> To make one of your custom controllers lazy, add a special comment on top: [...]

To me it's never an AssetMapper thing, but a source code thing, so.. 

I'd even call this a feature to be honest , as it would remove the following constraint:

> [!NOTE]
>  If you write your controllers using TypeScript, make sure removeComments is **not** set to true in your TypeScript config.

https://symfony.com/bundles/StimulusBundle/current/index.html#lazy-stimulus-controllers

So i'm clearly 👍  on this

@MatTheCat  Do you think you could add a test or two ? 
MatTheCat: Test added!

Patch:
diff --git a/src/StimulusBundle/src/AssetMapper/ControllersMapGenerator.php b/src/StimulusBundle/src/AssetMapper/ControllersMapGenerator.php
index 4eb66984..b99f5ffb 100644
--- a/src/StimulusBundle/src/AssetMapper/ControllersMapGenerator.php
+++ b/src/StimulusBundle/src/AssetMapper/ControllersMapGenerator.php
@@ -77,7 +77,7 @@ class ControllersMapGenerator
             $name = str_replace(['_', '/', '\\'], ['-', '--', '--'], $name);
 
             $asset = $this->assetMapper->getAssetFromSourcePath($file->getRealPath());
-            $content = $asset->content ?: file_get_contents($asset->sourcePath);
+            $content = file_get_contents($asset->sourcePath);
             $isLazy = preg_match('/\/\*\s*stimulusFetch:\s*\'lazy\'\s*\*\//i', $content);
 
             $controllersMap[$name] = new MappedControllerAsset($asset, $isLazy);


Test patch:
diff --git a/src/StimulusBundle/tests/AssetMapper/ControllerMapGeneratorTest.php b/src/StimulusBundle/tests/AssetMapper/ControllersMapGeneratorTest.php
similarity index 89%
rename from src/StimulusBundle/tests/AssetMapper/ControllerMapGeneratorTest.php
rename to src/StimulusBundle/tests/AssetMapper/ControllersMapGeneratorTest.php
index 11cbfe42..21277b28 100644
--- a/src/StimulusBundle/tests/AssetMapper/ControllerMapGeneratorTest.php
+++ b/src/StimulusBundle/tests/AssetMapper/ControllersMapGeneratorTest.php
@@ -20,7 +20,7 @@ use Symfony\UX\StimulusBundle\AssetMapper\ControllersMapGenerator;
 use Symfony\UX\StimulusBundle\AssetMapper\MappedControllerAutoImport;
 use Symfony\UX\StimulusBundle\Ux\UxPackageReader;
 
-class ControllerMapGeneratorTest extends TestCase
+class ControllersMapGeneratorTest extends TestCase
 {
     public function testGetControllersMap()
     {
@@ -41,7 +41,12 @@ class ControllerMapGeneratorTest extends TestCase
                     $logicalPath = substr($path, $assetsPosition + 1);
                 }
 
-                return new MappedAsset($logicalPath, $path, content: file_get_contents($path));
+                $content = null;
+                if (str_ends_with($path, 'minified-controller.js')) {
+                    $content = 'import{Controller}from"@hotwired/stimulus";export default class extends Controller{}';
+                }
+
+                return new MappedAsset($logicalPath, $path, content: $content);
             });
 
         $packageReader = new UxPackageReader(__DIR__.'/../fixtures');
@@ -73,8 +78,8 @@ class ControllerMapGeneratorTest extends TestCase
         $map = $generator->getControllersMap();
         // + 3 controller.json UX controllers
         // - 1 controllers.json UX controller is disabled
-        // + 9 custom controllers (1 file is not a controller & 1 is overridden)
-        $this->assertCount(11, $map);
+        // + 10 custom controllers (1 file is not a controller & 1 is overridden)
+        $this->assertCount(12, $map);
         $packageNames = array_keys($map);
         sort($packageNames);
         $this->assertSame([
@@ -84,6 +89,7 @@ class ControllerMapGeneratorTest extends TestCase
             'hello',
             'hello-with-dashes',
             'hello-with-underscores',
+            'minified',
             'other',
             'subdir--deeper',
             'subdir--deeper-with-dashes',
@@ -115,5 +121,8 @@ class ControllerMapGeneratorTest extends TestCase
 
         $otherController = $map['other'];
         $this->assertTrue($otherController->isLazy);
+
+        $minifiedController = $map['minified'];
+        $this->assertTrue($minifiedController->isLazy);
     }
 }
diff --git a/src/StimulusBundle/tests/AssetMapper/StimulusControllerLoaderFunctionalTest.php b/src/StimulusBundle/tests/AssetMapper/StimulusControllerLoaderFunctionalTest.php
index 877073ff..58bb6c8c 100644
--- a/src/StimulusBundle/tests/AssetMapper/StimulusControllerLoaderFunctionalTest.php
+++ b/src/StimulusBundle/tests/AssetMapper/StimulusControllerLoaderFunctionalTest.php
@@ -63,8 +63,9 @@ class StimulusControllerLoaderFunctionalTest extends WebTestCase
                 // 2x from UX packages, which are enabled in controllers.json
                 '/assets/fake-vendor/ux-package1/package-controller-second.js',
                 '/assets/fake-vendor/ux-package2/package-hello-controller.js',
-                // 2x from more-controllers
+                // 3x from more-controllers
                 '/assets/more-controllers/hello-controller.js',
+                '/assets/more-controllers/minified-controller.js',
                 '/assets/more-controllers/other-controller.js',
                 // 5x from importmap.php
                 '@hotwired/stimulus',
diff --git a/src/StimulusBundle/tests/fixtures/assets/more-controllers/minified-controller.js b/src/StimulusBundle/tests/fixtures/assets/more-controllers/minified-controller.js
new file mode 100644
index 00000000..2eb85a71
--- /dev/null
+++ b/src/StimulusBundle/tests/fixtures/assets/more-controllers/minified-controller.js
@@ -0,0 +1,6 @@
+// minified-controller.js
+import { Controller } from '@hotwired/stimulus';
+
+/* stimulusFetch: 'lazy' */
+export default class extends Controller {
+}