Membuat aplikasi web dengan Yeoman dan Polymer

Kembangkan aplikasi web Anda dengan alat modern

Addy Osmani
Addy Osmani

Pengantar

Allo’ Allo’. Siapa pun yang menulis aplikasi web tahu betapa pentingnya menjaga diri tetap produktif. Akan menjadi tantangan jika Anda harus mencemaskan tugas-tugas yang membosankan seperti menemukan boilerplate yang tepat, menyiapkan alur kerja pengembangan dan pengujian, serta meminifikasi dan mengompresi semua sumber Anda.

Untungnya, alat front-end modern dapat membantu mengotomatiskan sebagian besar hal ini, sehingga Anda dapat fokus pada penulisan aplikasi kick-ass. Artikel ini akan menunjukkan cara menggunakan Yeoman, alur kerja alat untuk aplikasi web untuk menyederhanakan pembuatan aplikasi menggunakan Polymer, library polyfill dan sugar untuk mengembangkan aplikasi menggunakan Komponen Web.

Yeoman

Perkenalkan Yo, Grunt, dan Bower

Yeoman adalah seorang pria yang memiliki 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 membosankan yang saya sebutkan sebelumnya.
  • grunt digunakan untuk membuat, melihat pratinjau, dan menguji project Anda, berkat bantuan dari tugas-tugas yang telah 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 Anda, meminimalkan dan menggabungkan CSS, JS, HTML, dan gambar, serta mengaktifkan server web sederhana di direktori Anda saat ini. Aplikasi ini juga dapat menjalankan pengujian unit dan lainnya.

Anda dapat menginstal generator dari Modul Paket Node (npm) dan kini tersedia lebih dari 220 generator, yang banyak di antaranya telah ditulis oleh komunitas open source. Generator populer meliputi generator-angular, generator-backbone, dan generator-ember.

Halaman beranda Yeoman

Dengan versi terbaru Node.js yang sudah terinstal, buka terminal terdekat dan jalankan:

$ npm install -g yo

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

Instalasi Yeoman

Generator Polimer

Seperti yang saya sebutkan sebelumnya, Polymer adalah library polyfill dan sugar yang memungkinkan penggunaan Komponen Web di browser modern. Proyek ini memungkinkan developer membangun aplikasi menggunakan platform masa depan dan memberi tahu W3C tentang tempat-tempat di mana spesifikasi dalam penerbangan dapat ditingkatkan lebih lanjut.

Hompage generator polimer

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

Selanjutnya, instal generator Polymer dengan menjalankan:

$ npm install generator-polymer -g

Selesai. Sekarang aplikasi Anda memiliki kemampuan super Komponen Web!

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

  • polymer:element digunakan untuk scaffolding elemen Polimer individual baru. Misalnya: yo polymer:element carousel.
  • polymer:app digunakan untuk merampingkan index.html awal Anda, Gruntfile.js yang berisi konfigurasi waktu build untuk project Anda, serta tugas Grunt dan struktur folder yang direkomendasikan untuk project. Ini juga akan memberi Anda opsi untuk menggunakan Sass Bootstrap untuk gaya proyek Anda.

Mari membangun aplikasi Polymer

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

Aplikasi Polymer

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

$ yo polymer
Pembuatan aplikasi Polymer

Fitur ini mendapatkan versi terbaru Polymer dari Bower dan menyusun index.html, struktur direktori, dan tugas Grunt untuk alur kerja Anda. Mengapa tidak minum kopi sambil menunggu aplikasi selesai disiapkan?

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

Server grunt

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

Selanjutnya, mari buat elemen Polymer baru untuk mewakili postingan Blog.

$ yo polymer:element post
Buat elemen postingan

Yeoman mengajukan beberapa pertanyaan seperti apakah kita ingin menyertakan konstruktor atau menggunakan Impor HTML untuk menyertakan elemen postingan di index.html. Misalkan Tidak untuk dua opsi pertama untuk saat ini dan kosongkan opsi ketiga.

$ 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 yang 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 aktual

Blog kita akan membutuhkan tempat untuk menulis dan membaca postingan baru. Untuk menunjukkan cara menggunakan layanan data yang sebenarnya, kita akan menggunakan API Spreadsheet Google Apps. Hal ini memudahkan kami untuk membaca isi spreadsheet apa pun yang dibuat menggunakan Google Dokumen.

Mari kita siapkan:

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

    • ID
    • Judul
    • Penulis
    • Konten
    • Tanggal
    • Kata kunci
    • E-mail (penulis)
    • Slug (untuk URL slug postingan Anda)
  2. Buka menu File dan pilih Buat salinan untuk membuat salinan spreadsheet Anda sendiri. Anda bebas mengedit konten di waktu senggang, dengan menambah atau menghapus postingan.

  3. Buka menu File sekali lagi, lalu pilih Publish to the web.

  4. Klik start publish.

  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. Tempelkan kunci ke URL berikut yang bertuliskan your-key-goes-here: https://spreadsheets.google.com/feeds/list/your-key-goes-here/od6/public/values?alt=json-in-script&callback=. Contoh yang menggunakan 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 tersebut, lalu luangkan waktu untuk meninjau format data ini karena Anda perlu melakukan iterasi untuk menampilkannya di layar nanti.

