Instalace frontend assetů pomocí Composeru

před 2 lety

janpecha
Člen | 58
+
+4
-

Ahoj všem,

napsal jsem plugin pro Composer, který umožňuje vytáhnout statické soubory (CSS, JS,…) ze složky /vendor do složky /www. Plugin stačí nainstalovat jako závislost projektu a on pak automaticky při aktualizaci balíčků aktualizuje i assety ve složce /www.

K čemu je to dobré?

  • můžete poslat Bower do věčných lovišť a instalovat frontend knihovny pomocí jednoho z nejlepších package managerů™
  • pokud máte projekt jenom v PHP, můžete všechny závislosti spravovat na jednom místě
  • server-side i client-side budou používat stejné verze knihoven (viz nette/forms vs. netteForms.js)
  • při commitování composer.lock budete mít jistotu, že všechny frontend assety budou nainstalovány vždy ve správné verzi

S čím plugin nepomůže?

  • neřeší spojování a kompilaci JS/CSS/LESS/… souborů – tohle každý řeší po svém a navíc pro tuhle činnost existuje dostatek jiných nástrojů

Instalace

composer require frontpack/composer-assets-plugin

Konfigurace

Konfiguraci lze rozdělit do 2 částí:

  1. konfigurace konkrétních balíčků – balíčky definují seznam souborů a složek, které bude plugin instalovat
  2. konfigurace projektu – programátor definuje, kam má plugin assety umístit
1) konfigurace konkrétních balíčků

Aby plugin věděl, které soubory má přetáhnout do složky www/, musí balíčky v composer.json uvést jejich seznam. Pro nette/forms by to vypadalo nějak takto:

{
    "name": "nette/forms",
    "extra": {
        "assets-files": [
            "src/assets/netteForms.js"
        ]
    }
}

Po instalaci nette/forms se soubor netteForms.js objeví v umístění assets/nette/forms/netteForms.js.

2) konfigurace projektu
Změna složky s assety

Ve výchozím nastavení plugin nainstaluje soubory do složky assets hned vedle složky vendor. To nemusí být vždycky užitečné a tak je možné cílové umístění upravit. Stačí v projektovém composer.json nastavit konfigurační volbu assets-dir. Pro standardní strukturu Nette aplikace by nastavení mohlo vypadat nějak tahle (cesta je relativní vzhledem k umístění složky vendor):

{
    "config": {
        "assets-dir": "www/assets"
    }
}
Podpora pro nekompatibilní balíčky

Málokterý balíček obsahuje seznam souborů pro instalaci a tak plugin umožňuje definovat tento seznam v projektovém composer.json:

{
    "config": {
        "assets-files": {
            "nette/forms": [
                "src/assets/netteForms.js"
            ],
            "o5/grido": [
                "assets/dist"
            ]
        }
    }
}

Díky tomu dokáže plugin pracovat i s nepodporovanými balíčky. Nastavení uvedené v projektovém composer.json má nejvyšší prioritu, takže lze zcela přepsat seznam souborů poskytovaný konkrétními balíčky.

Protože je otrava psát seznam souborů svépomocí, obsahuje plugin předpřipravený seznam souborů pro vybrané nekompatibilní balíčky, aktuálně pro:

  • components/jquery
  • nette/forms
  • o5/grido

Plugin je aktuálně ve verzi 0.9.1, budu rád, když ho vyzkoušíte a podělíte se o bug reporty, feature requesty a pull requesty :) Berte to zatím jako koncept.

Upozornění pro uživatele Windows – nemám plugin otestovaný na Windows. Místo kopírování souborů plugin vytváří pouze relativní symlinky do složky vendor/ – na Windows to pravděpodobně nebude fungovat. Časem to plánuju vyřešit pomocí instalačních strategií. mělo by být vyřešeno

Editoval janpecha (7. 3. 2017 13:04)

před 2 lety

CZechBoY
Člen | 3351
+
0
-

Co když to nechci mít ve www, ale chci spojit assety v neveřejný složce?
Navíc mi přijde, že se od assetů v composeru upouští a assety se hází na bower aj.

před 2 lety

janpecha
Člen | 58
+
+1
-

Co když to nechci mít ve www, ale chci spojit assety v neveřejný složce?

Buď řekneš pluginu, že to má nahrát do nějaké jiné složky a tam si to nějak pořešíš, nebo prostě použiješ jiný vhodnější nástroj.

Navíc mi přijde, že se od assetů v composeru upouští a assety se hází na bower aj.

No vidíš, a já upouštím od instalace assetů pomocí “Boweru, aj.” a hazím to na Composer :) Protože mi to tak u PHP projektů prostě více vyhovuje – Bower je skoro mrtvej, nemá lock soubor a nepřináší nic, co by mě donutilo ho nadále používat. Composer se mi dobře stará o PHP závislosti, proč by se dobře nepostaral i o ty ostatní.

před 2 lety

akadlec
Člen | 1309
+
0
-

A když nechci bower/npm apod. tak bych řek že je vhodnější použít nějaký balíček co udělá i to spojení a tím že si ty staticky bude tahat přímo z balíku bude zajištěn jejich update a nebudu je muset cpát do www složky kde je ve většine případů nechceš když je spojuješ.

před 2 lety

janpecha
Člen | 58
+
0
-

Tak hlavně záleží, jak aktuálně s těmi assety pracuješ. Třeba u mě to vypadá takto:

  1. během vývoje mám assety ve složce www/assets, načítám je odsud
  2. při buildu assety z www/assets pospojuju a na produkci nahrávám jen spojené soubory, složka www/assets se tak na server vůbec nedostane

Zároveň je diskutabilní, jestli opravdu potřebuješ při vývoji speciální nástroj, který se ti stará o spojování. Třeba LESS se dokáže spojovat sám o sobě, vč. úpravy relativních cest, JS soubory ti zase může spojovat Apache.

No a pokud potřebuješ něco komplexnějšího, prostě použiješ nějaký komplexnější nástroj – Webpack, či cokoli jiného.

před rokem

Ivorius
Člen | 111
+
0
-

Jak řešíš načtení pro různé entrypoint (např. admin a front)?

Nebylo by lepší místo kopírování těch assetů jen zapsat jejich cestu do nějakého extension.js, což by si pak načítal webpack? Šlo by tím pak načítat i např. potřebné knihovny z node_modules

před rokem

Tomáš Votruba
Moderator | 1154
+
0
-

Ahoj, pěkná práce!

Nečetl jsem všechny features, ale jak bys to stručně porovnal s https://github.com/…asset-plugin

před rokem

janpecha
Člen | 58
+
0
-

Vytvořím si soubory pro jednotlivá použití (admin.js, front.js, admin.less, front.less,…) a v nich uvedu seznam souborů, které se mají načíst. Pro strukturu

  • www/
    • assets/ – soubory nakopírované pomocí composer-assets-plugin
    • admin.js
    • admin.less

by to vypadalo třeba takhle:

admin.js

<!--#include file="assets/nette/forms/netteForms.js" -->
<!--#include file="assets/xyz/xyz/abc.js" -->

admin.less

@import 'assets/xyz/xyz/abc.less';

Teoreticky by šlo načítat ty JS a CSS/LESS soubory přímo ze složky /vendor, ve skutečnosti je to však nepraktické, protože stejně musíš z /vendor do /www vykopírovat obrázky a fonty, tak proč rovnou nevykopírovat všechno.


Při deploymentu pak nechám ten admin.js a admin.less zkompilovat a zminifikovat.


Jestli je lepší kopírovat soubory, nebo použít Webpack záleží na situaci:

  • buď soubory kopíruješ a pak nepotřebuješ Webpack
  • nebo použiješ Webpack a pak nepotřebuješ kopírovat soubory

Primárně tak záleží na tom, jestli Webpack využiješ i k něčemu jinému, než je spojování souborů.

před rokem

janpecha
Člen | 58
+
+1
-

@TomášVotruba nečetl jsem všechny features, ale stručně bych to shrnul takto:

  • můj plugin umožňuje jen vykopírovat soubory ze složky /vendor do nějaké veřejné složky
  • ten odkazovaný plugin umožňuje pomocí Composeru instalovat balíčky pro Bower, NPM, atd.

před rokem

Ivorius
Člen | 111
+
0
-

Aha, já bych to chtěl právě použít pro automatické načítání assetů z extensions (přes composer), ale abych vyřešil zároveň i to rozdělení front a admin (tedy nechci je definovat přímo v tom entrypointu).

před rokem

janpecha
Člen | 58
+
0
-

Mohl bys popsat, jak přesně bys chtěl, aby to fungovalo? Třeba by pro to šlo dopsat podporu.

před rokem

Ivorius
Člen | 111
+
0
-

jako pro mě by byla ideální možnost mít něco ve stylu:

definice balíčku composer:

"extra": {
    "assets": {
        "front.js": [
            "assets/front/search.js",
            "assets/front/main.js",
        ],
        "admin.js": [
            "package/xxx.js"
        ]
    }
}

Mno a pak už by se jen místo kopírování těch souborů vytvořily soubory front.js a admin.js, kde by bylo např.
require(‚vendor/unio/algolia/assets/front/search.js‘);
require(‚vendor/unio/algolia/assets/front/main.js‘);

před rokem

janpecha
Člen | 58
+
0
-

Takže ti jde v podstatě o to, aby si balíček sám určil, kam se má “nakopírovat” (resp. do jakého souboru se má zapsat)? Zkusím s tím něco vymyslet, prozatím jsem na to vytvořil issue.