diff --git a/.github/workflows/ci-node.yml b/.github/workflows/ci-node.yml index 345ef1b6e70..0b2a81c63e3 100644 --- a/.github/workflows/ci-node.yml +++ b/.github/workflows/ci-node.yml @@ -22,9 +22,6 @@ jobs: - name: Install dependencies. run: composer update $DEFAULT_COMPOSER_FLAGS - - name: Install JQuery `3.6.*@stable` for tests. - run: composer require "bower-asset/jquery:3.6.*@stable" - - name: Install node.js. uses: actions/setup-node@v4 with: diff --git a/composer.json b/composer.json index 7c9f043fbbc..6f8bfd290df 100644 --- a/composer.json +++ b/composer.json @@ -74,11 +74,7 @@ "lib-pcre": "*", "yiisoft/yii2-composer": "~2.0.4", "ezyang/htmlpurifier": "^4.17", - "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0", - "bower-asset/jquery": "3.7.*@stable | 3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", - "bower-asset/inputmask": "^5.0.8 ", - "bower-asset/punycode": "^2.2", - "bower-asset/yii2-pjax": "~2.0.1" + "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0" }, "require-dev": { "cebe/indent": "~1.0.2", @@ -87,12 +83,6 @@ "phpunit/phpunit": "9.6", "yiisoft/yii2-coding-standards": "^3.0" }, - "repositories": [ - { - "type": "composer", - "url": "https://asset-packagist.org" - } - ], "suggest": { "yiisoft/yii2-coding-standards": "you can use this package to check for code style issues when contributing to yii" }, diff --git a/composer.lock b/composer.lock index 112a5d9aa07..ff94b80965f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,83 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "67f4619312f2cbd6fe508df0d6219a2f", + "content-hash": "ed4b356d1fcdd0d1bb3c83fcd2506193", "packages": [ - { - "name": "bower-asset/inputmask", - "version": "5.0.9", - "source": { - "type": "git", - "url": "https://github.com/RobinHerbots/Inputmask.git", - "reference": "310a33557e2944daf86d5946a5e8c82b9118f8f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/310a33557e2944daf86d5946a5e8c82b9118f8f7", - "reference": "310a33557e2944daf86d5946a5e8c82b9118f8f7" - }, - "require": { - "bower-asset/jquery": ">=1.7" - }, - "type": "bower-asset", - "license": [ - "http://opensource.org/licenses/mit-license.php" - ] - }, - { - "name": "bower-asset/jquery", - "version": "3.7.1", - "source": { - "type": "git", - "url": "https://github.com/jquery/jquery-dist.git", - "reference": "fde1f76e2799dd877c176abde0ec836553246991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/fde1f76e2799dd877c176abde0ec836553246991", - "reference": "fde1f76e2799dd877c176abde0ec836553246991" - }, - "type": "bower-asset", - "license": [ - "MIT" - ] - }, - { - "name": "bower-asset/punycode", - "version": "v2.3.1", - "source": { - "type": "git", - "url": "https://github.com/mathiasbynens/punycode.js.git", - "reference": "9e1b2cda98d215d3a73fcbfe93c62e021f4ba768" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mathiasbynens/punycode.js/zipball/9e1b2cda98d215d3a73fcbfe93c62e021f4ba768", - "reference": "9e1b2cda98d215d3a73fcbfe93c62e021f4ba768" - }, - "type": "bower-asset" - }, - { - "name": "bower-asset/yii2-pjax", - "version": "2.0.8", - "source": { - "type": "git", - "url": "git@github.com:yiisoft/jquery-pjax.git", - "reference": "a9298d57da63d14a950f1b94366a864bc62264fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/a9298d57da63d14a950f1b94366a864bc62264fb", - "reference": "a9298d57da63d14a950f1b94366a864bc62264fb" - }, - "require": { - "bower-asset/jquery": ">=1.8" - }, - "type": "bower-asset", - "license": [ - "MIT" - ] - }, { "name": "cebe/markdown", "version": "1.2.1", @@ -515,16 +440,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.0", + "version": "1.13.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414" + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { @@ -563,7 +488,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" }, "funding": [ { @@ -571,7 +496,7 @@ "type": "tidelift" } ], - "time": "2025-02-12T12:17:51+00:00" + "time": "2025-04-29T12:36:36+00:00" }, { "name": "nikic/php-parser", @@ -2356,9 +2281,7 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": { - "bower-asset/jquery": 0 - }, + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { diff --git a/docs/guide/concept-aliases.md b/docs/guide/concept-aliases.md index c80ab7a09c4..d0cc9b9bc24 100644 --- a/docs/guide/concept-aliases.md +++ b/docs/guide/concept-aliases.md @@ -116,8 +116,7 @@ Yii predefines a set of aliases to easily reference commonly used file paths and containing the [entry script](structure-entry-scripts.md). - `@web`, the base URL of the currently running Web application. It has the same value as [[yii\web\Request::baseUrl]]. - `@vendor`, the [[yii\base\Application::vendorPath|Composer vendor directory]]. Defaults to `@app/vendor`. -- `@bower`, the root directory that contains [bower packages](https://bower.io/). Defaults to `@vendor/bower`. -- `@npm`, the root directory that contains [npm packages](https://www.npmjs.com/). Defaults to `@vendor/npm`. +- `@npm`, the root directory that contains [npm packages](https://www.npmjs.com/). Defaults to `@app/node_modules`. The `@yii` alias is defined when you include the `Yii.php` file in your [entry script](structure-entry-scripts.md). The rest of the aliases are defined in the application constructor when applying the application diff --git a/docs/guide/start-installation.md b/docs/guide/start-installation.md index 030af28951e..153b24f4c1f 100644 --- a/docs/guide/start-installation.md +++ b/docs/guide/start-installation.md @@ -114,26 +114,11 @@ But there are other installation options available: Installing Assets ----------------- -Yii relies on [Bower](https://bower.io/) and/or [NPM](https://www.npmjs.com/) packages for the asset (CSS and JavaScript) libraries installation. -It uses Composer to obtain these libraries, allowing PHP and CSS/JavaScript package versions to resolve at the same time. -This can be achieved either by usage of [asset-packagist.org](https://asset-packagist.org) or [composer asset plugin](https://github.com/fxpio/composer-asset-plugin). -Please refer to [Assets documentation](structure-assets.md) for more details. - -You may want to either manage your assets via native Bower/NPM client, use CDN or avoid assets installation entirely. -In order to prevent assets installation via Composer, add the following lines to your 'composer.json': - -```json -"replace": { - "bower-asset/jquery": ">=1.11.0", - "bower-asset/inputmask": ">=3.2.0", - "bower-asset/punycode": ">=1.3.0", - "bower-asset/yii2-pjax": ">=2.0.0" -}, -``` +Yii relies on [NPM](https://www.npmjs.com/) packages for the asset (CSS and JavaScript) libraries installation. -> Note: in case of bypassing asset installation via Composer, you are responsible for the assets installation and resolving -> version collisions. Be prepared for possible inconsistencies among asset files from different extensions. +Please refer to [Assets documentation](structure-assets.md) for more details. +You may want to either manage your assets via native NPM client, use CDN or avoid assets installation entirely. Verifying the Installation -------------------------- diff --git a/docs/guide/structure-assets.md b/docs/guide/structure-assets.md index 25b4b8fdfd3..7cae63a518f 100644 --- a/docs/guide/structure-assets.md +++ b/docs/guide/structure-assets.md @@ -188,7 +188,7 @@ use yii\web\AssetBundle; class FontAwesomeAsset extends AssetBundle { - public $sourcePath = '@bower/font-awesome'; + public $sourcePath = '@npm/font-awesome'; public $css = [ 'css/font-awesome.min.css', ]; @@ -205,13 +205,9 @@ The above example defines an asset bundle for the ["fontawesome" package](https: the `only` publishing option, only the `fonts` and `css` subdirectories will be published. -### Bower and NPM Assets installation +### NPM Assets installation -Most JavaScript/CSS packages are managed by [Bower](https://bower.io/) and/or [NPM](https://www.npmjs.com/) package -managers. In PHP world we have Composer, that manages PHP dependencies, but it is possible to load -both Bower and NPM packages using `composer.json` just as PHP packages. - -To achieve this, we should configure our composer a bit. There are two options to do that: +Most JavaScript/CSS packages are managed by [NPM](https://www.npmjs.com/) package managers. ___ @@ -233,14 +229,13 @@ In the `composer.json` of your project, add the following lines: ] ``` -Adjust `@npm` and `@bower` [aliases](concept-aliases.md) in you [application configuration](concept-configurations.md): +Adjust `@npm` [aliases](concept-aliases.md) in you [application configuration](concept-configurations.md): ```php $config = [ ... 'aliases' => [ - '@bower' => '@vendor/bower-asset', - '@npm' => '@vendor/npm-asset', + '@npm' => '@root/npm-asset', ], ... ]; @@ -248,52 +243,6 @@ $config = [ Visit [asset-packagist.org](https://asset-packagist.org) to know, how it works. -#### Using fxp/composer-asset-plugin - -Compared to asset-packagist, composer-asset-plugin does not require any changes to application config. Instead, it -requires global installation of a special Composer plugin by running the following command: - -```bash -composer global require "fxp/composer-asset-plugin:^1.4.1" -``` - -This command installs [composer asset plugin](https://github.com/fxpio/composer-asset-plugin/) globally -which allows managing Bower and NPM package dependencies through Composer. After the plugin installation, -every single project on your computer will support Bower and NPM packages through `composer.json`. - -Add the following lines to `composer.json` of your project to adjust directories where the installed packages -will be placed, if you want to publish them using Yii: - -```json -"config": { - "fxp-asset": { - "installer-paths": { - "npm-asset-library": "vendor/npm", - "bower-asset-library": "vendor/bower" - } - } -} -``` - -> Note: `fxp/composer-asset-plugin` significantly slows down the `composer update` command in comparison - to asset-packagist. - -____ - -After configuring Composer to support Bower and NPM: - -1. Modify the `composer.json` file of your application or extension and list the package in the `require` entry. - You should use `bower-asset/PackageName` (for Bower packages) or `npm-asset/PackageName` (for NPM packages) - to refer to the library. -2. Run `composer update` -3. Create an asset bundle class and list the JavaScript/CSS files that you plan to use in your application or extension. - You should specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property as `@bower/PackageName` or `@npm/PackageName`. - This is because Composer will install the Bower or NPM package in the directory corresponding to this alias. - -> Note: Some packages may put all their distributed files in a subdirectory. If this is the case, you should specify - the subdirectory as the value of [[yii\web\AssetBundle::sourcePath|sourcePath]]. For example, [[yii\web\JqueryAsset]] - uses `@bower/jquery/dist` instead of `@bower/jquery`. - ## Using Asset Bundles diff --git a/docs/guide/structure-extensions.md b/docs/guide/structure-extensions.md index bc94fe9412e..9bd9103dbca 100644 --- a/docs/guide/structure-extensions.md +++ b/docs/guide/structure-extensions.md @@ -181,31 +181,30 @@ can know which extensions are installed (the information can be accessed via [[y Your extension depends on Yii (of course). So you should list it (`yiisoft/yii2`) in the `require` entry in `composer.json`. If your extension also depends on other extensions or third-party libraries, you should list them as well. -Make sure you also list appropriate version constraints (e.g. `1.*`, `@stable`) for each dependent package. Use stable -dependencies when your extension is released in a stable version. +Make sure you also list appropriate version constraints (for example, `1.*`, `@stable`) for each dependent package. +Use stable dependencies when your extension is released in a stable version. -Most JavaScript/CSS packages are managed using [Bower](https://bower.io/) and/or [NPM](https://www.npmjs.com/), -instead of Composer. Yii uses the [Composer asset plugin](https://github.com/fxpio/composer-asset-plugin) -to enable managing these kinds of packages through Composer. If your extension depends on a Bower package, you can -simply list the dependency in `composer.json` like the following: +For JavaScript/CSS packages, Yii uses [NPM](https://www.npmjs.com/) natively. If your extension depends on NPM packages, +you should include a `package.json` file in your extension root directory. For example: ```json { - // package dependencies - "require": { - "bower-asset/jquery": ">=1.11.*" + "name": "your-extension-name", + "version": "1.0.0", + "dependencies": { + "jquery": "^3.6.0", + "bootstrap": "^5.1.3" } } ``` -The above code states that the extension depends on the `jquery` Bower package. In general, you can use -`bower-asset/PackageName` to refer to a Bower package in `composer.json`, and use `npm-asset/PackageName` -to refer to a NPM package. When Composer installs a Bower or NPM package, by default the package content will be -installed under the `@vendor/bower/PackageName` and `@vendor/npm/Packages` directories, respectively. -These two directories can also be referred to using the shorter aliases `@bower/PackageName` and `@npm/PackageName`. +When your extension is installed, users will need to run `npm install` in the extension directory to install these +frontend dependencies. You should document this requirement in your extension's README file. -For more details about asset management, please refer to the [Assets](structure-assets.md#bower-npm-assets) section. +In your extension's code, you can reference these assets from the `node_modules` directory. For example, in an asset +bundle class: +For more details about asset management, please refer to the [Assets](structure-assets.md#npm-assets) section. #### Class Autoloading diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 24ad9ecce55..bae37c111cf 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -6,6 +6,7 @@ Yii Framework 2 Change Log - Chg #19902: Remove support for CUBRID (mtangoo) - Chg #19891: Remove XCache and ZendDataCache support (mtangoo) +- Enh #20368: Refactor asset management: Migrate from `Bower` to `NPM` for package dependencies and update related documentation (terabytesoftw) 2.0.53 under development diff --git a/framework/base/Application.php b/framework/base/Application.php index e2944b82a5e..fddd279b7e3 100644 --- a/framework/base/Application.php +++ b/framework/base/Application.php @@ -459,8 +459,7 @@ public function setVendorPath($path) { $this->_vendorPath = Yii::getAlias($path); Yii::setAlias('@vendor', $this->_vendorPath); - Yii::setAlias('@bower', $this->_vendorPath . DIRECTORY_SEPARATOR . 'bower'); - Yii::setAlias('@npm', $this->_vendorPath . DIRECTORY_SEPARATOR . 'npm'); + Yii::setAlias('@npm', $this->getBasePath() . DIRECTORY_SEPARATOR . 'node_modules'); } /** diff --git a/framework/composer.json b/framework/composer.json index ad247b9284b..e7612a41b1a 100644 --- a/framework/composer.json +++ b/framework/composer.json @@ -69,11 +69,7 @@ "lib-pcre": "*", "yiisoft/yii2-composer": "~2.0.4", "ezyang/htmlpurifier": "^4.17", - "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0", - "bower-asset/jquery": "3.7.*@stable | 3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", - "bower-asset/inputmask": "^5.0.8 ", - "bower-asset/punycode": "^1.4", - "bower-asset/yii2-pjax": "~2.0.1" + "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0" }, "autoload": { "psr-4": {"yii\\": ""} diff --git a/framework/validators/PunycodeAsset.php b/framework/validators/PunycodeAsset.php index 8d928838ce9..0e5917a5bd0 100644 --- a/framework/validators/PunycodeAsset.php +++ b/framework/validators/PunycodeAsset.php @@ -17,7 +17,7 @@ */ class PunycodeAsset extends AssetBundle { - public $sourcePath = '@bower/punycode'; + public $sourcePath = '@npm/punycode'; public $js = [ 'punycode.js', ]; diff --git a/framework/web/JqueryAsset.php b/framework/web/JqueryAsset.php index df365d7686b..e7a53467181 100644 --- a/framework/web/JqueryAsset.php +++ b/framework/web/JqueryAsset.php @@ -15,7 +15,7 @@ */ class JqueryAsset extends AssetBundle { - public $sourcePath = '@bower/jquery/dist'; + public $sourcePath = '@npm/jquery/dist'; public $js = [ 'jquery.js', ]; diff --git a/framework/widgets/MaskedInputAsset.php b/framework/widgets/MaskedInputAsset.php index 473f4315ffa..2a0a6a1974d 100644 --- a/framework/widgets/MaskedInputAsset.php +++ b/framework/widgets/MaskedInputAsset.php @@ -19,7 +19,7 @@ */ class MaskedInputAsset extends AssetBundle { - public $sourcePath = '@bower/inputmask/dist'; + public $sourcePath = '@npm/inputmask/dist'; public $js = [ 'jquery.inputmask.js', ]; diff --git a/framework/widgets/PjaxAsset.php b/framework/widgets/PjaxAsset.php index 47795f683cf..c084763f913 100644 --- a/framework/widgets/PjaxAsset.php +++ b/framework/widgets/PjaxAsset.php @@ -17,7 +17,7 @@ */ class PjaxAsset extends AssetBundle { - public $sourcePath = '@bower/yii2-pjax'; + public $sourcePath = '@npm/yii2-pjax'; public $js = [ 'jquery.pjax.js', ]; diff --git a/package.json b/package.json index d02833949d9..a21e79fa96b 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,13 @@ "doc": "docs", "test": "tests/js/tests" }, + "dependencies": { + "inputmask": "^5.0.8", + "jquery-pjax": "^2.0.1", + "jquery": "~3.6.4", + "punycode": "^1.4.0", + "yii2-pjax": "^2.0.8" + }, "devDependencies": { "chai": "^3.5.0", "jsdom": "24.1.0", diff --git a/tests/TestCase.php b/tests/TestCase.php index f6c081a7784..0a9fad4ae4f 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -74,8 +74,7 @@ protected function mockWebApplication($config = [], $appClass = '\yii\web\Applic 'basePath' => __DIR__, 'vendorPath' => $this->getVendorPath(), 'aliases' => [ - '@bower' => '@vendor/bower-asset', - '@npm' => '@vendor/npm-asset', + '@npm' => '@root/node_modules', ], 'components' => [ 'request' => [ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 35a3b1e4a90..c1a4ba00222 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -22,6 +22,7 @@ require_once __DIR__ . '/../framework/Yii.php'; Yii::setAlias('@yiiunit', __DIR__); +Yii::setAlias('@root', dirname(__DIR__)); if (getenv('TEST_RUNTIME_PATH')) { Yii::setAlias('@yiiunit/runtime', getenv('TEST_RUNTIME_PATH')); diff --git a/tests/js/tests/yii.activeForm.test.js b/tests/js/tests/yii.activeForm.test.js index 506fe38a5a1..233e768fa08 100644 --- a/tests/js/tests/yii.activeForm.test.js +++ b/tests/js/tests/yii.activeForm.test.js @@ -8,7 +8,7 @@ var vm = require('vm'); describe('yii.activeForm', function () { var yiiActiveFormPath = 'framework/assets/yii.activeForm.js'; var yiiPath = 'framework/assets/yii.js'; - var jQueryPath = 'vendor/bower-asset/jquery/dist/jquery.js'; + var jQueryPath = 'node_modules/jquery/dist/jquery.js'; var $; var $activeForm; diff --git a/tests/js/tests/yii.captcha.test.js b/tests/js/tests/yii.captcha.test.js index 8970b7decfb..90cec542a83 100644 --- a/tests/js/tests/yii.captcha.test.js +++ b/tests/js/tests/yii.captcha.test.js @@ -8,7 +8,7 @@ var vm = require('vm'); describe('yii.captcha', function () { var yiiCaptchaPath = 'framework/assets/yii.captcha.js'; - var jQueryPath = 'vendor/bower-asset/jquery/dist/jquery.js'; + var jQueryPath = 'node_modules/jquery/dist/jquery.js'; var $; var $captcha; var settings = { diff --git a/tests/js/tests/yii.gridView.test.js b/tests/js/tests/yii.gridView.test.js index de13b4e7090..744e9bac76c 100644 --- a/tests/js/tests/yii.gridView.test.js +++ b/tests/js/tests/yii.gridView.test.js @@ -9,7 +9,7 @@ var vm = require('vm'); describe('yii.gridView', function () { var yiiGridViewPath = 'framework/assets/yii.gridView.js'; var yiiPath = 'framework/assets/yii.js'; - var jQueryPath = 'vendor/bower-asset/jquery/dist/jquery.js'; + var jQueryPath = 'node_modules/jquery/dist/jquery.js'; var $; var $gridView; var settings = { diff --git a/tests/js/tests/yii.test.js b/tests/js/tests/yii.test.js index 2072235002b..0ef1f6963cf 100644 --- a/tests/js/tests/yii.test.js +++ b/tests/js/tests/yii.test.js @@ -20,8 +20,8 @@ var StringUtils = { describe('yii', function () { var yiiPath = 'framework/assets/yii.js'; - var jQueryPath = 'vendor/bower-asset/jquery/dist/jquery.js'; - var pjaxPath = 'vendor/bower-asset/yii2-pjax/jquery.pjax.js'; + var jQueryPath = 'node_modules/jquery/dist/jquery.js'; + var pjaxPath = 'node_modules/yii2-pjax/jquery.pjax.js'; var sandbox; var $; var yii; diff --git a/tests/js/tests/yii.validation.test.js b/tests/js/tests/yii.validation.test.js index 5cd742c075e..c75cc1388f0 100644 --- a/tests/js/tests/yii.validation.test.js +++ b/tests/js/tests/yii.validation.test.js @@ -18,7 +18,7 @@ var StringUtils = { }; var jsdom = require('mocha-jsdom'); -var punycode = require('../../../vendor/bower-asset/punycode/punycode'); +var punycode = require('../../../node_modules/punycode/punycode'); var fs = require('fs'); var vm = require('vm'); @@ -76,7 +76,7 @@ describe('yii.validation', function () { } jsdom({ - src: fs.readFileSync('vendor/bower-asset/jquery/dist/jquery.js', 'utf-8'), + src: fs.readFileSync('node_modules/jquery/dist/jquery.js', 'utf-8'), url: "http://foo.bar" });