Rich Contenty – co trzeba wiedzieć

Rich Content to specyficzny format contentu i w zależności od wydawcy jego przygotowanie będzie wyglądać nieco inaczej. W tym artykule dowiesz się jak skonfigurować projekt i poznasz dobre praktyki dzięki którym zminimalizujesz ryzyko błędów.

Kilka podstawowych zasad

  • paczka pojedynczego rc powinna ważyć jak najmniej dlatego warto pamiętać aby w miarę możliwości skompresować wszystkie grafiki ( polecam https://www.iloveimg.com/compress-image )
  • najczęściej dozwolone formaty plików graficznych to jpg oraz png
  • pamiętaj o dodawaniu wersji paczek oraz plików
  • unikaj dołączania zewnętrznych bibliotek ( często są one zabronione )
  • jeśli rc wymaga napisania skryptu zrób to w czystym js’ie
  • zapoznaj się ze szczegółową specyfikacją techniczną jeśli istnieje
  • za nim wyślesz finalną paczkę poproś kolegę / koleżankę z zespołu o rzucenie okiem i przetestowanie

Stylowanie

W zależności od sposoby w jaki RC zostanie osadzony przyjmujemy dwa podejścia do stylowania.

  • Jeśli RC zostanie osadzony bezpośrednio na stronie

Ustawiamy style dla wszystkich elementów statycznie w px uwzględniając breakpointsy wydawcy

  • Jeśli RC zostanie osadzony jako iframe

Ustawiamy style dla wszystkich elementów bazując na vm oraz vh. W tym przypadku trzeba pamiętać że naszą wyjściowym punktem do przeliczeń będzie szerokość iframe dlatego podgląd podczas pracy nad projektem powinien być również jako iframe. W innym przypadku wielkości zostaną przeliczone względem szerokości przeglądarki i po wrzuceniu do iframe wielkości mogą się różnić.

Istnieje możliwość obejścia tego problemu poprzez zastosowanie container query units ale nie jest to jeszcze w pełni wspierane

https://ishadeed.com/article/container-query-units/

Konfiguracja projektu

W zależności od wydawcy konfiguracja projektu może się od siebie różnić. Niektórzy osadzają RC bezpośrednio w stukurze swoich serwisów a inni jako iframe. Należy zawsze zwrócić uwagę na wymagania odnośnie sposobu budowania struktury katalogowej oraz ustawieniu odpowiednich ścieżek.

Paczki generowane są przy pomocy gulpa a jego podstawowa konfiguracja wygląda następująco

const { watch, src, dest, series, parallel } = require('gulp');
const browserSync = require('browser-sync').create();
const autoprefixer = require('gulp-autoprefixer');
const sass = require('gulp-sass')(require('sass'));
const del = require('del');
const tinypng = require('gulp-tinypng-compress');
const cssmin = require('gulp-cssmin');
const rename = require('gulp-rename');
const replace = require('gulp-replace');

var dataArry = [
    {
        id: 0,
        ean_number: '3474637109387',
        product_name: 'product_name',
        assets_path: 'userdata/public/assets/cards/loreal-professionnel/scalp/',
    }
];

const config = {
    name: 'semilac/extendy',
    app: {
        scss: './dev/assets/scss/main.scss',
        images: './dev/assets/img/',
        html: './dev/base.html',
        css: './dev/assets/css',
        js: './dev/assets/js',
        fonts: './dev/assets/fonts/**/*.*',
    },
    dist: {
        base: './dist/**',
    }
}

const cleanTemp = (done) => del('./dev/assets/_temp/**/*.*')

const tinypngTask = (done) => {
    src('./dev/assets/_temp/**/*.{png,jpg,jpeg,ico}')
        .pipe(tinypng({
            key: 'SFfxZhtQHN2lS2GCgK4k3Svr54bBjm5s',
            log: true
        }))
        .pipe(dest('./dev/assets/img/'))
    done();
}

const moveImages = (done) => {
    src('./dev/assets/img/**/*.{png,jpg,jpeg,ico}')
        .pipe(dest('./dev/assets/_temp'))
    done();
}

const cleanImages = (done) => {
    return del('./asssets/dev/img');
}

const cssTask = (done) => {
    src(config.app.scss)
        .pipe(sass({
            outputStyle: 'expanded'
        }))
        .pipe(autoprefixer({
            cascade: false
        }))
        .pipe(dest(
            config.app.css
        ))
    done();
}

const cssDist = (done) => {
    dataArry.forEach(function(obj) {
        src(config.app.css + '/**.css')
            .pipe(rename({
                basename: "loreal-professionnel-scalp",
            }))
            .pipe(dest('./dist/css'))
        done();
    });
}


const cleanDist = () => {
    return del(config.dist.base);
}


const imagesTask = (done) => {
    dataArry.forEach(function(obj) {
        src(config.app.images + obj.product_name + '/**/*.*')
            .pipe(dest('./dist/' + obj.assets_path + obj.product_name))
        done();
    });  
}


const watchFiles = () => {
    watch(config.app.html, series(indexReplace, reload));
    watch(config.app.scss, series(cssTask, reload));
}

const reload = (done) => {
    browserSync.reload();
    done();
}

const browser = () => {
    browserSync.init({
        server: {
            baseDir: './dev/'
        }
    });
}



const indexReplace = (done) => {
    src(['./dev/base.html'])
        .pipe(replace('{{text_replace}}', dataArry[0].text_replace))
        .pipe(rename("index.html"))
        .pipe(dest('./dev/'))
        done();
}

const indexDist = (done) => {
    dataArry.forEach(function(obj) {
        src(['./dev/base.html'])
            .pipe(replace('{{text_replace}}', obj.text_replace))
            .pipe(rename(obj.ean_number + ".html"))
            .pipe(dest('./dist/'))
        done();
    });
}


const fontsDist = (done) => {
    dataArry.forEach(function(obj) {
        src(config.app.fonts)
            .pipe(dest('./dist/' + obj.assets_path + '/fonts'))
        done();
    });  
}


exports.dev = parallel(
    cssTask,
    watchFiles,
    // indexReplace,
    browser,
);

exports.build = series(
    cleanDist,
    parallel(
        cssDist,
        imagesTask,
        indexDist,
        // jsDist,
        // fontsDist,
    )
);

exports.compress = series(
    cleanTemp,
    moveImages,
    cleanImages,
    tinypngTask,
);

Struktura katalogowa

nazwa_klienta 
   - nazwa_wydawcy 
      - gulpfile.js 
      - package.json 
      - dev 
         - base.html 
         - index.html
         - assets
            - css
            - js
            - img
            - fonts 
       - dist

Odpalenia projektu w trybie deweloperskim

gulp dev

W tym momencie na podstawie pliku base.html zostanie wygenerowany index.html który będzie nadpisywany za każdym razem kiedy wprowadzimy zmiany w base.html lub plikach css i js. W przeglądarce otworzy się nowe okno z podglądem projektu, zmiany będą odświeżane automatycznie.

Podmian tekstu

Jeśli teksty w projekcie dla każdego produktu mogę się różnić należy uwzględnić je w strukturze oraz konfiguracji. W funkcji indexReplace oraz indexDist należy dodać następującą instrukcje

// indexReplace

.pipe(replace('{{text_replace}}', dataArry[0].text_replace))

dataArry[0] – możemy podmienić na dowolny identyfikator z tablicy produktowej jeśli chcemy mieć podgląd konkretnego produktu.

//indexDist

.pipe(replace('{{text_replace}}', obj.text_replace))

Po każdej tego typu operacji musimy zrestartować proces

Budowanie paczki

Przed zbudowaniem paczki należy określić ścieżki docelowe dla wszystkich zasobów tak aby zgadzały się z specyfikacją oraz strukturą html

Dla każdego zasoby mamy możliwość określenia docelowej ścieżki ( funkcje fontsDist, indexDist, cssDist, imagesTask )

Możemy zdefiniować ją statycznie lub dynamicznie na bazie danych z tablicy

src(config.app.images + obj.product_name + '/**/*.*')
    .pipe(dest('./dist/project_name/css'))
done();
src(config.app.images + obj.product_name + '/**/*.*')
    .pipe(dest('./dist/' + obj.assets_path + obj.product_name))
done();

const imagesTask = (done) => {
    dataArry.forEach(function(obj) {
        src(config.app.images + obj.product_name + '/**/*.*')
            .pipe(dest('./dist/' + obj.assets_path + obj.product_name))
        done();
    });  
}
const fontsDist = (done) => {
    dataArry.forEach(function(obj) {
        src(config.app.fonts)
            .pipe(dest('./dist/' + obj.assets_path + '/fonts'))
        done();
    });  
}
const cssDist = (done) => {
    dataArry.forEach(function(obj) {
        src(config.app.css + '/**.css')
            .pipe(rename({
                basename: "css_file_name",
            }))
            .pipe(dest('./dist/css'))
        done();
    });
}

Funkcja indexDist podczas generowania pliku docelowego odpowiedzialna jest za podmianę ścieżek do plików oraz wygenerowania właściwych tekstów.


const indexDist = (done) => {
    dataArry.forEach(function(obj) {
        src(['./dev/base.html'])
            .pipe(replace('{{text_replace}}', obj.text_replace))
            .pipe(replace('assets/img/base', obj.assets_path + obj.product_name))
            .pipe(replace('assets/css/main.css', './css/css_file_name.css'))
            .pipe(rename(obj.ean_number + ".html"))
            .pipe(dest('./dist/'))
        done();
    });
}

Na koniec w celu zbudowania paczki należy wykonać polecenie

gulp build