Προς το περιεχόμενο

Simple CSS Concatenation


Προτεινόμενες αναρτήσεις

Δημοσ.

Προσπαθώ να δημιουργήσω έναν 'ελαφρύ' τρόπο για να ενώσω αρχεία .css και έτσι γράφω μια μικρή PHP κλάση.

 

Μη διστάσετε να κάνετε οποιαδήποτε σχόλια όσον αφορά ελαττώματα στη λογική, ασφάλεια, ταχύτητα, αποτελεσματικότητα και απόδοση (efficiency/performance), και οτιδήποτε άλλο μπορείτε να σκεφτείτε προκειμένου να βελτιωθεί (ίσως και έναν καλύτερο τρόπο ή και μια τελείως διαφορετική προσέγγιση και λογική).

 

Η λογική ή αλγόριθμος έχει ως εξής:

 

1. Παίρνουμε ένα array από αρχεία CSS προς συνένωση.

2. Ελέγχουμε αν υπάρχει προηγούμενο αρχείο από συνένωση και αν δεν υπάρχει το δημιουργούμε.

3. Εάν υπάρχει ήδη ένα, βλέπουμε την ημερομηνία τελευταίας τροποποίησής του και τη συγκρίνουμε με εκείνη των αρχείων CSS.

4. Εάν υπάρχει τουλάχιστον ένα αρχείο CSS που είναι νεότερό του, τότε δημιουργούμε ένα καινούργιο.

 

 

<?php

/**
 * @author randomcat
 *
 * Usage:
 * include_once("./includes/concatenation.php");
 * $concat = new StylesConcatenation($files);
 * $concat->concatenate();
 */
class StylesConcatenation
{

    /**
     * @var array $files List of files to concatenate.
     */
    private $files = array();

    /**
     * @var string $cssDirectory The path to the CSS directory, relative to this script.
     */
    private $cssDirectory;

    /**
     * @var string $concatenatedOutput The path where the concatenated file will be stored, relative to this script.
     */
    private $concatenatedOutput;

    /**
     * @var boolean $shouldConcatenate A flag to determine whether to concatenate or not.
     */
    private $shouldConcatenate = false;

    /**
     * Constructor
     *
     * @param $files The files to be concatenated.
     */
    public function __construct($files)
    {
        $this->files = $files;
        $this->cssDirectory = dirname(__FILE__) . "/../css/";
        $this->concatenatedOutput = dirname(__FILE__) . "/../css/all.css";
    }

    /**
     * Accessor
     *
     * @return $files Returns a list of files.
     */
    public function getFiles()
    {
        return self::$files;
    }

    /**
     * Mutator
     */
    public function setFiles($files)
    {
        self::$files = $files;
    }

    /**
     * Concatenation logic.
     */
    public function concatenate()
    {

        $filename = $this->concatenatedOutput;

        // If there's already an older concatenated file in place.
        if (file_exists($filename) && is_file($filename) && is_writable($filename))
        {
            // Last modified time of the concatenated file.
            $concatLastModified = filemtime($filename);

            foreach ($this->files as $file)
            {
                $file = $this->cssDirectory . $file;

                if (!is_file($file))
                {
                    echo "$file is not a correct file<br>";
                    continue;
                }

                $fileLastModified = filemtime($file);

                // If one file has been modified after the creation of the concantenated file, then we should concantenate again!
                if ($concatLastModified < $fileLastModified)
                {
                    $this->shouldConcatenate = true;
                }
            }

            if ($this->shouldConcatenate)
            {
                $this->createConcatenatedFile();
                echo "Reconcantenated!<br>";
            }
            else
            {
                echo "No need to concantenate.<br>";
                return;
            }
        }
        // If there's no concatenated file yet or if it's not writable.
        else
        {
            if (!file_exists($filename))
            {
                echo "The file '" . $filename . "' does not exist. Proceeding to create it...<br>";
                $this->createConcatenatedFile();
                echo "New file was created<br>";
                return;
            }
            else if (!is_writable($filename))
            {
                echo "$filename is not writable<br>";
                return;
            }
        }
    }

