yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.24k stars 6.91k forks source link

Asset publishing before conversion breaks imports #19792

Closed Pwuts closed 1 year ago

Pwuts commented 1 year ago

https://github.com/yiisoft/yii2/blob/5406e5dad3eaa4e9d58f65bb565d37adc4307f3b/framework/web/AssetBundle.php#L180-L182

This executes:

  1. If sourcePath is set and basePath is not, the asset is published
  2. The published asset is converted

The problem

  1. I want to keep the source files out of the webroot, and only publish the converted output asset. This is currently not possible, since the source files are first published and only then converted.
  2. Yii displays unexpected behavior when both $sourcePath and $basePath are set: instead of converting from $sourcePath into $basePath, it completely ignores $basePath (which is not explicitly documented) and publishes to a hashed asset folder in the webroot.
  3. Suppose I have an index.scss which imports base.scss and ../vendor/package/dep.scss. Because the first step is to copy index.scss to the webroot, the relative imports will break and conversion will subsequently fail.

Two possible solutions:

samdark commented 1 year ago

What if you have images there references from stylesheets?

Pwuts commented 1 year ago

Then it could make sense to publish first, yes... but not in my current use case. Can you help me to solve issue 3 (and maybe 1)?

samdark commented 1 year ago

Sure. This would help copying only what's needed i.e. solve case 1: https://github.com/yiisoft/yii2/blob/5406e5dad3eaa4e9d58f65bb565d37adc4307f3b/framework/web/AssetManager.php#L452 These options could be set on a concrete bundle level via publishOptions.

Pwuts commented 1 year ago

The source folder @app/scss:

scss
  includes
    _file1.scss
    _file2.scss
  lib
    _file3.scss
    _file4.scss
  _variables.scss
  index.scss
  utils.scss

In this case, after conversion, index.css and utils.css are imported/used by views and layouts. The source files index.scss and utils.scss import the other files such as _variables.scss and also a library located somewhere in vendor/ (with a relative path, ../vendor/author/lib/file.scss).

Importing that library still fails because the source files are moved before conversion. I can solve it like this in the config:

// config/web.php

$appRoot = dirname(__DIR__);

/* ... */

$config['components']['assetManager']['converter'] => [
    'commands' => [
        'scss' => ['css', "sass --style=compressed --load-path=$appRoot/vendor {from} {to}"],
    ],
];

It works, but it feels like a bodge. It would be nice if Yii had a better way to prevent this problem, even if it was as simple as alias conversion in the command string e.g. allowing sass --load-path=@app/vendor {from} {to}.