Strona Główna Blog webmasterski

Sass w Web Components

Nawiązując do poprzedniego artykułu pt. „Pierwszy komponent w Polymerze”, chciałbym zwrócić uwagę na problem związany z umieszczaniem stylów wewnątrz pliku HTML.

Dla przypomnienia wstawię kod źródłowy z poprzedniego wpisu.

<dom-module id="polymer-modal-style">
    <template>
        <style>
            :host {
                --modal-width: 400px;
                --modal-background: #fff;
                --modal-padding: 10px;
                --modal-border: 1px solid #000;
                display: none;
            }

            :host([opened]) {
                position: fixed;
                top: 0;
                left: 0;
                display: flex;
                width: 100vw;
                height: 100vh;
                overflow-y: auto;
                overflow-x: hidden;
                justify-content: center;
                align-items: center;
            }

            .modal {
                position: relative;
                top: 0;
                left: 0;
                width: var(--modal-width);
                background: var(--modal-background);
                padding: var(--modal-padding);
                border: var(--modal-border);
            }

            .modal__heading {
                border-bottom: var(--modal-border);
            }

            .modal__close {
                position: absolute;
                top: var(--modal-padding);
                right: var(--modal-padding);
            }
        </style>
    </template>
</dom-module>

Umieszczenie stylów w pliku HTML, powoduje komplikacje, w momencie, gdybyśmy chcieli użyć preprocesora Sass. Wynika to z faktu, że Sass nie potrafi ignorować znaczników HTML. Próba skompilowania powyższego kodu najpewniej zakończy się syntax errorem.

Rozwiązanie problemu

W celu rozwiązania problemu użyję Gulpa, gulp-sass i gulp-style-modules. Szczególnie istotny jest tutaj plugin gulp-style-modules, którego zadaniem jest opakowywanie kodu CSS w deklarację modułu typową dla Polymera.

Utwórzmy zatem plik package.json:

{
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-sass": "^3.1.0",
    "gulp-style-modules": "^0.1.0"
  }
}

Teraz należy wykonać komendę npm install i utworzyć plik o nazwie gulpfile.js, w którym zostanie napisany task odpowiedzialny za kompilowanie plików .scss.

const gulp = require('gulp');
const stylemod = require('gulp-style-modules');
const sass = require('gulp-sass');

gulp.task('modularize-styles', () => {
    return gulp.src('./src/elements/**/*.scss')
        .pipe(sass({
            outputStyle: 'compressed',
        }).on('error', sass.logError))
        .pipe(stylemod())
        .pipe(gulp.dest("./src/elements"));
});

gulp.task('watch:modularize-styles', () => {
    return gulp.watch('./src/elements/**/*.scss', ['modularize-styles']);
});

W powyższym pliku zostały utworzone dwa taski: modularize-styles i watch:modularize-styles. Pierwszy z nich służy do budowania modułów ze stylami, natomiast drugi do tego samego, lecz w czasie rzeczywistym (jest to tzw. watcher).

Od teraz dla każdego z plików scss umieszczonych w folderze src/elements, zostanie utworzony plik modułu z przyrostkiem -styles.html.

Utworzę plik o nazwie polymer-modal.scss, żeby zobrazować jak to działa.

:host {
  --modal-width: 400px;
  --modal-background: #fff;
  --modal-padding: 10px;
  --modal-border: 1px solid #000;
  display: none;
}

:host([opened]) {
  position: fixed;
  top: 0;
  left: 0;
  display: flex;
  width: 100vw;
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  justify-content: center;
  align-items: center;
}

.modal {
  position: relative;
  top: 0;
  left: 0;
  width: var(--modal-width);
  background: var(--modal-background);
  padding: var(--modal-padding);
  border: var(--modal-border);

  &__heading {
    border-bottom: var(--modal-border);
  }

  &__close {
    position: absolute;
    top: var(--modal-padding);
    right: var(--modal-padding);
  }
}

Po uruchomieniu komendy gulp modularize-styles zostanie utworzony plik polymer-modal-styles.html. W jego wnętrzu znajdzie się deklaracja modułu o id identycznym z nazwą pliku bez rozszerzenia.

Tak wygląda kod wynikowy:

<dom-module id="polymer-modal-styles">
<template>
<style>
:host{--modal-width:400px;--modal-background:#fff;--modal-padding:10px;--modal-border:1px solid #000;display:none}:host([opened]){position:fixed;top:0;left:0;display:flex;width:100vw;height:100vh;overflow-y:auto;overflow-x:hidden;justify-content:center;align-items:center}.modal{position:relative;top:0;left:0;width:var(--modal-width);background:var(--modal-background);padding:var(--modal-padding);border:var(--modal-border)}.modal__heading{border-bottom:var(--modal-border)}.modal__close{position:absolute;top:var(--modal-padding);right:var(--modal-padding)}

</style>
</template>
</dom-module>

Podsumowanie

Pokazałem, że używanie Sass w komponentach webowych wcale nie jest takie trudne. Co prawda wymaga to poświęcenia dodatkowego czasu na skonfigurowanie gulpa, ale w ostatecznym rozrachunku i tak się to opłaci ze względu na zmniejszoną liczbę linii kodu źródłowego stylów.