    /**
     * Create concatenated file.
     */
    private function createConcatenatedFile()
    {
        echo "Starting concatenation...<br>";

        $myfile = fopen($this->concatenatedOutput, "w") or die("Unable to open file!");

        $i = 0;

        // exclusive lock for thread-safe writing.
        if (flock($myfile, LOCK_EX | LOCK_NB))
        {

            foreach ($this->files as $file)
            {

                $file = $this->cssDirectory . $file;

                if (!is_file($file))
                {
                    echo "File '" . $file . "' is not a valid file.<br>";
                    continue;
                }

                $i++;
                echo "Combining " . $file . "<br>";

                $success = fwrite($myfile, file_get_contents($file, true));

                if ($success)
                {
                    echo "It was written!<br>";
                }
                else
                {
                    echo "Failed to write '" . $file . "' to file.<br>";
                }
            }

            echo "Combined " . $i . " files.<br>";

            // release lock
            flock($myfile, LOCK_UN);
        }
        else
        {
            echo "Error locking file!<br>";
        }

        fclose($myfile);
    }

}
  • Like 1
Δημοσ.

Θα ήθελα να σε ρωτήσω για την σκοπιμότητα αυτού του προγράμματος. Το .css file εξυπηρετεί ένα .html file στου οποίου το header γίνεται link. Έστω ότι υπάρχουν δύο η περισσότερα .css που εξυπηρετούν το ίδιο αρχείο html. Εάν τα ενώσεις θα πρέπει να αλλάξεις τον κώδικα και στο html και πολύ πιθανό να έχεις προβλήματα (conflicts).

Δυστυχώς δεν σκαμπαζω από php. Με python θα ανοίγα το αρχείο με την ιδιότητα append open('filename.php','a') και θα έκανα επικόλληση το άλλο αρχείο γραμμή γραμμή.

Δημοσ.

Το template (π.χ. αρχείο .html) έχει ένα array από πολλά .css αρχεία που το δίνει στο αντικείμενο της κλάσης και του παράγει ένα μόνο αρχείο .css το οποίο θα linkάρει στο <header> ώστε να μειωθεί ο αριθμός των http requests.

Δημοσ.

Αυτό που δείχνεις υποτίθεται πως τρέχει manually κάθε όποτε χρειάζεται, ή έστω σε κάθε build? Αν είναι έτσι τότε γιατί κάνεις το δικό σου αντί να χρησιμοποιήσεις κάποιο από τα πάμπολλα build tools που υπάρχουν και κάνουν αυτή τη δουλειά συν ακόμα περισσότερες;

 

Επίσης, νομίζω πως έχεις παρεξηγήσει τι κάνει η flock(). Εκτός Windows περιβάλλοντος, είναι advisory locking. Αυτό σημαίνει ότι πρέπει όλοι οι ενδιαφερόμενοι να κάνουν flock για να λειτουργήσει όπως περιμένεις. Αν ο ένας κάνει flock και ο άλλος στεγνά ανοίξει το αρχείο με fopen δε θα τον εμποδίσει κανείς.

Δημοσ.

Αυτό που δείχνεις υποτίθεται πως τρέχει manually κάθε όποτε χρειάζεται, ή έστω σε κάθε build? Αν είναι έτσι τότε γιατί κάνεις το δικό σου αντί να χρησιμοποιήσεις κάποιο από τα πάμπολλα build tools που υπάρχουν και κάνουν αυτή τη δουλειά συν ακόμα περισσότερες;

 

Επίσης, νομίζω πως έχεις παρεξηγήσει τι κάνει η flock(). Εκτός Windows περιβάλλοντος, είναι advisory locking. Αυτό σημαίνει ότι πρέπει όλοι οι ενδιαφερόμενοι να κάνουν flock για να λειτουργήσει όπως περιμένεις. Αν ο ένας κάνει flock και ο άλλος στεγνά ανοίξει το αρχείο με fopen δε θα τον εμποδίσει κανείς.

 

Τρέχει κάθε φορά, ναι. Θέλω να έχω κάτι lightweight και μικρό, χωρίς περιττές λειτουργίες (αργότερα θα το επεκτείνω προσθέτοντας versioning κ.α.). Ξέρεις εσύ κάποιο που να κυκλοφορεί ως μία κλάση;

 

Η flock() ήταν η καλύτερη λύση που μπόρεσα να βρω μέχρι στιγμής, αλλά έψαχνα κάτι αντίστοιχο του synchronized(Object MUTEX) του πολυνηματικού προγραμματισμού της Java.

Δημοσ.

Αν το κάνεις για να παίξεις / μάθεις, καλά κάνεις και το δουλεύεις. Ίσως σου βγει κάτι καλό στο τέλος και να το μοιραστείς με το community.

Αν το κάνεις γιατί δε βρίσκεις εργαλείο να κάνεις τη δουλειά σου, θα σου πρότεινα να ρίξεις μια ματιά σε Link.png Site: Sass και Link.png Site: Less .

Αν δουλεύεις κάτι που έχει τόσο πολύ css ώστε να χρειαστεί να το σπάσεις σε αρχεία για να το οργανώσεις, τα παραπάνω θα σε βοηθήσουν να δουλέψεις καλύτερα με τις δυνατότητες που προσθέτουν στην απλή css, όπως mixins, variables κλπ

  • Like 1
Δημοσ.

Αν το κάνεις γιατί δε βρίσκεις εργαλείο να κάνεις τη δουλειά σου, θα σου πρότεινα να ρίξεις μια ματιά σε Link.png Site: Sass και Link.png Site: Less .

Αν δουλεύεις κάτι που έχει τόσο πολύ css ώστε να χρειαστεί να το σπάσεις σε αρχεία για να το οργανώσεις, τα παραπάνω θα σε βοηθήσουν να δουλέψεις καλύτερα με τις δυνατότητες που προσθέτουν στην απλή css, όπως mixins, variables κλπ

 

Ναι, για modularity και οργάνωση το κάνω κυρίως, αλλά και για λιγότερα http requests.

 

Γνωρίζω από Sass και Less αλλά δεν μου αρέσει να επενδύω σε αυτά, γιατί εκτός του ότι προσωπικά δεν νιώθω ότι με διευκολύνουν, στο κοντινό μέλλον θα αντικατασταθούν και προτιμώ να αναπτύσσω λύσεις που θα χρησιμοποιώ για χρόνια στη δουλειά μου. Δεν εννοώ ότι θα σταματήσουν να λειτουργούν οι υλοποιήσεις μου με Sass, αλλά μπορεί π.χ. να έχουμε CSS variables κ.λπ. και οπότε θα θέλω να ξηλώσω το ξεπερασμένο πλέον Sass για να χρησιμοποιήσω την ευκολότερη και καθαρότερη λύση. Καλύτερα να επενδύω σε PHP και να αποκομίζω γνώσεις και κώδικα που θα μπορώ να εφαρμόσω και αλλού.

 

Και από τη στιγμή που το κάνω για οργάνωση, είναι πολύ σημαντικό για εμένα να κάνω τη δουλειά μου με μία κλάση. Έτσι θα μπορώ να την μεταφέρω σε όποιο web software/platform θέλω (π.χ. WordPress, Joomla κ.λπ.) ώστε να φτιάξω custom themes.

Δημοσ.

Το να κάνεις concanate τα css files για κάθε request δεν το θεωρώ "καθάρή λύση" προσωπικά. Οι CSS preprocessors κάνουν και αυτό.

 

Εάν δεν έχει τροποποιηθεί κάποιο css file τότε δεν γίνεται concatenation. ;)

Δημοσ.

Τρέχει κάθε φορά, ναι. Θέλω να έχω κάτι lightweight και μικρό, χωρίς περιττές λειτουργίες (αργότερα θα το επεκτείνω προσθέτοντας versioning κ.α.). Ξέρεις εσύ κάποιο που να κυκλοφορεί ως μία κλάση;

Όταν λες "κάθε φορά" ελπίζω δεν εννοείς σε κάθε HTTP request έτσι; Αλλά σε κάθε build ας πούμε.

 

Προσωπική μου άποψη ότι δίνεις βάρος σε στοιχεία που δεν έχουν καμία απολύτως σημασία αλλά ΟΚ. Με αυτό τον τρόπο επίσης "χάνεις" όλα τα πράγματα που είναι έτοιμα και δοκιμασμένα και τη δουλειά που πέφτει στο ΧΥΖ οικοσύστημα και πρέπει να τα ξανακάνεις μόνος σου.

 

Η flock() ήταν η καλύτερη λύση που μπόρεσα να βρω μέχρι στιγμής, αλλά έψαχνα κάτι αντίστοιχο του synchronized(Object MUTEX) του πολυνηματικού προγραμματισμού της Java.

Δεν είναι και πολύ λύση οπότε για ποιό λόγο να υπάρχει; Και τι σχέση έχει το multithreading και τα mutex μ' αυτό που κάνεις; Ένα single threaded πρόγραμμα τρέχει κάθε τόσο και κάνει κάτι. Άμα κάποιος άλλος από αυτό το πρόγραμμα πειράζει το αρχείο σου την ίδια στιγμή που το γράφεις εσύ προφανώς ούτε mutex ούτε flock κάνει καμία διαφορά.

 

Γνωρίζω από Sass και Less αλλά δεν μου αρέσει να επενδύω σε αυτά, γιατί εκτός του ότι προσωπικά δεν νιώθω ότι με διευκολύνουν, στο κοντινό μέλλον θα αντικατασταθούν και προτιμώ να αναπτύσσω λύσεις που θα χρησιμοποιώ για χρόνια στη δουλειά μου.

Ακούγεται καθαρά σα Not Invented Here syndrome.

 

Δεν εννοώ ότι θα σταματήσουν να λειτουργούν οι υλοποιήσεις μου με Sass, αλλά μπορεί π.χ. να έχουμε CSS variables κ.λπ. και οπότε θα θέλω να ξηλώσω το ξεπερασμένο πλέον Sass για να χρησιμοποιήσω την ευκολότερη και καθαρότερη λύση.

Άμα φτάσεις στο σημείο να ξηλώσεις το sass επειδή "είναι ξεπερασμένο", το δικό σου custom πώς θα πρέπει να χαρακτηριστεί υπό τις ίδιες συνθήκες;

 

Και από τη στιγμή που το κάνω για οργάνωση, είναι πολύ σημαντικό για εμένα να κάνω τη δουλειά μου με μία κλάση. Έτσι θα μπορώ να την μεταφέρω σε όποιο web software/platform θέλω (π.χ. WordPress, Joomla κ.λπ.) ώστε να φτιάξω custom themes.

composer install και μεταφέρεις ο,τι θέλεις όπου θέλεις με χίλια δυο επιπλέον πλεονεκτήματα.

  • Like 1
Δημοσ.

Εάν δεν έχει τροποποιηθεί κάποιο css file τότε δεν γίνεται concatenation. ;)

 

Και πάλι όμως, το εξετάζει σε κάθε request, θα υπάρχει πάντα  ένα O(n) (τουλάχιστον).

Δεν θα έπρεπε να ασχοληθει ο server με όλο αυτο γενικά. Separate your concerns.

Δημοσ.

Και πάλι όμως, το εξετάζει σε κάθε request, θα υπάρχει πάντα  ένα O(n) (τουλάχιστον).

Δεν θα έπρεπε να ασχοληθει ο server με όλο αυτο γενικά. Separate your concerns.

 

Μόνο εάν εγώ έχω τροποποιήσει κάποιο αρχείο .css.

 

Πόσο 'βαρύς' πιστεύεις ότι είναι ένας έλεγχος των last modified times με το filemtime();

 

Έκανα ένα debugging για να δω script execution time και peak memory usage και φαινόταν 'ελαφρύ', αλλά εννοείται ότι θέλω γνώμες - γι' αυτό και άνοιξα αυτό το topic.

 

Όταν λες "κάθε φορά" ελπίζω δεν εννοείς σε κάθε HTTP request έτσι; Αλλά σε κάθε build ας πούμε.

 

Προσωπική μου άποψη ότι δίνεις βάρος σε στοιχεία που δεν έχουν καμία απολύτως σημασία αλλά ΟΚ. Με αυτό τον τρόπο επίσης "χάνεις" όλα τα πράγματα που είναι έτοιμα και δοκιμασμένα και τη δουλειά που πέφτει στο ΧΥΖ οικοσύστημα και πρέπει να τα ξανακάνεις μόνος σου.

Σε κάθε HTTP request.

 

Αν δεν μπορεί να είναι κάτι τόσο απλό όσο η κλάση που έφτιαξα, τότε θα πάω στο έτοιμο εργαλείο.

 

Δεν είναι και πολύ λύση οπότε για ποιό λόγο να υπάρχει; Και τι σχέση έχει το multithreading και τα mutex μ' αυτό που κάνεις; Ένα single threaded πρόγραμμα τρέχει κάθε τόσο και κάνει κάτι. Άμα κάποιος άλλος από αυτό το πρόγραμμα πειράζει το αρχείο σου την ίδια στιγμή που το γράφεις εσύ προφανώς ούτε mutex ούτε flock κάνει καμία διαφορά.

Περίπτωση multithreading -> πολλά νήματα του ίδιου προγράμματος να θέλουν να κάνουν read/write operations στο ίδιο αρχείο οπότε με το mutex το κάθε νήμα θα περιμένει να τελειώσουν τα υπόλοιπα από το synchronized block.

 

Περίπτωση "single threaded" PHP scriptάκι -> το ίδιο scriptάκι να καλεστεί πολλές φορές οπότε μια ενέργεια στο αρχείο μπορεί να μην έχει ολοκληρωθεί ενώ ξεκινάει η επόμενη.

 

Καλύτερα να έχω το flock() που σε κάποιες περιπτώσεις θα κάνει τη διαφορά, από το τίποτα. Εσύ τι θα χρησιμοποιούσες;

 

Ακούγεται καθαρά σα Not Invented Here syndrome.

 

Άμα φτάσεις στο σημείο να ξηλώσεις το sass επειδή "είναι ξεπερασμένο", το δικό σου custom πώς θα πρέπει να χαρακτηριστεί υπό τις ίδιες συνθήκες;

Οι μόνες κινήσεις που θέλω να κάνω είναι να τραβάω το αρχείο .css από τον server στο desktop μου, να το τροποποιώ και να το κάνω upload.

 

Και όταν ξεκινάω ένα νέο project θέλω απλά να πετάω το σύστημα για concatenation δηλ. μία κλάση σε έναν φάκελο και να είμαι έτοιμος. "Lazy syndrome", αυτό το δέχομαι.

 

Το δικό custom μου είναι υλοποίηση σε PHP - το πολύ να θεωρηθεί ξεπερασμένη η λογική που χρησιμοποιώ αλλά όχι το 'εργαλείο'.

 

composer install και μεταφέρεις ο,τι θέλεις όπου θέλεις με χίλια δυο επιπλέον πλεονεκτήματα.

 

Ξέρω πάνω κάτω τι κάνει επειδή ασχολούμε με phpBB development και το χρησιμοποιεί το phpBB software και τα extensions του.

 

Ωστόσο δεν ξέρω πως να το χρησιμοποιήσω για αυτά που θέλω να κάνω (π.χ. CSS dependencies για κάθε template) και στο documentation του δεν βλέπω κάτι σχετικό.

Δημοσ.

Σε κάθε HTTP request.

Έτσι εξηγούνται κάποια πράγματα...

 

Λοιπόν, don't do it, είναι απλά λάθος. Τα filemtime() κλπ που κάνεις οδηγούν σε stat call το οποίο είναι, στα πλαίσια του πόσο θα μπορούσε να παίρνει να εξυπηρετηθεί ένα http request, πάρα πολύ "ακριβό". Φυσικά αν η σελίδα έχει μηδέν traffic δεν πρόκειται να δεις κάποια διαφορά αλλά τότε ο,τι κι αν κάνεις δε θα δείξει διαφορά. Ειδικά από τη στιγμή που αν ασχοληθείς λίγο με caching στο browser -- που θα έπρεπε ήδη να το έχεις κάνει, αλλιώς γιατί ασχολούμαστε με προσπάθειες για manual optimization ενώ δεν έχουμε χρησιμοποιήσει ακόμα τα έτοιμα εργαλεία -- ακόμα και χωρίς concatenation δε θα γίνονται τα πολλά HTTP requests που αναφέρεις σα πρόβλημα γιατί θα εξυπηρετούνται από την cache.

 

Concatenation κλπ έχουν νόημα μόνο αν ήδη χρησιμοποιείς caching, και πάντα η διαδικασία γίνεται απαραίτητα ξεχωριστά από τα http requests των επισκεπτών. Ναι, αυτό σημαίνει πως δε μπορείς να είσαι look ma no hands αλλά υπάρχει κάποιος λόγος που δεν το κάνει κανένας (τον ανέφερα παραπάνω).

 

Περίπτωση multithreading -> πολλά νήματα του ίδιου προγράμματος να θέλουν να κάνουν read/write operations στο ίδιο αρχείο οπότε με το mutex το κάθε νήμα θα περιμένει να τελειώσουν τα υπόλοιπα από το synchronized block.

Ναι ΟΚ απλά αυτό δεν έχει να κάνει καθόλου με την παρούσα φάση.

 

Περίπτωση "single threaded" PHP scriptάκι -> το ίδιο scriptάκι να καλεστεί πολλές φορές οπότε μια ενέργεια στο αρχείο μπορεί να μην έχει ολοκληρωθεί ενώ ξεκινάει η επόμενη.

Εδώ ήδη θα έπρεπε να χτυπάνε καμπανάκια γιατί όταν ενεργοποιηθεί το concatenation και το flock() είναι έτοιμο να βγάλει τα λεφτά του, αυτό σημαίνει πως τα πράγματα είναι ακόμα χειρότερα από το συνεχές stat στα αρχεία: μέχρι να ολοκληρωθεί η διαδικασία, όλα τα requests που είναι στον αέρα περιμένουν να κάνουν το καθένα flock και concatenate με τη σειρά του και έχεις βάλει για λίγο το web server σε mode "ένας ένας όλοι θα πάρετε".

 

Καλύτερα να έχω το flock() που σε κάποιες περιπτώσεις θα κάνει τη διαφορά, από το τίποτα. Εσύ τι θα χρησιμοποιούσες;

Πάντα μα πάντα το να γίνονται πράγματα που επηρρεάζουν κάθε ένα HTTP request πρέπει να μη συμβαίνει σα μέρος του ίδιου του HTTP request. Το κάνεις με κάποιο εξωτερικό μηχανισμό. Όσο για locking εδώ δεν υπάρχει λόγος, απλά κάνεις generate στο tmp και όταν τελειώσεις move εκεί που θέλεις.

 

Και όταν ξεκινάω ένα νέο project θέλω απλά να πετάω το σύστημα για concatenation δηλ. μία κλάση σε έναν φάκελο και να είμαι έτοιμος. "Lazy syndrome", αυτό το δέχομαι.

Τροφή για σκέψη: άρα τελικά το σύστημα έχει σα σκοπό να βελτιώσει την ταχύτητα ή να βολέψει το lazy syndrome? Γιατί αυτά τα δύο έρχονται σε σύγκρουση. Έχει νόημα να χρησιμοποιείς κάτι που προσπαθεί να βολέψει ταυτόχρονα συγκρουόμενες απαιτήσεις;

 

Το δικό custom μου είναι υλοποίηση σε PHP - το πολύ να θεωρηθεί ξεπερασμένη η λογική που χρησιμοποιώ αλλά όχι το 'εργαλείο'.

Δεν καταλαβαίνω τότε με ποιά λογική θα μπορούσε να θεωρηθεί ξεπερασμένο κάποιο άλλο εργαλείο. Το αν κάτι είναι ξεπερασμένο ή όχι πάει με τη γλώσσα προγραμματισμού;

 

Ωστόσο δεν ξέρω πως να το χρησιμοποιήσω για αυτά που θέλω να κάνω (π.χ. CSS dependencies για κάθε template) και στο documentation του δεν βλέπω κάτι σχετικό.

Ο Composer δεν κάνει κάτι τέτοιο. Αυτό που κάνει είναι ότι σου επιτρέπει να βολέψεις το lazy syndrome χωρίς να πέφτεις σε επίπεδο "κάνω copy τη μία class". Το κάνει αυτό τραβώντας αυτόματα τα dependencies που εσύ θα του δηλώσεις και που είναι hosted στο github ή κάπου αλλού, δίνοντάς σου αυτόματα autoloader για να μην ασχολείσαι με τα κουραστικά και μέχρι που μπορεί να χρησιμοποιηθεί και σαν build system του φτωχού αυτοματοποιώντας διαδικασίες concatenation (που δε θα γίνονται look ma no hands όπως είπαμε) κλπ.

 

Σταμάτα οτιδήποτε άλλο κάνεις και μάθε να χρησιμοποιείς Composer.

Δημοσ.

Στην προκειμένη θα έλεγα σταμάτα τα πάντα και μάθε να χρησιμοποιείς grunt/gulp tasks (κατά προτίμηση το δεύτερο). Αυτό που ζητάς γίνεται ήδη μαζί με χιλιάδες άλλα common tasks (πχ less/scss compilation, minification για js/css, string search & replace, file sync και γενικότερα όλα τα tasks που χρειάζεσαι για να πας από unminified κώδικα σε production code). Τα tasks αυτά τρέχουν με έναν watcher όσο αναπτύσεις την εφαρμογή σου και ενημερώνουν το pre-production environment (ή test, dev, whatever environment) on-the-fly. Όταν είσαι ικανοποιημένος με το αποτέλεσμα, ανεβάζεις τον κώδικά σου στο σέρβερ σου και είσαι έτοιμος.

  • Like 2

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...