Percorso delle risorse nei file CSS in Symfony 2


101

Problema

Ho un file CSS con alcuni percorsi al suo interno (per immagini, caratteri, ecc .. url(..)).

La mia struttura del percorso è così:

...
+-src/
| +-MyCompany/
|   +-MyBundle/
|     +-Resources/
|       +-assets/
|         +-css/
|           +-stylesheets...
+-web/
| +-images/
|   +-images...
...

Voglio fare riferimento alle mie immagini nel foglio di stile.

Prima soluzione

Ho cambiato tutti i percorsi nel file CSS in percorsi assoluti. Questa non è una soluzione, poiché l'applicazione dovrebbe (e deve!) Funzionare anche in una sottodirectory.

Seconda soluzione

Usa Assetic con filter="cssrewrite".

Quindi ho cambiato tutti i miei percorsi nel mio file CSS in

url("../../../../../../web/images/myimage.png")

per rappresentare il percorso effettivo dalla directory delle mie risorse alla /web/imagesdirectory. Questo non funziona, poiché cssrewrite produce il seguente codice:

url("../../Resources/assets/")

che è ovviamente la strada sbagliata.

Dopo aver assetic:dumpcreato questo percorso, che è ancora sbagliato:

url("../../../web/images/myimage.png")

Il codice ramoscello di Assetic:

{% stylesheets
    '@MyCompanyMyBundle/Resources/assets/css/*.css'
    filter="cssrewrite"
%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}

Soluzione attuale (terza)

Poiché tutti i file CSS finiscono /web/css/stylexyz.css, ho modificato tutti i percorsi nel file CSS in modo che siano relativi:

url("../images/myimage.png")

Questa (cattiva) soluzione funziona, tranne che devnell'ambiente: il percorso CSS è /app_dev.php/css/stylexyz.csse quindi il percorso dell'immagine che ne risulta è /app_dev.php/images/myimage.png, che risulta in un file NotFoundHttpException.

Esiste una soluzione migliore e funzionante?


1
Ho postato la mia soluzione qui: stackoverflow.com/q/9501248/1146363
CERAD

Questo risolve effettivamente il problema con i percorsi durante l'utilizzo app_dev.php?
apfelbox

Risposte:


194

Mi sono imbattuto nello stesso problema.

In breve:

  • Disponibilità ad avere CSS originale in una directory "interna" (Resources / assets / css / a.css)
  • Disponibilità ad avere le immagini nella directory "public" (Resources / public / images / devil.png)
  • Volendo quel ramoscello prende quel CSS, lo ricompila in web / css / a.css e fa in modo che punti l'immagine in /web/bundles/mynicebundle/images/devil.png

Ho effettuato un test con TUTTE le possibili (sane) combinazioni di quanto segue:

  • @notation, notazione relativa
  • Analizza con cssrewrite, senza di essa
  • Sfondo dell'immagine CSS vs tag <img> diretto src = alla stessa immagine del CSS
  • CSS analizzato con assetic e anche senza analizzare con output diretto assetic
  • E tutto questo si è moltiplicato provando una Resources/public/css"directory pubblica" (as ) con il CSS e una directory "privata" (as Resources/assets/css).

Questo mi ha dato un totale di 14 combinazioni sullo stesso ramoscello, e questa via è stata lanciata da

  • "/App_dev.php/"
  • "/App.php/"
  • e "/"

dando così 14 x 3 = 42 test.

Inoltre, tutto questo è stato testato lavorando in una sottodirectory, quindi non c'è modo di ingannare fornendo URL assoluti perché semplicemente non funzionerebbero.

I test erano due immagini senza nome e poi div denominati da "a" a "f" per il CSS compilato DALLA cartella pubblica e denominati da "g a" l "per quelli creati dal percorso interno.

Ho osservato quanto segue:

Solo 3 dei 14 test sono stati mostrati adeguatamente sui tre URL. E NESSUNO proveniva dalla cartella "interna" (Risorse / risorse). Era un prerequisito avere il CSS PUBLIC di riserva e quindi compilare con assetic FROM lì.

Questi sono i risultati:

  1. Risultato lanciato con /app_dev.php/ Risultato lanciato con /app_dev.php/

  2. Risultato lanciato con /app.php/ Risultato lanciato con /app.php/

  3. Risultato lanciato con / inserisci qui la descrizione dell'immagine

Quindi ... SOLO - La seconda immagine - Div B - Div C sono le sintassi consentite.

Ecco il codice TWIG:

<html>
    <head>
            {% stylesheets 'bundles/commondirty/css_original/container.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

    {# First Row: ABCDEF #}

            <link href="{{ '../bundles/commondirty/css_original/a.css' }}" rel="stylesheet" type="text/css" />
            <link href="{{ asset( 'bundles/commondirty/css_original/b.css' ) }}" rel="stylesheet" type="text/css" />

            {% stylesheets 'bundles/commondirty/css_original/c.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets 'bundles/commondirty/css_original/d.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/public/css_original/e.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/public/css_original/f.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

    {# First Row: GHIJKL #}

            <link href="{{ '../../src/Common/DirtyBundle/Resources/assets/css/g.css' }}" rel="stylesheet" type="text/css" />
            <link href="{{ asset( '../src/Common/DirtyBundle/Resources/assets/css/h.css' ) }}" rel="stylesheet" type="text/css" />

            {% stylesheets '../src/Common/DirtyBundle/Resources/assets/css/i.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '../src/Common/DirtyBundle/Resources/assets/css/j.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/assets/css/k.css' filter="cssrewrite" %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

            {% stylesheets '@CommonDirtyBundle/Resources/assets/css/l.css' %}
                <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
            {% endstylesheets %}

    </head>
    <body>
        <div class="container">
            <p>
                <img alt="Devil" src="../bundles/commondirty/images/devil.png">
                <img alt="Devil" src="{{ asset('bundles/commondirty/images/devil.png') }}">
            </p>
            <p>
                <div class="a">
                    A
                </div>
                <div class="b">
                    B
                </div>
                <div class="c">
                    C
                </div>
                <div class="d">
                    D
                </div>
                <div class="e">
                    E
                </div>
                <div class="f">
                    F
                </div>
            </p>
            <p>
                <div class="g">
                    G
                </div>
                <div class="h">
                    H
                </div>
                <div class="i">
                    I
                </div>
                <div class="j">
                    J
                </div>
                <div class="k">
                    K
                </div>
                <div class="l">
                    L
                </div>
            </p>
        </div>
    </body>
</html>

Il container.css:

div.container
{
    border: 1px solid red;
    padding: 0px;
}

div.container img, div.container div 
{
    border: 1px solid green;
    padding: 5px;
    margin: 5px;
    width: 64px;
    height: 64px;
    display: inline-block;
    vertical-align: top;
}

E a.css, b.css, c.css, ecc: tutti identici, cambiando solo il colore e il selettore CSS.

.a
{
    background: red url('../images/devil.png');
}

La struttura delle "directory" è:

Elenchi Elenchi

Tutto questo è venuto, perché non volevo che i singoli file originali fossero esposti al pubblico, specialmente se volevo giocare con filtri "less" o "sass" o simili ... non volevo che i miei "originali" fossero pubblicati, solo il compilato uno.

Ma ci sono buone notizie . Se non vuoi avere il "CSS di riserva" nelle directory pubbliche ... installali non con --symlink, ma facendone una copia. Una volta che "assetic" ha costruito il CSS composto, puoi CANCELLARE il CSS originale dal filesystem e lasciare le immagini:

Processo di compilazione Processo di compilazione

Nota che lo faccio per l' --env=prodambiente.

Solo alcune considerazioni finali:

  • Questo comportamento desiderato può essere ottenuto avendo le immagini nella directory "public" in Git o Mercurial e il "css" nella directory "assets". Cioè, invece di averli in "pubblico" come mostrato nelle directory, immagina a, b, c ... risiedere nelle "risorse" invece di "pubblico", piuttosto che avere il tuo installatore / deployer (probabilmente uno script Bash ) per mettere il CSS temporaneamente all'interno della directory "public" prima assets:installviene eseguito, poi assets:install, poi assetic:dump, e quindi automatizza la rimozione del CSS dalla directory pubblica dopo che assetic:dumpè stato eseguito. Ciò otterrebbe ESATTAMENTE il comportamento desiderato nella domanda.

  • Un'altra soluzione (sconosciuta se possibile) sarebbe quella di esplorare se "assets: install" può prendere solo "public" come fonte o potrebbe anche prendere "asset" come fonte da pubblicare. Ciò sarebbe utile se installato con l' --symlinkopzione durante lo sviluppo.

  • Inoltre, se stiamo per eseguire la rimozione tramite script dalla directory "public", la necessità di memorizzarli in una directory separata ("assets") scompare. Possono vivere in "pubblico" nel nostro sistema di controllo della versione poiché verranno rilasciati al momento della distribuzione al pubblico. Ciò consente anche l' --symlinkutilizzo.

MA IN OGNI MODO, ATTENZIONE ORA: poiché ora gli originali non ci sono più ( rm -Rf), ci sono solo due soluzioni, non tre. Il div funzionante "B" non funziona più poiché era una chiamata asset () assumendo che ci fosse l'asset originale. Solo "C" (quello compilato) funzionerà.

Quindi ... c'è SOLO un VINCITORE FINALE: Il Div "C" permette ESATTAMENTE quello che è stato chiesto nel topic: Per essere compilato, rispettare il percorso delle immagini e non esporre la fonte originale al pubblico.

Il vincitore è C

Il vincitore è C


3
Collegamenti alle immagini per il post precedente: 1) Risultato lanciato con /app_dev.php/ , 2) Risultato lanciato con /app.php/ link , 3) Risultato lanciato con / link , 4) Collegamento alle directory , 5) Collegamento al processo di compilazione , 6) Chi è il link
Xavi Montero

1
E se vuoi aggiungere un'immagine da un altro pacchetto, invece di usarlo, background-image: url('../images/devil.png');usa questobackground-image: url('../../../bundles/frontendlayout/images/devil.png');
Xavi Montero

1
Funziona anche combinando "cssrewrite" con "less":{% stylesheets filter="cssrewrite,less" "bundles/frontendlayout/less/layout.less" %} <link href="{{ asset_url }}" rel="stylesheet" type="text/css" /> {% endstylesheets %}
Xavi Montero

1
Questo è notato nella documentazione di symfony. Vedi qui
Noah Duncan

17

Il filtro cssrewrite non è compatibile con la notazione @bundle per ora. Quindi hai due scelte:

  • Fai riferimento ai file CSS nella cartella web (dopo console assets:install --symlink web:)

    {% stylesheets '/bundles/myCompany/css/*." filter="cssrewrite" %}
  • Usa il filtro cssembed per incorporare immagini nel CSS in questo modo.

    {% stylesheets '@MyCompanyMyBundle/Resources/assets/css/*.css' filter="cssembed" %}

Grazie per il tuo commento. La seconda soluzione sembra abbastanza buona se hai solo immagini piuttosto piccole. Tuttavia, non mi sentirei a mio agio nell'inserire oltre 100.000 immagini nel file CSS.
apfelbox

9

Pubblicherò ciò che ha funzionato per me, grazie a @ xavi-montero.

Metti il ​​tuo CSS nella Resource/public/cssdirectory del tuo bundle e le tue immagini in diciamo Resource/public/img.

Cambia i percorsi assetici alla forma 'bundles/mybundle/css/*.css', nel tuo layout.

In config.yml, aggiungi la regola css_rewritead assetic:

assetic:
    filters:
        cssrewrite:
            apply_to: "\.css$"

Ora installa le risorse e compila con assetic:

$ rm -r app/cache/* # just in case
$ php app/console assets:install --symlink
$ php app/console assetic:dump --env=prod

Questo è abbastanza buono per la casella di sviluppo ed --symlinkè utile, quindi non devi reinstallare le tue risorse (ad esempio, aggiungi una nuova immagine) quando entri app_dev.php.

Per il server di produzione, ho appena rimosso l'opzione '--symlink' (nel mio script di distribuzione) e ho aggiunto questo comando alla fine:

$ rm -r web/bundles/*/css web/bundles/*/js # all this is already compiled, we don't need the originals

Tutto è stato fatto. Con questo, puoi usare percorsi come questo nei tuoi file .css:../img/picture.jpeg


5

Ho avuto lo stesso problema e ho appena provato a utilizzare quanto segue come soluzione alternativa. Sembra funzionare finora. Puoi persino creare un modello fittizio che contiene solo riferimenti a tutte quelle risorse statiche.

{% stylesheets
    output='assets/fonts/glyphicons-halflings-regular.ttf'
    'bundles/bootstrap/fonts/glyphicons-halflings-regular.ttf'
%}{% endstylesheets %}

Si noti l'omissione di qualsiasi output che significa che non viene visualizzato nulla sul modello. Quando eseguo assetic: dump i file vengono copiati nella posizione desiderata e il css include il lavoro come previsto.


1
È possibile utilizzare una voce di configurazione per l'asset denominato e non è necessario includerla nei modelli. Si farà il dump comunque symfony.com/doc/current/cookbook/assetic/...
Venimus

3

Se può aiutare qualcuno, abbiamo lottato molto con Assetic e ora stiamo facendo quanto segue in modalità di sviluppo:

  • Impostato come in Dumping Asset Files nell'ambiente di sviluppo, quindi in config_dev.yml, abbiamo commentato:

    #assetic:
    #    use_controller: true

    E in routing_dev.yml

    #_assetic:
    #    resource: .
    #    type:     assetic
  • Specifica l'URL come assoluto dalla radice web. Ad esempio, immagine di sfondo: url("/bundles/core/dynatree/skins/skin/vline.gif");Nota: la nostra radice web vhost sta puntando su web/.

  • Nessun utilizzo del filtro cssrewrite


3
Questa è una soluzione valida, ma solo se non si sarà mai servire i file da una sottodirectory, ad esempio: http://example.org/sub/.
apfelbox

1

Offro di gestire il plugin css / js con il compositore che lo installa sotto il fornitore. Li collego simbolicamente alla directory web / bundles, che consente al compositore di aggiornare i bundle secondo necessità.

Esempio:

1 - collegamento simbolico una volta (usa il comando fromweb / bundles /

ln -sf vendor/select2/select2/dist/ select2

2 - usa la risorsa dove necessario, nel modello twig:

{{ asset('bundles/select2/css/fileinput.css) }}

Saluti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.