Membuat aplikasi web dengan Yeoman dan Polymer

Membuat scaffold aplikasi web dengan alat modern

Addy Osmani
Addy Osmani

Pengantar

Allo’ Allo’. Siapa pun yang menulis aplikasi web tahu betapa pentingnya untuk tetap produktif. Anda akan menghadapi tantangan saat harus khawatir dengan tugas yang merepotkan seperti menemukan boilerplate yang tepat, menyiapkan alur kerja pengembangan dan pengujian, serta melakukan minifikasi dan kompresi semua sumber.

Untungnya, alat frontend modern dapat membantu mengotomatiskan sebagian besar hal ini, sehingga Anda dapat berfokus pada penulisan aplikasi yang luar biasa. Artikel ini akan menunjukkan cara menggunakan Yeoman, alur kerja alat untuk aplikasi web guna menyederhanakan pembuatan aplikasi menggunakan Polymer, library polyfill dan sugar untuk mengembangkan aplikasi menggunakan Komponen Web.

Yeoman

Temui Yo, Grunt, dan Bower

Yeoman adalah pria yang mengenakan topi dengan tiga alat untuk meningkatkan produktivitas Anda:

  • yo adalah alat scaffolding yang menawarkan ekosistem scaffold khusus framework, yang disebut generator yang dapat digunakan untuk melakukan beberapa tugas yang melelahkan yang saya sebutkan sebelumnya.
  • grunt digunakan untuk mem-build, melihat pratinjau, dan menguji project Anda, berkat bantuan dari tugas yang diseleksi oleh tim Yeoman dan grunt-contrib.
  • bower digunakan untuk pengelolaan dependensi, sehingga Anda tidak perlu lagi mendownload dan mengelola skrip secara manual.

Hanya dengan satu atau dua perintah, Yeoman dapat menulis kode boilerplate untuk aplikasi Anda (atau setiap bagian seperti Model), mengompilasi Sass, meminimalkan dan menggabungkan CSS, JS, HTML, dan gambar, serta mengaktifkan server web sederhana di direktori saat ini. Alat ini juga dapat menjalankan pengujian unit dan lainnya.

Anda dapat menginstal generator dari Node Packaged Modules (npm) dan kini tersedia lebih dari 220 generator, yang sebagian besar telah ditulis oleh komunitas open source. Generator populer mencakup generator-angular, generator-backbone, dan generator-ember.

Halaman beranda Yeoman

Setelah menginstal Node.js versi terbaru, buka terminal terdekat dan jalankan:

$ npm install -g yo

Selesai. Sekarang Anda memiliki Yo, Grunt, dan Bower serta dapat menjalankannya langsung dari command line. Berikut adalah output dari menjalankan yo:

Penginstalan Yeoman

Generator Polimer

Seperti yang telah saya sebutkan sebelumnya, Polymer adalah library polyfill dan sugar yang memungkinkan penggunaan Komponen Web di browser modern. Project ini memungkinkan developer membuat aplikasi menggunakan platform masa depan dan memberi tahu W3C tempat spesifikasi in-flight dapat ditingkatkan lebih lanjut.

Halaman beranda generator Polymer

generator-polymer adalah generator baru yang membantu Anda membuat scaffold aplikasi Polymer menggunakan Yeoman, sehingga Anda dapat dengan mudah membuat dan menyesuaikan elemen Polymer (kustom) melalui command line, dan mengimpornya menggunakan HTML Imports. Tindakan ini menghemat waktu Anda dengan menulis kode boilerplate untuk Anda.

Selanjutnya, instal generator Polymer dengan menjalankan:

$ npm install generator-polymer -g

Selesai. Sekarang aplikasi Anda memiliki kemampuan super Komponen Web.

Generator yang baru diinstal memiliki beberapa bit tertentu yang dapat Anda akses:

  • polymer:element digunakan untuk membuat scaffold setiap elemen Polymer baru. Misalnya: yo polymer:element carousel.
  • polymer:app digunakan untuk membuat scaffold index.html awal, Gruntfile.js yang berisi konfigurasi waktu build untuk project Anda serta tugas Grunt dan struktur folder yang direkomendasikan untuk project. Tindakan ini juga akan memberi Anda opsi untuk menggunakan Sass Bootstrap untuk gaya project Anda.

Mari kita build aplikasi Polymer

Kita akan membuat blog sederhana menggunakan beberapa elemen Polymer kustom dan generator baru.

Aplikasi Polymer

Untuk memulai, buka terminal, buat direktori baru, lalu cd ke dalamnya menggunakan mkdir my-new-project && cd $_. Sekarang Anda dapat memulai aplikasi Polymer dengan menjalankan:

$ yo polymer
Pembuatan aplikasi Polymer

Tindakan ini akan mendapatkan Polymer versi terbaru dari Bower dan membuat scaffold index.html, struktur direktori, dan tugas Grunt untuk alur kerja Anda. Sembari menunggu aplikasi selesai disiapkan, mengapa tidak minum kopi?

Baik, selanjutnya kita dapat menjalankan grunt server untuk melihat pratinjau tampilan aplikasi:

Server Grunt

Server mendukung LiveReload, yang berarti Anda dapat mengaktifkan editor teks, mengedit elemen kustom, dan browser akan memuat ulang saat disimpan. Hal ini memberi Anda tampilan real-time yang bagus tentang status aplikasi saat ini.

Selanjutnya, mari kita buat elemen Polymer baru untuk merepresentasikan postingan Blog.

$ yo polymer:element post
Membuat elemen postingan

Yeoman akan mengajukan beberapa pertanyaan kepada kita, seperti apakah kita ingin menyertakan konstruktor atau menggunakan Impor HTML untuk menyertakan elemen postingan di index.html. Untuk saat ini, mari kita jawab Tidak untuk dua opsi pertama dan biarkan opsi ketiga kosong.

$ yo polymer:element post

[?] Would you like to include constructor=''? No

[?] Import to your index.html using HTML imports? No

[?] Import other elements into this one? (e.g 'another_element.html' or leave blank)

    create app/elements/post.html

Tindakan ini akan membuat elemen Polymer baru di direktori /elements bernama post.html:

<polymer-element name="post-element"  attributes="">

    <template>

    <style>
        @host { :scope {display: block;} }
    </style>

    <span>I'm <b>post-element</b>. This is my Shadow DOM.</span>

    </template>

    <script>

    Polymer('post-element', {

        //applyAuthorStyles: true,

        //resetStyleInheritance: true,

        created: function() { },

        enteredView: function() { },

        leftView: function() { },

        attributeChanged: function(attrName, oldVal, newVal) { }

    });

    </script>

</polymer-element>

File tersebut berisi:

Bekerja dengan sumber data yang sebenarnya

Blog kita memerlukan tempat untuk menulis dan membaca postingan baru. Untuk menunjukkan cara menggunakan layanan data yang sebenarnya, kita akan menggunakan Google Apps Spreadsheets API. Hal ini memungkinkan kita membaca konten spreadsheet apa pun yang dibuat menggunakan Google Dokumen dengan mudah.

Mari kita siapkan:

  1. Di browser Anda (untuk langkah-langkah ini, sebaiknya gunakan Chrome), buka Spreadsheet Google Dokumen ini. File ini berisi contoh data postingan di kolom berikut:

    • ID
    • Judul
    • Penulis
    • Konten
    • Tanggal
    • Kata kunci
    • Email (penulis)
    • Slug (untuk URL slug postingan Anda)
  2. Buka menu File, lalu pilih Buat salinan untuk membuat salinan spreadsheet Anda sendiri. Anda bebas mengedit konten kapan saja, menambahkan atau menghapus postingan.

  3. Buka menu File sekali lagi dan pilih Publikasikan ke web.

  4. Klik mulai memublikasikan

  5. Di bagian Dapatkan link ke data yang dipublikasikan, dari kotak teks terakhir, salin bagian kunci dari URL yang diberikan. Tampilannya seperti ini: https://docs.google.com/spreadsheet/ccc?key=0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc#gid=0

  6. Tempel kunci ke URL berikut di bagian your-key-goes-here: https://spreadsheets.google.com/feeds/list/your-key-goes-here/od6/public/values?alt=json-in-script&callback=. Contoh penggunaan kunci di atas mungkin terlihat seperti https://spreadsheets.google.com/feeds/list/0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc/od6/public/values?alt=json-in-script.

  7. Anda dapat menempelkan URL ke browser dan membukanya untuk melihat versi JSON konten blog Anda. Catat URL-nya, lalu luangkan waktu sejenak untuk meninjau format data ini karena Anda perlu melakukan iterasi untuk menampilkannya di layar nanti.

Output JSON di browser Anda mungkin terlihat sedikit menakutkan, tetapi jangan khawatir. Kami hanya tertarik dengan data untuk postingan Anda.

Google Spreadsheets API menampilkan setiap kolom di spreadsheet blog Anda dengan awalan khusus post.gsx$. Misalnya: post.gsx$title.$t, post.gsx$author.$t, post.gsx$content.$t, dan sebagainya. Saat melakukan iterasi pada setiap “baris” dalam output JSON, kita akan mereferensikan kolom ini untuk mendapatkan kembali nilai yang relevan untuk setiap postingan.

Sekarang Anda dapat mengedit elemen postingan yang baru dibuat scaffold-nya untuk mengikat bagian markup ke data dalam spreadsheet. Untuk melakukannya, kita memperkenalkan atribut post, yang akan membaca judul postingan, penulis, konten, dan kolom lainnya yang kita buat sebelumnya. Atribut selected (yang akan kita isi nanti) digunakan untuk hanya menampilkan postingan jika pengguna membuka slug yang benar untuk postingan tersebut.

<polymer-element name="post-element" attributes="post selected">

    <template>

    <style>
        @host { :scope {display: block;} }
    </style>

        <div class="col-lg-4">

            <template if="[[post.gsx$slug.$t === selected]]">

            <h2>
                <a href="#[[post.gsx$slug.$t]]">
                [[post.gsx$title.$t  ]]
                </a>
            </h2>

            <p>By [[post.gsx$author.$t]]</p>

            <p>[[post.gsx$content.$t]]</p>

            <p>Published on: [[post.gsx$date.$t]]</p>

            <small>Keywords: [[post.gsx$keywords.$t]]</small>

            </template>

        </div>

    </template>

    <script>

    Polymer('post-element', {

        created: function() { },

        enteredView: function() { },

        leftView: function() { },

        attributeChanged: function(attrName, oldVal, newVal) { }

    });

    </script>

</polymer-element>

Selanjutnya, mari kita buat elemen blog yang berisi kumpulan postingan dan tata letak untuk blog Anda dengan menjalankan yo polymer:element blog.

$ yo polymer:element blog

[?] Would you like to include constructor=''? No

[?] Import to your index.html using HTML imports? Yes

[?] Import other elements into this one? (e.g 'another_element.html' or leave blank) post.html

    create app/elements/blog.html

Kali ini kita akan mengimpor blog ke index.html menggunakan impor HTML seperti yang kita inginkan untuk ditampilkan di halaman. Khusus untuk perintah ketiga, kita menentukan post.html sebagai elemen yang ingin disertakan.

Seperti sebelumnya, file elemen baru dibuat (blog.html) dan ditambahkan ke /elements, kali ini mengimpor post.html dan menyertakan <post-element> dalam tag template:

<link rel="import" href="post.html">

<polymer-element name="blog-element"  attributes="">

    <template>

    <style>
        @host { :scope {display: block;} }
    </style>

    <span>I'm <b>blog-element</b>. This is my Shadow DOM.</span>

        <post-element></post-element>

    </template>

    <script>

    Polymer('blog-element', {

        //applyAuthorStyles: true,

        //resetStyleInheritance: true,

        created: function() { },

        enteredView: function() { },

        leftView: function() { },

        attributeChanged: function(attrName, oldVal, newVal) { }

    });

    </script>

</polymer-element>

Karena kita meminta elemen blog untuk diimpor menggunakan impor HTML (cara untuk menyertakan dan menggunakan kembali dokumen HTML dalam dokumen HTML lain) ke indeks, kita juga dapat memverifikasi bahwa elemen tersebut telah ditambahkan dengan benar ke dokumen <head>:

<!doctype html>
    <head>

        <meta charset="utf-8">

        <meta http-equiv="X-UA-Compatible" content="IE=edge">

        <title></title>

        <meta name="description" content="">

        <meta name="viewport" content="width=device-width">

        <link rel="stylesheet" href="styles/main.css">

        <!-- build:js scripts/vendor/modernizr.js -->

        <script src="bower_components/modernizr/modernizr.js"></script>

        <!-- endbuild -->

        <!-- Place your HTML imports here -->

        <link rel="import" href="elements/blog.html">

    </head>

    <body>

        <div class="container">

            <div class="hero-unit" style="width:90%">

                <blog-element></blog-element>

            </div>

        </div>

        <script>
        document.addEventListener('WebComponentsReady', function() {
            // Perform some behaviour
        });
        </script>

        <!-- build:js scripts/vendor.js -->

        <script src="bower_components/polymer/polymer.min.js"></script>

        <!-- endbuild -->

</body>

</html>

Bagus sekali.

Menambahkan dependensi menggunakan Bower

Selanjutnya, mari kita edit elemen untuk menggunakan elemen utilitas Polymer JSONP guna membaca posts.json. Anda bisa mendapatkan adaptor dengan meng-clone repositori git atau menginstal polymer-elements melalui Bower dengan menjalankan bower install polymer-elements.

Dependensi Bower

Setelah memiliki utilitas, Anda harus menyertakannya sebagai impor di elemen blog.html dengan:

<link rel="import" href="../bower_components/polymer-jsonp/polymer-jsonp.html">

Selanjutnya, sertakan tag untuknya dan berikan url ke spreadsheet postingan blog kita dari sebelumnya, dengan menambahkan &callback= di bagian akhir:

<polymer-jsonp auto url="https://spreadsheets.google.com/feeds/list/your-key-value/od6/public/values?alt=json-in-script&callback=" response="[[posts]]"></polymer-jsonp>

Dengan ini, kita sekarang dapat menambahkan template untuk melakukan iterasi pada spreadsheet setelah dibaca. Yang pertama menghasilkan daftar isi, dengan judul tertaut untuk postingan yang mengarah ke slug-nya.

<!-- Table of contents -->

<ul>

    <template repeat="[[post in posts.feed.entry]]">

    <li><a href="#[[post.gsx$slug.$t]]">[[post.gsx$title.$t]]</a></li>

    </template>

</ul>

Yang kedua merender satu instance post-element untuk setiap entri yang ditemukan, yang meneruskan konten postingan ke instance tersebut. Perhatikan bahwa kita meneruskan atribut post yang mewakili konten postingan untuk satu baris spreadsheet dan atribut selected yang akan kita isi dengan rute.

<!-- Post content -->

<template repeat="[[post in posts.feed.entry]]">

    <post-element post="[[post]]" selected="[[route]]"></post-element>

</template>

Atribut repeat yang Anda lihat digunakan dalam template kami membuat dan mempertahankan instance dengan [[ bindings ]] untuk setiap elemen dalam koleksi array postingan kami, jika disediakan.

Aplikasi Polymer

Sekarang, agar [[route]] saat ini terisi, kita akan melakukan kecurangan dan menggunakan library bernama Flatiron director yang terikat dengan [[route]] setiap kali hash URL berubah.

Untungnya, ada elemen Polymer (bagian dari paket more-elements) yang dapat kita ambil. Setelah disalin ke direktori /elements, kita dapat mereferensikannya dengan <flatiron-director route="[[route]]" autoHash></flatiron-director>, menentukan route sebagai properti yang ingin kita ikat dan memberi tahu properti tersebut untuk otomatis membaca nilai perubahan hash apa pun (autoHash).

Dengan menggabungkan semuanya, kita mendapatkan:

    <link rel="import" href="post.html">

    <link rel="import" href="polymer-jsonp/polymer-jsonp.html">

    <link rel="import" href="flatiron-director/flatiron-director.html">

    <polymer-element name="blog-element"  attributes="">

      <template>

        <style>
          @host { :scope {display: block;} }
        </style>

        <div class="row">

          <h1><a href="/#">My Polymer Blog</a></h1>

          <flatiron-director route="[[route]]" autoHash></flatiron-director>

          <h2>Posts</h2>

          <!-- Table of contents -->

          <ul>

            <template repeat="[[post in posts.feed.entry]]">

              <li><a href="#[[post.gsx$slug.$t]]">[[post.gsx$title.$t]]</a></li>

            </template>

          </ul>

          <!-- Post content -->

          <template repeat="[[post in posts.feed.entry]]">

            <post-element post="[[post]]" selected="[[route]]"></post-element>

          </template>

        </div>

        <polymer-jsonp auto url="https://spreadsheets.google.com/feeds/list/0AhcraNy3sgspdHVQUGd2M2Q0MEZnRms3c3dDQWQ3V1E/od6/public/values?alt=json-in-script&callback=" response="[[posts]]"></polymer-jsonp>

      </template>

      <script>

        Polymer('blog-element', {

          created: function() {},

          enteredView: function() { },

          leftView: function() { },

          attributeChanged: function(attrName, oldVal, newVal) { }

        });

      </script>

    </polymer-element>
Aplikasi Polimer

Hore! Sekarang kita memiliki blog sederhana yang membaca data dari JSON dan menggunakan dua elemen Polymer yang dibuat dengan Yeoman.

Menggunakan elemen pihak ketiga

Ekosistem elemen di sekitar Komponen Web telah berkembang akhir-akhir ini dengan situs galeri komponen seperti customelements.io mulai muncul. Setelah melihat elemen yang dibuat oleh komunitas, saya menemukan salah satu elemen untuk mengambil profil gravatar dan kita juga dapat mengambil dan menambahkannya ke situs blog kita.

Halaman beranda elemen kustom

Salin sumber elemen gravatar ke direktori /elements, sertakan melalui impor HTML di post.html, lalu tambahkan ke template Anda, dengan meneruskan kolom email dari spreadsheet sebagai sumber nama pengguna. Boom!

<link rel="import" href="gravatar-element/src/gravatar.html">

<polymer-element name="post-element" attributes="post selected">

    <template>

    <style>
        @host { :scope {display: block;} }
    </style>

        <div class="col-lg-4">

            <template if="[[post.gsx$slug.$t === selected]]">

            <h2><a href="#[[post.gsx$slug.$t]]">[[post.gsx$title.$t]]</a></h2>

            <p>By [[post.gsx$author.$t]]</p>

            <gravatar-element username="[[post.gsx$email.$t]]" size="100"></gravatar-element>

            <p>[[post.gsx$content.$t]]</p>

            <p>[[post.gsx$date.$t]]</p>

            <small>Keywords: [[post.gsx$keywords.$t]]</small>

            </template>

        </div>

    </template>

    <script>

    Polymer('post-element', {

        created: function() { },

        enteredView: function() { },

        leftView: function() { },

        attributeChanged: function(attrName, oldVal, newVal) { }

    });

    </script>

</polymer-element>

Mari kita lihat manfaatnya:

Aplikasi Polymer dengan elemen kustom

Cantik!

Dalam waktu yang relatif singkat, kita telah membuat aplikasi sederhana yang terdiri dari beberapa komponen web tanpa harus khawatir menulis kode boilerplate, mendownload dependensi secara manual, atau menyiapkan server lokal atau membuat alur kerja.

Mengoptimalkan aplikasi Anda

Alur kerja Yeoman menyertakan project open source lain yang disebut Grunt - runner tugas yang dapat menjalankan sejumlah tugas khusus build (ditentukan dalam Gruntfile) untuk menghasilkan versi aplikasi yang dioptimalkan. Menjalankan grunt sendiri akan mengeksekusi tugas default yang telah disiapkan generator untuk linting, pengujian, dan build:

grunt.registerTask('default', [

    'jshint',

    'test',

    'build'

]);

Tugas jshint di atas akan memeriksa file .jshintrc untuk mempelajari preferensi Anda, lalu menjalankannya terhadap semua file JavaScript dalam project Anda. Untuk mendapatkan ringkasan lengkap opsi Anda dengan JSHint, lihat dokumen.

Tugas test terlihat seperti ini, dan dapat membuat serta menayangkan aplikasi Anda untuk framework pengujian yang kami rekomendasikan secara langsung, Mocha. Alat ini juga akan menjalankan pengujian untuk Anda:

grunt.registerTask('test', [

    'clean:server',

    'createDefaultTemplate',

    'jst',

    'compass',

    'connect:test',

    'mocha'

]);

Karena aplikasi kita dalam hal ini cukup sederhana, kita akan menyerahkan penulisan pengujian kepada Anda sebagai latihan terpisah. Ada beberapa hal lain yang perlu ditangani oleh proses build. Jadi, mari kita lihat apa yang akan dilakukan tugas grunt build yang ditentukan dalam Gruntfile.js:

grunt.registerTask('build', [

    'clean:dist',    // Clears out your .tmp/ and dist/ folders

    'compass:dist',  // Compiles your Sassiness

    'useminPrepare', // Looks for <!-- special blocks --> in your HTML

    'imagemin',      // Optimizes your images!

    'htmlmin',       // Minifies your HTML files

    'concat',        // Task used to concatenate your JS and CSS

    'cssmin',        // Minifies your CSS files

    'uglify',        // Task used to minify your JS

    'copy',          // Copies files from .tmp/ and app/ into dist/

    'usemin'         // Updates the references in your HTML with the new files

]);

Jalankan grunt build dan versi aplikasi yang siap produksi akan di-build, siap untuk dikirim. Mari kita coba.

Build Grunt

Berhasil!

Jika Anda mengalami masalah, versi polymer-blog yang telah dibuat sebelumnya tersedia untuk Anda lihat di https://github.com/addyosmani/polymer-blog.

Apa lagi yang kami sediakan?

Komponen Web masih dalam proses evolusi, begitu pula dengan alat-alat di sekitarnya.

Saat ini kami sedang mempelajari cara menggabungkan impor HTML untuk meningkatkan performa pemuatan melalui project seperti Vulcanize (alat dari project Polymer) dan cara ekosistem untuk komponen dapat berfungsi dengan pengelola paket seperti Bower.

Kami akan memberi tahu Anda jika kami memiliki jawaban yang lebih baik untuk pertanyaan ini, tetapi ada banyak hal menarik yang akan datang.

Menginstal Polymer mandiri dengan Bower

Jika Anda lebih memilih memulai Polymer dengan lebih ringan, Anda dapat menginstalnya secara mandiri langsung dari Bower dengan menjalankan:

bower install polymer

yang akan menambahkannya ke direktori bower_components Anda. Kemudian, Anda dapat mereferensikannya di indeks aplikasi secara manual dan menikmati masa depan.

Bagaimana menurut Anda?

Sekarang Anda tahu cara membuat scaffold aplikasi Polymer menggunakan Web Components dengan Yeoman. Jika Anda memiliki masukan tentang generator, beri tahu kami di kolom komentar atau laporkan bug atau posting ke pelacak masalah Yeoman. Kami ingin mengetahui apakah ada hal lain yang ingin Anda lihat dari generator ini karena kami dapat meningkatkan kualitasnya hanya melalui penggunaan dan masukan Anda :)