sensiolabs / minify-bundle

Asset Minifier for Symfony Asset Mapper - Made by SensioLabs
MIT License
34 stars 4 forks source link

Comment "stimulusFetch: 'lazy'" is dropped from Stimulus Controller #10

Open Kocal opened 2 days ago

Kocal commented 2 days ago

Hey :)

Given my Stimulus controller:

import { redo as commandRedo, undo as commandUndo } from "@codemirror/commands";
import { markdown } from "@codemirror/lang-markdown";
import { Compartment, EditorSelection } from "@codemirror/state";
import { githubDark } from "@fsegurai/codemirror-theme-github-dark";
import { githubLight } from "@fsegurai/codemirror-theme-github-light";
import { Controller } from "@hotwired/stimulus";
import { EditorView, basicSetup } from "codemirror";
import { codeLanguages } from "../codemirror/code_languages.js";
import { lightDarkThemeSwitcher } from "../codemirror/light_dark_theme_switcher.js";

/* stimulusFetch: 'lazy' */
export default class extends Controller {
    static targets = ["textarea"];
    static classes = ["editor"];

    /* ... */
}

After being minified, the comment /* stimulusFetch: 'lazy' */ disappear from the source code:

image

Which load the controller (even if not needed since there are no data-controller="markdown-editor" on the page) and load all the dependencies (a lot):

image
Kocal commented 2 days ago

I've tried to add a ! to the comment, like this: /*! stimulusFetch: 'lazy' */, it's usually something that tell minifiers to NOT remove the comment, thus, Minify supports that behavior for CSS (https://github.com/tdewolff/minify#css) but for JS I don't know.

Anyway, if I use the new comment like that:

import { redo as commandRedo, undo as commandUndo } from "@codemirror/commands";
import { markdown } from "@codemirror/lang-markdown";
import { Compartment, EditorSelection } from "@codemirror/state";
import { githubDark } from "@fsegurai/codemirror-theme-github-dark";
import { githubLight } from "@fsegurai/codemirror-theme-github-light";
import { Controller } from "@hotwired/stimulus";
import { EditorView, basicSetup } from "codemirror";
import { codeLanguages } from "../codemirror/code_languages.js";
import { lightDarkThemeSwitcher } from "../codemirror/light_dark_theme_switcher.js";

/*! stimulusFetch: 'lazy' */
export default class extends Controller {
    static targets = ["textarea"];
    static classes = ["editor"];

Then I see the comment being at the very top of the file:

image

And the lazy-loading behavior still not works.

smnandre commented 20 hours ago

Is it happening both for asset-map:compile and Minify:asset command or just the later?

MatTheCat commented 17 hours ago

See https://github.com/tdewolff/minify/issues/552

MatTheCat commented 5 hours ago

Okay dug a little bit deeper and minify will only keep a comment if

So we could make this work by putting /*! stimulusFetch: 'lazy' */ on top of lazy controllers, and updating the StimulusBundle’s regexp so that it allows the exclamation mark…

MatTheCat commented 5 hours ago

Just thought of something simpler :sweat_smile:

StimulusBundle’s ControllersMapGenerator checks for the comment in the compiled asset: https://github.com/symfony/stimulus-bundle/blob/60ec83e56c94d441eae0c33d858addf6f1c780dd/src/AssetMapper/ControllersMapGenerator.php#L80

Always checking against the source file content would solve this issue:

- $content = $asset->content ?: file_get_contents($asset->sourcePath);
+ $content = file_get_contents($asset->sourcePath);

I feel like it would make sense :thinking:

smnandre commented 1 hour ago

Are you sure this does not work with AssetMapper ? When i tested it i’m pretty sure it did, but i may had another implémentation at that point

smnandre commented 1 hour ago

(i’m 100km from my computer right now ^^)

MatTheCat commented 1 hour ago

Yes I successfully reproduced what @Kocal reported: given the following controller:

import { Controller } from '@hotwired/stimulus';

/* stimulusFetch: 'lazy' */
export default class extends Controller {
    connect() {
        this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
    }
}

The ControllersMapGenerator gets the following to search /* stimulusFetch: 'lazy' */ in:

import{Controller}from"@hotwired/stimulus";export default class extends Controller{connect(){this.element.textContent="Hello Stimulus! Edit me in assets/controllers/hello_controller.js"}}

It doesn’t find the comment and thus considers the controller to be loaded eagerly.

https://github.com/symfony/ux/pull/2304 should fix this issue :crossed_fingers: