Schönes Frontend-Projekt

  • Tutorial
In diesem Artikel werden wir den Prozess der Zusammenstellung eines Front-End-Projekts, das sich in meiner täglichen Arbeit festgesetzt und die Routine erheblich vereinfacht hat, im Detail analysieren.

Der Artikel behauptet nicht, die ultimative Wahrheit zu sein, da es heutzutage eine große Anzahl unterschiedlicher Assembler und Assembler-Ansätze gibt und jeder nach Belieben schmeckt. Ich werde nur meine Gedanken zu diesem Thema teilen und meinen Workflow zeigen.

UPD (13. März 2015): Mehrere Plugins wurden durch relevantere ersetzt. + Das Problem beim Importieren von CSS-Dateien in SCSS wurde behoben.


Wir werden den Gulp- Collector verwenden . Dementsprechend muss Node js auf Ihrem System installiert sein. Wir werden nicht in Betracht ziehen, einen Knoten für eine bestimmte Plattform zu installieren, weil Es ist Google in ein paar Minuten.
Und zunächst werde ich die Frage beantworten - warum Gulp?

Von mehr oder weniger erträglichen Alternativen haben wir Grunzen und Brunch .

Als ich gerade anfing, mich mit Monteuren zu beschäftigen, waren sowohl Grunt als auch Gulp bereits auf dem Markt. Die erste erschien früher und hat daher eine größere Community und eine Vielzahl von Plugins. Laut npm :
Grunt - 11171 Paket
Gulp - 4371 Paket

Aber Grunt erschien mir ein bisschen zu wortreich. Und nachdem ich mehrere Vergleichsartikel gelesen hatte, zog ich Gulp wegen seiner Einfachheit und Klarheit vor.

Brunch ist ein relativ junges Projekt, aus dem alle Vor- und Nachteile resultieren. Ich beobachte ihn mit Interesse, habe es aber noch nicht in meiner Arbeit verwendet.

Weiter:

Erstellen Sie einen Ordner für unser Projekt, zum Beispiel "habr". Öffne es in der Konsole und führe den Befehl aus:

npm init

Sie können bei allen Fragen des Installationsprogramms einfach die Eingabetaste drücken, weil Jetzt ist es egal.
Als Ergebnis generieren wir im Ordner mit dem Projekt die Datei package.json wie folgt:

{
  "name": "habr",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Wir werden es leicht an unsere Bedürfnisse anpassen:

{
  "name": "habr",
  "version": "1.0.0",
  "description": "",
  "author": "",
  "license": "ISC",
  "dependencies": {
      "gulp": "^3.8.11"
   }
}

Im Abhängigkeitsblock haben wir angegeben, dass wir gulp benötigen, und wir werden sofort alle unsere Plugins registrieren.

Plugins

gulp-autoprefixer — автоматически добавляет вендорные префиксы к CSS свойствам (пару лет назад я бы убил за такую тулзу)
gulp-minify-css — нужен для сжатия CSS кода
browser-sync — с помощью этого плагина мы можем легко развернуть локальный dev сервер с блэкджеком и livereload, а так же с его помощью мы сможем сделать тунель на наш localhost, что бы легко демонстрировать верстку заказчику
gulp-imagemin — для сжатия картинок
imagemin-pngquant — дополнения к предыдущему плагину, для работы с PNG
gulp-uglify — будет сжимать наш JS
gulp-sass — для компиляции нашего SCSS кода
Не холивара ради
Ich habe LESS sehr lange in meiner Arbeit verwendet. Ich war von diesem Präprozessor sehr beeindruckt, da er schnell und einfach zu erlernen ist. Auch hat ein Bericht über sie in einem Rostov Hackathon. Und insbesondere in diesem Bericht habe ich nicht sehr schmeichelhaft über SASS gesprochen.
Aber die Zeit verging, ich wurde älter und weiser :) und jetzt trat ich diesem Präprozessor bei.
Die Basis meiner Unzufriedenheit mit SASS - war, dass ich nicht in Reibung schreibe. Und als es notwendig war, SASS / SCSS-Code zu kompilieren, musste man das Projekt mit den erforderlichen Bundles einschleppen, was mich wirklich verärgerte.
Aber das alles mit dem Aufkommen der so etwas wie ein verändertes LibSass . Dies ist der C / C ++ - Compiler-Port für SASS. Das Gulp-Sass-Plugin verwendet es. Jetzt können wir SASS in der Native Node-Umgebung verwenden - das freut mich außerordentlich.

gulp-sourcemaps - Lassen Sie uns CSS-Sourscemaps generieren, die uns beim Debuggen des
gulp-rigger-Codes helfen - es ist nur eine Killer-Funktion. Das Plugin ermöglicht es Ihnen, eine Datei mit einem einfachen Design in eine andere zu importieren
//= footer.html

und diese Zeile beim Kompilieren wird durch den Inhalt der Datei footer.html
gulp-watch ersetzt - Wird benötigt, um Dateiänderungen zu überwachen. Ich weiß, dass Gulp eine eingebaute Uhr hat, aber ich hatte einige Probleme damit, insbesondere sah er die neu erstellten Dateien nicht und musste sie neu starten. Dieses Plugin hat das Problem behoben (ich hoffe, dies wird in zukünftigen Versionen von gulp behoben).
rimraf - rm -rf für den Knoten

Installieren Sie alle Plugins und holen Sie sich das folgende package.json in die Ausgabe:

{
  "name": "habr",
  "version": "1.0.0",
  "description": "",
  "author": "",
  "license": "ISC",
 "dependencies": {
    "browser-sync": "^2.2.3",
    "gulp": "^3.8.11",
    "gulp-autoprefixer": "^2.1.0",
    "gulp-imagemin": "^2.2.1",
    "gulp-minify-css": "^1.0.0",
    "gulp-rigger": "^0.5.8",
    "gulp-sass": "^1.3.3",
    "gulp-sourcemaps": "^1.5.0",
    "gulp-uglify": "^1.1.0",
    "gulp-watch": "^4.1.1",
    "imagemin-pngquant": "^4.0.0",
    "rimraf": "^2.3.1"
  }
}


Bower

Ich kann mir meine Arbeit ohne den Bower- Paketmanager nicht vorstellen, und das hoffe ich auch. Wenn nicht, lesen Sie es und was es isst, können Sie hier .
Fügen wir es unserem Projekt hinzu. Führen Sie dazu den Befehl in der Konsole aus:

bower init

Sie können auch alle Fragen eingeben.
Am Ende erhalten wir so etwas wie diese bower.json-Datei:

{
  "name": "habr",
  "version": "0.0.0",
  "authors": [
    "Insayt "
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

Und wir passen es an den Zustand an, den wir brauchen:

{
  "name": "habr",
  "version": "0.0.0",
  "authors": [
    "Insayt "
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "normalize.css": "*",
    "jquery": "2.*"
  }
}

Im Abhängigkeitsblock geben wir die Abhängigkeiten unseres Projekts an. Jetzt ist es nur für den Test normalisiert und jQuery (obwohl ich mich nicht erinnere, wann ich das Projekt ohne diese Dinge gestartet habe).
Und natürlich installieren Sie sie mit dem Befehl:

bower i

Nun, jetzt das interessanteste. Erstellen Sie die Struktur unseres Projekts und konfigurieren Sie den Kollektor.

Projektstruktur:


Dies ist ein sehr kontroverser Moment. Natürlich sind Projekte anders, genau wie die Vorlieben der Entwickler. Man muss sich nur die yeoman.io- Website ansehen (dies ist übrigens ein sehr cooles Tool, das eine große Anzahl vorbereiteter Frameworks für ein Projekt mit allen möglichen Extras bereitstellt. Es lohnt sich auf jeden Fall, einen Blick darauf zu werfen). Wir werden nichts erfinden und die einfachste Struktur machen.

Zuerst brauchen wir 2 Ordner. Eine (src), in die wir den Code schreiben, und die zweite (build), in die der Collector die fertigen Dateien ausspuckt. Fügen Sie sie dem Projekt hinzu. Unsere aktuelle Struktur sieht folgendermaßen aus:



Erstellen Sie im Ordner src eine typische Struktur eines durchschnittlichen Projekts. Lassen Sie uns die Hauptdateien in den Ordnern js / und style / erstellen und die erste HTML-Seite mit solchen Inhalten erstellen.

index.html
Я собираю проекты как рок звезда
Header
Content

Die src-Ordnerstruktur sieht nun folgendermaßen aus: Hier ist



alles trivial:
fonts -
img fonts -
js pictures - scripts. Im Stammverzeichnis dieses Ordners befindet sich nur die Datei main.js, die für die Montage nützlich ist. Alle Ihre js-Dateien - Sie müssen in den Ordner partials
style - styles einfügen . Es gibt auch nur main.scss im Stammverzeichnis und die Arbeitsdateien im Ordner partials
template - hier werden sich wiederholende Teile des HTML-Codes gespeichert.
Alle HTML-Seiten, die wir erstellen, werden im src-Stammverzeichnis
abgelegt. Fügen Sie die ersten js- und scss-Dateien zu den Partials hinzu und fertig in das Stammverzeichnis unseres Projekts und erstellen Sie dort die Datei gulpfile.js. Der gesamte Projektordner sieht jetzt so aus:



Jetzt ist alles bereit, um unseren Kollektor zu konfigurieren, also lasst uns rocken!

Gulpfile.js

Alle Magie wird in dieser Datei eingeschlossen. Zu Beginn importieren wir alle unsere Plugins und schlucken selbst

gulpfile.js
'use strict';
var gulp = require('gulp'),
    watch = require('gulp-watch'),
    prefixer = require('gulp-autoprefixer'),
    uglify = require('gulp-uglify'),
    sass = require('gulp-sass'),
    sourcemaps = require('gulp-sourcemaps'),
    rigger = require('gulp-rigger'),
    cssmin = require('gulp-minify-css'),
    imagemin = require('gulp-imagemin'),
    pngquant = require('imagemin-pngquant'),
    rimraf = require('rimraf'),
    browserSync = require("browser-sync"),
    reload = browserSync.reload;

Das ist natürlich nicht nötig. Es ist ein Plug- schluck-Last-Plugins , die Sie alles schreiben können von Nudeln erfordern. Aber ich mag es, wenn ich klar sehe, was verbunden ist und wo und wenn ich will, kann ich es ausschalten. Dafür schreibe ich auf die altmodische Art und Weise.

Wir erstellen auch ein js-Objekt, in das wir alle Pfade schreiben, die wir benötigen, damit es bei Bedarf einfach ist, sie an einer Stelle zu bearbeiten:

var path = {
    build: { //Тут мы укажем куда складывать готовые после сборки файлы
        html: 'build/',
        js: 'build/js/',
        css: 'build/css/',
        img: 'build/img/',
        fonts: 'build/fonts/'
    },
    src: { //Пути откуда брать исходники
        html: 'src/*.html', //Синтаксис src/*.html говорит gulp что мы хотим взять все файлы с расширением .html
        js: 'src/js/main.js',//В стилях и скриптах нам понадобятся только main файлы
        style: 'src/style/main.scss',
        img: 'src/img/**/*.*', //Синтаксис img/**/*.* означает - взять все файлы всех расширений из папки и из вложенных каталогов
        fonts: 'src/fonts/**/*.*'
    },
    watch: { //Тут мы укажем, за изменением каких файлов мы хотим наблюдать
        html: 'src/**/*.html',
        js: 'src/js/**/*.js',
        style: 'src/style/**/*.scss',
        img: 'src/img/**/*.*',
        fonts: 'src/fonts/**/*.*'
    },
    clean: './build'
};


Erstellen Sie eine Variable mit den Einstellungen unseres Entwicklerservers:

var config = {
    server: {
        baseDir: "./build"
    },
    tunnel: true,
    host: 'localhost',
    port: 9000,
    logPrefix: "Frontend_Devil"
};


HTML zusammenstellen

Schreiben wir eine Aufgabe für die HTML-Assemblierung:

gulp.task('html:build', function () {
    gulp.src(path.src.html) //Выберем файлы по нужному пути
        .pipe(rigger()) //Прогоним через rigger
        .pipe(gulp.dest(path.build.html)) //Выплюнем их в папку build
        .pipe(reload({stream: true})); //И перезагрузим наш сервер для обновлений
});

Ich möchte Sie daran erinnern, dass Rigger unser Plugin ist, mit dem Sie dieses Design zum Importieren von Dateien verwenden können:

//= template/footer.html

Lass es uns in Aktion einsetzen!
Erstellen Sie im Ordner src / template / die Dateien header.html und footer.html mit dem folgenden Inhalt

header.html
Header


footer.html
Footer


und ändere unsere index.html Datei wie folgt:
Я собираю проекты как рок звезда


    //= template/header.html
    
Content
//= template/footer.html


Es bleibt zu der Konsole zu gehen und unsere Aufgabe mit dem Befehl auszuführen:

gulp html:build

Nachdem es funktioniert, gehen Sie in den Build-Ordner und sehen Sie sich dort unsere Datei index.html an.

Я собираю проекты как рок звезда
Header
Content

Es ist einfach unglaublich!

Ich erinnere mich an die vielen Unannehmlichkeiten, die es mit sich brachte, alle Seiten durchzugehen und Änderungen an Teilen vorzunehmen, die sie wiederholen. Dies geschieht nun bequem an einem Ort.

Bauen Sie Javascript

Die Skriptassemblierungsaufgabe sieht folgendermaßen aus:

gulp.task('js:build', function () {
    gulp.src(path.src.js) //Найдем наш main файл
        .pipe(rigger()) //Прогоним через rigger
        .pipe(sourcemaps.init()) //Инициализируем sourcemap
        .pipe(uglify()) //Сожмем наш js
        .pipe(sourcemaps.write()) //Пропишем карты
        .pipe(gulp.dest(path.build.js)) //Выплюнем готовый файл в build
        .pipe(reload({stream: true})); //И перезагрузим сервер
});

Erinnern Sie sich an unsere Datei main.js?
Die ganze Idee hier ist, Rigger zu verwenden, um alle JS-Dateien, die wir brauchen, in der Reihenfolge, in der wir sie brauchen, darin aufzunehmen. Es dient der Kontrolle über die Verbindungsreihenfolge - ich mache es auf diese Weise, anstatt gulp zu bitten, alle * .js-Dateien zu finden und sie zu kleben.

Wenn ich nach dem Ort eines Fehlers suche, schalte ich häufig einige Dateien der Reihe nach aus, um den Ort des Problems zu lokalisieren. Wenn Sie sinnlos alle .js-Debugs zusammenkleben, wird dies kompliziert.

Füllen Sie unsere main.js aus:

/*
 * Third party
 */
//= ../../bower_components/jquery/dist/jquery.js
/*
 * Custom
 */
//= partials/app.js

Genau das mache ich bei Kampfprojekten. Am Anfang dieser Datei steht immer die Verknüpfung von Abhängigkeiten, unterhalb der Verknüpfung meiner eigenen Skripte.

Übrigens, Laubenpakete können über ein Plugin wie eine Schluck-Laube verbunden werden . Aber ich mache das auch nicht, weil ich selbst bestimmen will, was, wo und wie es sich verbinden soll.

Es bleibt nur, um unsere Aufgabe von der Konsole mit dem Befehl zu starten:

gulp js:build  

Und im build / js-Ordner sehen wir unsere kompilierte und komprimierte Datei.

Wir sammeln Stile


Schreiben wir eine Aufgabe zum Aufbau unseres SCSS:

gulp.task('style:build', function () {
    gulp.src(path.src.style) //Выберем наш main.scss
        .pipe(sourcemaps.init()) //То же самое что и с js
        .pipe(sass()) //Скомпилируем
        .pipe(prefixer()) //Добавим вендорные префиксы
        .pipe(cssmin()) //Сожмем
        .pipe(sourcemaps.write())
        .pipe(gulp.dest(path.build.css)) //И в build
        .pipe(reload({stream: true}));
});

Hier ist alles einfach, aber möglicherweise interessieren Sie sich für die Auto-Fix-Einstellungen. Standardmäßig werden die für die letzten beiden Browserversionen erforderlichen Präfixe geschrieben. In meinem Fall ist dies ausreichend, aber wenn Sie andere Einstellungen benötigen, finden Sie diese hier .

Mit Stilen mache ich dasselbe wie mit js, aber nur anstelle von Rigger verwende ich den in SCSS integrierten Import.
UPD (13. März 2015): Einige Benutzer haben Probleme beim Inline-Import von CSS-Dateien. Wie sich herausstellte, weiß gulp-sass nicht, wie das geht, und die Ausgabe bietet einen einfachen CSS-Import. Unser gulp-minify-css-Plugin behebt dieses Problem, bei dem der CSS-Import durch den Inhalt der Datei ersetzt wird.
Unsere main.scss wird so aussehen:
/*
* Third Party
*/
@import "../../bower_components/normalize.css/normalize.css";
/*
* Custom
*/
@import "partials/app";

Auf diese Weise können Sie leicht steuern, wie Stile verbunden sind.
Lassen Sie uns unsere Aufgabe durch Laufen überprüfen
gulp style:build


Wir sammeln Bilder


Die Aufgabe in den Bildern sieht folgendermaßen aus:

gulp.task('image:build', function () {
    gulp.src(path.src.img) //Выберем наши картинки
        .pipe(imagemin({ //Сожмем их
            progressive: true,
            svgoPlugins: [{removeViewBox: false}],
            use: [pngquant()],
            interlaced: true
        }))
        .pipe(gulp.dest(path.build.img)) //И бросим в build
        .pipe(reload({stream: true}));
});

Ich verwende die Standardeinstellungen für Imagemin, mit Ausnahme von Interlaced. Erfahren Sie mehr über die API dieses Plugin kann gelesen werden hier .

Wenn wir nun ein Bild in src / img einfügen und den Befehl ausführen:

gulp image:build

Wir werden unser optimiertes Image im Build sehen. Außerdem schreibt gulp freundlicherweise in die Konsole, wie viel Speicherplatz er für die Benutzer unserer Website gespart hat.

Schriften


Normalerweise muss ich keine Schriftarten manipulieren, aber um das Paradigma "Wir arbeiten in src / und bauen in build / zusammen" nicht zu zerstören, kopiere ich einfach Dateien aus src / fonts und füge sie in build / fonts ein. Hier ist die Aufgabe:

gulp.task('fonts:build', function() {
    gulp.src(path.src.fonts)
        .pipe(gulp.dest(path.build.fonts))
});


Definieren wir nun eine Aufgabe namens "build", die alles ausführt, was Sie und ich hier hochgeladen haben:

gulp.task('build', [
    'html:build',
    'js:build',
    'style:build',
    'fonts:build',
    'image:build'
]);


Dateiänderungen


Um nicht die ganze Zeit in die Konsole zu klettern, bitten wir gulp, die erforderliche Aufgabe jedes Mal auszuführen, wenn Sie eine Datei ändern. Dazu schreibt er eine solche Aufgabe:

gulp.task('watch', function(){
    watch([path.watch.html], function(event, cb) {
        gulp.start('html:build');
    });
    watch([path.watch.style], function(event, cb) {
        gulp.start('style:build');
    });
    watch([path.watch.js], function(event, cb) {
        gulp.start('js:build');
    });
    watch([path.watch.img], function(event, cb) {
        gulp.start('image:build');
    });
    watch([path.watch.fonts], function(event, cb) {
        gulp.start('fonts:build');
    });
});

Mit Verstehen sollte es kein Problem geben. Wir folgen einfach unseren Pfaden, die in der Pfadvariablen definiert sind, und fordern Sie in der Funktion, die aufgerufen wird, wenn sich die Datei ändert, auf, die von uns benötigte Aufgabe auszuführen.

Versuchen Sie es in der Konsole:

gulp watch

Und tauschen Sie verschiedene Dateien aus.
Ist es nicht cool?

Webserver


Um das Wunder der Leberbelastung zu genießen, müssen wir einen lokalen Webserver für uns selbst erstellen. Dazu schreiben Sie die folgende einfache Aufgabe:

gulp.task('webserver', function () {
    browserSync(config);
});

Es gibt sogar nichts zu kommentieren. Wir starten einfach den Livereload-Server mit den Einstellungen, die wir im Konfigurationsobjekt definiert haben. Außerdem wird gulp unser Projekt höflich in einem Browser öffnen und in der Konsole Links zum lokalen Server und zum Tunnel schreiben, die wir dem Kunden zur Demonstration zur Verfügung stellen können.

Reinigung


Wenn Sie ein Bild hinzufügen, führen Sie den Befehl image: build aus und löschen Sie das Bild. Es verbleibt im Erstellungsordner. Es wäre also zweckmäßig, es regelmäßig zu reinigen. Lassen Sie uns dazu eine einfache Aufgabe erstellen.

gulp.task('clean', function (cb) {
    rimraf(path.clean, cb);
});

Jetzt, wenn Sie den Befehl ausführen
gulp clean

Nur der Build-Ordner wird gelöscht.

Schlussakkord


Das Letzte - wir werden die Standardaufgabe bestimmen, die unsere gesamte Baugruppe ausführen wird.

gulp.task('default', ['build', 'webserver', 'watch']);


Schließlich Ihr gulpfile.js wird etwas sehen wie folgt aus .
Jetzt in der Konsole laufen
gulp

Und voila. Die Vorbereitung für Ihr Projekt ist fertig und wartet auf Sie.

Ein paar Worte zum Schluss


Dieser Artikel wurde konzipiert, um die Feinheiten des Assemblierens von Frontend-Projekten erneut aufzufrischen und diese Erfahrung einfach auf neue Entwickler zu übertragen. Sie müssen eine solche Assembly-Option nicht für Ihre Projekte verwenden. Es gibt yeoman.io, wo Sie Generatoren für fast jeden Bedarf finden.
Ich habe diesen Sammler aus drei Gründen geschrieben.
- Ich verwende Rigger gerne in meinem HTML-Code.
- In fast allen Assemblys, die ich gesehen habe, wird ein temporärer Ordner (normalerweise .tmp /) verwendet, um Zwischenergebnisse der Assembly aufzuzeichnen. Ich mag diesen Ansatz nicht und wollte temporäre Ordner loswerden.
"Und ich wünschte, all das wäre nicht in meinem Kasten."

Sie können meine Arbeitsversion des Sammlers auf meinem Github herunterladen .

Ich hoffe, dieser Artikel hat Ihnen geholfen.

PS Über alle Fehler, Mängel und Pfosten - bitte in einem persönlichen schreiben.

Jetzt auch beliebt: