yiisoft / assets Goto Github PK
View Code? Open in Web Editor NEWAssets management
Home Page: https://www.yiiframework.com/
License: BSD 3-Clause "New" or "Revised" License
Assets management
Home Page: https://www.yiiframework.com/
License: BSD 3-Clause "New" or "Revised" License
workflow:
https://www.yiiframework.com/assets/263ed6ff/css/all.min.css?v=1567695980
)all.min.css
has image reference (../image/new-image-in-old-name.png
)https://www.yiiframework.com/assets/263ed6ff/image/new-image-in-old-name.png
In addition, there are CDN options that store the content completely without considering the query parameter.
server <---> CDN <---> client
The CDN gets a URL that changes from the previous version.
CDN serves the previous content.
There are other problems with appendTimestamp
:
I suggest add version config.
[
'assetManager' => [
'defaultVersion'=> '0.1.0' // or custom string; default version string, if not set
],
]
MyAsset extends AssetBundle {
public $version = '0.3.4' // override version
}
Generated asset URL
https://www.yiiframework.com/assets/263ed6ff/<version>/css/all.min.css
https://www.yiiframework.com/assets/263ed6ff/0.3.4/css/all.min.css
https://www.yiiframework.com/assets/263ed6ff/0.3.4/image/new-image-in-old-name.png
Q | A |
---|---|
Version | 2.x |
PHP version | - |
Operating system | - |
Line 249 in a31b8e9
Often this method used only for one asset:
$assetManager->register([MainAsset::class]);
We can allow use string
or string[]
. In this case using the method will be more convenient:
$assetManager->register(MainAsset::class);
And for several assets, we can use it as now:
$assetManager->register([Asset1::class, Asset2::class]);
See #29 (comment)
Good day. By default AssetPublisher::hash
using max filemtime from assets files to generate unique path name in public. But - if we remove some files/directories which not equals/contains max filemtime, then result of this method will be same and unique name will not be changed. So as idea - add some FileHelper::avgModifiedTime
and change AssetPublisher::hash
to using it. Thanks
public $cssOptions = [ 'media' => 'none', 'onload' => 'media=\'all\'' ];
<link href="/marelin/public_html/assets/21226de2/css/bootstrap.css" rel="stylesheet" media="none" onload="media='all'">
<link href="/marelin/public_html/assets/2169c8c1/css/flag-icon.min.css" rel="stylesheet" media="none" onload="media='all'">
<link href="/marelin/public_html/assets/2318c97f/css/bootstrap-slider.css" rel="stylesheet" media="none" onload="media='all'">
. . .
<link href="/marelin/public_html/assets/21226de2/css/bootstrap.css" rel="stylesheet">
<link href="/marelin/public_html/assets/2169c8c1/css/flag-icon.min.css" rel="stylesheet">
<link href="/marelin/public_html/assets/2318c97f/css/bootstrap-slider.css" rel="stylesheet">
. . .
<link href="/marelin/public_html/css/BootstrapXL.css" rel="stylesheet" media="none" onload="media='all'">
<link href="/marelin/public_html/css/site.css" rel="stylesheet" media="none" onload="media='all'">
<link href="/marelin/public_html/css/main.css" rel="stylesheet" media="none" onload="media='all'">
<link href="/marelin/public_html/css/fontastic.css" rel="stylesheet" media="none" onload="media='all'">
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&amp;subset=cyrillic" rel="stylesheet" media="none" onload="media='all'">
<link href="/marelin/public_html/assets/35e8d075/css/activeform.css" rel="stylesheet">
<link href="/marelin/public_html/assets/485b695f/css/typeahead.css" rel="stylesheet">
<link href="/marelin/public_html/assets/485b695f/css/typeahead-kv.css" rel="stylesheet">
<link href="/marelin/public_html/assets/3db9be1b/css/kv-widgets.css" rel="stylesheet">
Q | A |
---|---|
Yii version | 2.0.11-dev |
PHP version | |
Operating system |
This issue is about asset-management in general for Yii 2.1. While there's already a checked box for "Make fxp composer plugin optional. Describe how to use asset packagist instead." on https://github.com/yiisoft/yii2/wiki/Plan-for-next-major-versions#client-side I still think we need to elaborate on this topic.
bower
In the current state the Yii ecosystem mainly uses bower-asset
s for installing client side scripts (or CSS) packages. This can either be done using https://github.com/fxpio/composer-asset-plugin (cap) or https://github.com/hiqdev/asset-packagist (ap).
One of the main issues with this approach is that bower
is deprecated yiisoft/yii2#14297, and projects start dropping bower support (eg. https://news.ycombinator.com/item?id=10891324, lodash/lodash#2206 (comment), chartjs/Chart.js#3081 {they brought it back, but still...}).
While this currently does not affect "near-core" packages, like jquery or bootstrap, there should be a safe migration path to npm
in planning.
Yii 2.1 should also deprecate bower
usage, while still having the possiblity to use 2.0 extensions with bower via a separate ap-URL, see hiqdev/asset-packagist#67
npm
While both tools mentioned above (cap, ap) are able to work with npm
packages, there might (I'd say will) be huge issues, when switching to npm
packages (ie. hiqdev/asset-packagist#69, hiqdev/asset-packagist#68) One problematic dependency is minimist
- a lib with over 10M downloads ... a week(!). A dependency of over 8000 other projects; details are outlined here - it boils down to flat (composer, bower) vs. tree (npm) installation.
That's also one reason why foxy was created. The basic idea is to use native tooling for client side packages (npm
/yarn
/webpack
- currently), along with package.json
files, while still having a minimal connection for dependency resolution between server and client side packages, for ie. widgets or REST API connectors.
There are also discussions about smooth transitions for older packages, see fxpio/foxy#8
The main question here is: How will Yii2 core-extensions require assets? (should be best-practice)
Using npm-asset/package
looks convenient in the first place, but as layed out above, this might fail even in smaller setups - IMHO we currently do not see issues popping up about this, because only few people use npm-asset
. Another contra is that composer.json
is "polluted" with a package-syntax which does not belong there.
[update] Another con of ap is that every not-registered package will throw an error unless manually registered on their website, which can be pretty cumbersome on projects with a lot of dependencies.
A con using foxy + packages.json
requires node
+ npm
or yarn
to be installed.
[update] There's also a proposal to use a CDN for delivering assets by default, which is not a viable solution IMHO, see yiisoft/yii2#8452 (comment)
The ideal solution would be something where the developers can freely choose which solution they want to use.
Feedback highly appreciated. CC: @yiisoft/core-developers @mikehaertl @tonydspaniard
More related issues/PRs:
Yii2 asset manager specified to any file storage and file serving. There is a small problem with this in a cloud platform.
server A server B server C .... server X
| | | |
\---------------------------------------------------------/
|
LB
|
client browser
Yii2 schema:
Idea:
files serving any servers
not found asset files (onlye copy files server A)
yii2 solution (with my source codes):
Q | A |
---|---|
Version | 2.x |
PHP version | - |
Operating system | - |
Asset classes are now separated from asset files.
// config
return [
'assetName' => [
'baseUrl' => '',
....
],
....
];
// view
$view->registerAsset('assetName');
IDE won't be able to analyze them.
final class TestAsset extends AssetBundle
{
public bool $cdn = true;
public array $css = [
[
'https://cdn.jsdelivr.net/example.css',
],
];
}
Error:
ERROR: NonInvariantDocblockPropertyType - src/TestAsset.php:11:18 - Property Yiisoft\Assets\TestAsset::$css has type array<array-key, mixed>, not invariant with Yiisoft\Assets\AssetBundle::$css of type array<array-key, array{0: string, 1?: int}|string> (see https://psalm.dev/267)
public array $css = [
Suggestions by @devanych:
The AssetManager class has become complex and will be difficult to maintain. Need to think about how to divide it into responsibilities. For example, adding an internal AssetRegistarator class and put all the CSS and JS manipulations in it.
Support manifest.json generated by webpack/vite (e.g. https://vitejs.dev/guide/backend-integration.html)
Like in https://symfony.com/doc/current/components/asset.html#json-file-manifest
It would be nice if we can pass plain JS code and jsVar to the view from the Asset.
I used this in Yii2 from register
and/or registerAssetFiles
:
public function registerAssetFiles($view): void
{
parent::registerAssetFiles($view);
$view->registerJs("bsCustomFileInput.init();", View::POS_READY);
$view->registerJsVar('pwdToggleLng', ['hide' => _('Hide Password'), 'show' => _('Show Password')]);
}
This doesn't seem possible anymore.
There is not way to pass configuration into AssetBundle
class to a contructor, only to public properties.
I'd like to have a method that accepts an object of AssetBundle
and registers it as it does with a class of AssetBundle
.
$assetManager->registerBundle(new AssetBundle())
When registering JS files, I'd like to register them with assets. According to [the documentation][1], it's possible to declare JS files with options as HTML attributes — save a few. Doing this causes an issue when converting the JS file. #89 attempts to fix this, but needs some touching up to ensure it builds properly
In src/Asset/AppAsset.php
declare JS files as
public array $js = [
'js/site.js' => [
'foo' => 'bar',
]
];
<script src="/assets/br34d3d/js/site.js" foo="bar"></script>
Yiisoft\ErrorHandler\Exception\ErrorException: Undefined array key 0 in /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/assets/src/AssetRegistrar.php:246
Stack trace:
#0 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/assets/src/AssetRegistrar.php(246): Yiisoft\ErrorHandler\ErrorHandler::Yiisoft\ErrorHandler\{closure}(2, 'Undefined array...', '/Users/igbanam/...', 246)
#1 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/assets/src/AssetRegistrar.php(143): Yiisoft\Assets\AssetRegistrar->convertJs(Object(App\Asset\AppAsset))
#2 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/assets/src/AssetManager.php(394): Yiisoft\Assets\AssetRegistrar->register(Object(App\Asset\AppAsset))
#3 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/assets/src/AssetManager.php(256): Yiisoft\Assets\AssetManager->registerFiles('App\\Asset\\AppAs...')
#4 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/assets/src/AssetManager.php(272): Yiisoft\Assets\AssetManager->register('App\\Asset\\AppAs...', NULL, NULL)
#5 /Users/igbanam/projects/igbanam/memscape/resources/views/layout/main.php(23): Yiisoft\Assets\AssetManager->registerMany(Array)
#6 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/view/src/PhpTemplateRenderer.php(28): require('/Users/igbanam/...')
#7 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/view/src/PhpTemplateRenderer.php(37): Yiisoft\View\PhpTemplateRenderer->Yiisoft\View\{closure}('/Users/igbanam/...', Array)
#8 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/view/src/ViewTrait.php(449): Yiisoft\View\PhpTemplateRenderer->render(Object(Yiisoft\View\WebView), '/Users/igbanam/...', Array)
#9 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/yii-view/src/ViewRenderer.php(339): Yiisoft\View\WebView->renderFile('/Users/igbanam/...', Array)
#10 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/yii-view/src/ViewRenderer.php(119): Yiisoft\Yii\View\ViewRenderer->renderProxy('index', Array, Array, Array, Array, Array)
#11 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/data-response/src/DataResponse.php(324): Yiisoft\Yii\View\ViewRenderer->Yiisoft\Yii\View\{closure}()
#12 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/data-response/src/Formatter/HtmlDataResponseFormatter.php(43): Yiisoft\DataResponse\DataResponse->getData()
#13 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/data-response/src/DataResponse.php(353): Yiisoft\DataResponse\Formatter\HtmlDataResponseFormatter->format(Object(Yiisoft\DataResponse\DataResponse))
#14 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/data-response/src/DataResponse.php(146): Yiisoft\DataResponse\DataResponse->formatResponse()
#15 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/yii-debug/src/Collector/RequestCollector.php(48): Yiisoft\DataResponse\DataResponse->getStatusCode()
#16 [internal function]: Yiisoft\Yii\Debug\Collector\RequestCollector->collect(Object(Yiisoft\Yii\Http\Event\AfterRequest))
#17 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/injector/src/Injector.php(66): ReflectionFunction->invokeArgs(Array)
#18 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/yii-event/src/ListenerCollectionFactory.php(54): Yiisoft\Injector\Injector->invoke(Object(Closure), Array)
#19 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/event-dispatcher/src/Dispatcher/Dispatcher.php(34): Yiisoft\Yii\Event\ListenerCollectionFactory->Yiisoft\Yii\Event\{closure}(Object(Yiisoft\Yii\Http\Event\AfterRequest))
#20 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/yii-debug/src/Proxy/EventDispatcherInterfaceProxy.php(25): Yiisoft\EventDispatcher\Dispatcher\Dispatcher->dispatch(Object(Yiisoft\Yii\Http\Event\AfterRequest))
#21 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/yii-http/src/Application.php(89): Yiisoft\Yii\Debug\Proxy\EventDispatcherInterfaceProxy->dispatch(Object(Yiisoft\Yii\Http\Event\AfterRequest))
#22 /Users/igbanam/projects/igbanam/memscape/vendor/yiisoft/yii-runner-http/src/HttpApplicationRunner.php(209): Yiisoft\Yii\Http\Application->handle(Object(HttpSoft\Message\ServerRequest))
#23 /Users/igbanam/projects/igbanam/memscape/public/index.php(35): Yiisoft\Yii\Runner\Http\HttpApplicationRunner->run()
#24 {main}
Q | A |
---|---|
Version | 3.0 |
PHP version | 8.1 |
Operating system | OS X |
Currently the AssetManager
does a lot:
Ideally this would be split into several smaller interfaces; this allows for replacing specific content.
Currently we don't have an interface for asset bundles, meaning that asset managers code against the specific implementation and it is unclear what subclasses are allowed and not allowed to change.
In view files when load asset with wrong namespace.
// @var Yiisoft\Assets\AssetManager $assetManager
$assetManager->register(\wrong\namespace\AppAsset::class);
It happening here loadBundle() ---> AssetUtil::createAsset()
https://github.com/yiisoft/assets/blob/4.0.0/src/AssetLoader.php#L102
https://github.com/yiisoft/assets/blob/4.0.0/src/AssetUtil.php#L44
Expected throw exception
Got empty instance of AssetBundle
Q | A |
---|---|
Version | 4.0.0 |
PHP version | 8.0 |
Operating system |
When Yii copies/symlinks files into the asset base path webroot/assets if the directory doesn't exist it throws an error. Shouldn't Yii create the base path if it doesn't exist?
Q | A |
---|---|
Yii version | 2.0.15 |
PHP version | 7 |
Operating system | Mac/Linux |
It would be nice if we have $links = []
in asset bundles for registering link tags.
My use case for example is preloading an SVG file that is used in combination with a JS and CSS file for SVG icons.
I'm sure other use cases exist.
Good afternoon, everyone. The documentation describes an example of how to resolve assets from a console command. But - this example does not work without a thorough edit of the configuration, because all dependencies are described in relation to the web. Is it possible to move these dependencies to common and add possibility to switch off publisher at will (add possibility to set it to null in a method). Thanks in advance
Design problem that does not verify the filetime change of the files in the sourcePath directory.
After change sources Its should update css file.
Issues: yiisoft/yii2#17620, yiisoft/yii2#8197
I believe that we can implement the craft solution @brandonkelly yiisoft/yii2#8197 (comment) , which is proven to work in craft, in terms of performance, today almost all accommodations are cloud with ssd support, also use the latest PHP version which is the fastest, i believe that performance would not be affected.
Additionally we can eliminate the forceCopy()
options, and create isCheckFileRecursive, and its behavior would be true, we do the recursive check, in case we are developing, and in case we are in production we change it to false eliminating said check, since the ccs files sourcePath would not change, just checking the directory's filetime as it is right now.
Q | A |
---|---|
Version | 3.0 |
PHP version | 7.4 |
Operating system | Centos 8 |
Suggestion by @devanych:
I don't like that we have an implicit dependency on yiisoft/view. Namely, by positions (WebView:: POSITION_HEAD, WebView::POSITION_END , etc.). Need to think about how to get away from this. For example, move these constants to the yiisoft/html package.
Create asset class and render it.
<?php
use Yiisoft\Assets\AssetBundle;
final class CdnFontAwesomeAsset extends AssetBundle
{
public bool $cdn = true;
public array $css = [
'https://use.fontawesome.com/releases/v5.13.0/css/all.css'
];
}
Link to use.fontawesome.com
in css styles list:
https://use.fontawesome.com/releases/v5.13.0/css/all.css
Link with my domain name prefix:
https://my.site/https://use.fontawesome.com/releases/v5.13.0/css/all.css
Q | A |
---|---|
Version | 1.0.? |
PHP version | |
Operating system |
public ?string $basePath = '@assets';
public ?string $baseUrl = '@assetsUrl';
public ?string $sourcePath = '@resources/assets/css';
public array $css = [
'site.scss',
];
public array $converterOptions = [
'scss' => '-I /path/to/bootstrap/scss',
];
sass -I /path/to/bootstrap/scss '/path/to/assets/ce37712/site.scss' '/path/to/assets/ce37712/site.css'
Testing this on the command line works and css is created.
sass '-I /path/to/bootstrap/scss' '/path/to/assets/ce37712/site.scss' '/path/to/assets/ce37712/site.css'
Testing this on the command line leads to errors:
Error: File to import not found or unreadable: functions.
Load path: /path/to/bootstrap/scss/ /path/to/bootstrap/scss
on line 1 of /path/to/assets/ce37712/bootstrap.scss
from line 8 of /path/to/assets/ce37712/site.scss
Q | A |
---|---|
Version | current dev |
PHP version | 7.4.6 |
Operating system | Debian 9 |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.