Output JSON di browser Anda mungkin terlihat sedikit membingungkan, tetapi jangan khawatir. Kami benar-benar hanya tertarik pada data untuk kiriman Anda.

Google Spreadsheet API menghasilkan 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 seterusnya. Saat melakukan iterasi pada setiap "baris" dalam output JSON, kita akan mereferensikan kolom ini untuk mendapatkan kembali nilai yang relevan untuk setiap postingan.

Anda kini dapat mengedit elemen postingan dengan susunan yang baru disusun untuk bind bagian markup ke data dalam spreadsheet Anda. Untuk melakukannya, kami memperkenalkan atribut post, yang akan dibaca untuk judul postingan, penulis, konten, dan kolom lain yang telah kita buat sebelumnya. Atribut selected (yang akan kita isi nanti) digunakan hanya untuk menampilkan postingan jika pengguna membuka slug yang benar untuknya.

<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>

Berikutnya, mari 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 mengimpor blog ke index.html menggunakan impor HTML seperti yang ingin kita tampilkan di halaman. Khusus untuk perintah ketiga, kita menentukan post.html sebagai elemen yang ingin disertakan.

Seperti sebelumnya, file elemen baru telah dibuat (blog.html) dan ditambahkan ke /element, 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>

Saat 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 blog 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 untuk dibaca di posts.json. Anda bisa mendapatkan adaptor dengan meng-clone repositori atau menginstal polymer-elements melalui Bower dengan menjalankan bower install polymer-elements.

Dependensi bower

Setelah memiliki utilitas tersebut, Anda perlu menyertakannya sebagai impor dalam elemen blog.html dengan:

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

Selanjutnya, sertakan tag untuk tag tersebut dan berikan url ke spreadsheet postingan blog 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 menggunakan ini, kita sekarang dapat menambahkan {i>template<i} untuk melakukan iterasi pada {i>spreadsheet<i} kita setelah dibaca. Yang pertama menghasilkan daftar isi, dengan judul yang ditautkan untuk postingan yang mengarah ke slug.

<!-- 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, meneruskan konten postingan ke entri 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 membuat dan mempertahankan instance dengan [[ bindings ]] untuk setiap elemen dalam koleksi array postingan, jika tersedia.

Aplikasi Polymer

Sekarang agar kita dapat mengisi [[route]] saat ini, kita akan curang dan menggunakan library bernama direktur Flatiron yang mengikat ke [[route]] setiap kali hash URL berubah.

Untungnya ada Elemen Polimer (bagian dari paket lebih banyak elemen) yang bisa kita ambil. Setelah disalin ke direktori /element, kita dapat mereferensikannya dengan <flatiron-director route="[[route]]" autoHash></flatiron-director>, yang menentukan route sebagai properti yang ingin kita ikat dan memerintahkannya untuk otomatis membaca nilai setiap perubahan hash (autoHash).

Menggabungkan semuanya, sekarang 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 kami memiliki blog sederhana yang membaca data dari JSON dan menggunakan dua elemen Polymer yang disusun dengan Yeoman.

Menangani elemen pihak ketiga

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

Halaman beranda elemen kustom

Salin sumber elemen gravatar ke direktori /elements Anda, sertakan melalui impor HTML di post.html, lalu tambahkan ke template Anda, dengan meneruskan kolom email dari spreadsheet kami 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 manfaat dari hal ini:

Aplikasi Polymer dengan elemen kustom

Cantik!

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

Mengoptimalkan aplikasi Anda

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

grunt.registerTask('default', [

    'jshint',

    'test',

    'build'

]);

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

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

grunt.registerTask('test', [

    'clean:server',

    'createDefaultTemplate',

    'jst',

    'compass',

    'connect:test',

    'mocha'

]);

Karena aplikasi kita dalam kasus ini cukup sederhana, kita akan menyerahkan pengujian penulisan kepada Anda sebagai latihan terpisah. Ada beberapa hal lain yang diperlukan agar kita dapat menangani proses build. Jadi, mari kita lihat fungsi tugas grunt build yang ditentukan di 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 mendengus

Berhasil!

Jika Anda menemui kesulitan, versi polimer-blog yang telah dibuat sebelumnya tersedia untuk Anda lihat https://github.com/addyosmani/polymer-blog.

Apa lagi yang kami miliki?

Komponen Web masih dalam tahap evolusi dan demikian pula alat di sekitarnya.

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

Kami akan memberi tahu Anda saat kami memiliki jawaban yang lebih baik untuk pertanyaan ini, tetapi masih ada banyak kesempatan menarik ke depannya.

Menginstal Polymer secara mandiri dengan Bower

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

bower install polymer

yang akan menambahkannya ke direktori {i>bower_components<i} Anda. Anda kemudian dapat mereferensikannya dalam indeks aplikasi secara manual dan memanfaatkannya di masa mendatang.

Bagaimana menurut Anda?

Sekarang Anda tahu cara membuat scaffolding aplikasi Polymer menggunakan Komponen Web dengan Yeoman. Jika Anda memiliki masukan tentang generator, beri tahu kami di komentar atau laporkan bug atau posting ke issue tracker Yeoman. Kami ingin tahu apakah ada hal lain yang Anda ingin agar generator semakin baik karena hanya melalui penggunaan dan masukan Anda yang dapat kami tingkatkan :)