Web uygulamalarınızı modern araçlarla iskeletlendirin
Giriş
Merhaba. Web uygulaması yazan herkes, üretken kalmayı ne kadar önemli bildiğini bilir. Doğru şablonu bulma, geliştirme ve test iş akışı oluşturma, tüm kaynaklarınızı küçültme ve sıkıştırma gibi sıkıcı görevlerle uğraşmak zordur.
Neyse ki modern ön uç araçları bu işlemlerin çoğunu otomatikleştirmenize yardımcı olabilir. Böylece, harika bir uygulama yazmaya odaklanabilirsiniz. Bu makalede, Web Bileşenleri'ni kullanarak uygulama geliştirmek için polyfill ve sugar kitaplığı olan Polymer'i kullanarak uygulama oluşturmayı kolaylaştırmak amacıyla web uygulamalarına yönelik bir araç iş akışı olan Yeoman'ı nasıl kullanacağınız gösterilmektedir.
Yo, Grunt ve Bower ile tanışın
Yeoman, üretkenliğinizi artıracak üç araçla şapkalı bir adamdır:
- yo, daha önce bahsettiğim sıkıcı görevlerden bazılarını gerçekleştirmek için kullanılabilecek, çerçeveye özel iskeleler ekosistemi sunan bir iskele aracıdır.
- grunt, Yeoman ekibi ve grunt-contrib tarafından seçilen görevlerden yardım alarak projenizi oluşturmak, önizlemek ve test etmek için kullanılır.
- bower, bağımlılık yönetimi için kullanılır. Böylece artık komut dosyalarınızı manuel olarak indirip yönetmeniz gerekmez.
Yeoman, yalnızca bir veya iki komutla uygulamanız için şablon kod (veya Modeller gibi ayrı parçalar) yazabilir, Sass'ınızı derleyebilir, CSS, JS, HTML ve resimlerinizi en aza indirip birleştirebilir ve mevcut dizininizde basit bir web sunucusu başlatabilir. Ayrıca birim testlerinizi ve daha fazlasını çalıştırabilir.
Oluşturucuları Node Paketlenmiş Modülleri'nden (npm) yükleyebilirsiniz. Şu anda çoğu açık kaynak topluluğu tarafından yazılmış 220'den fazla oluşturucu mevcuttur. Popüler jeneratörler arasında generator-angular, generator-backbone ve generator-ember bulunur.
Node.js'in en son sürümünü yükledikten sonra en yakın terminalinize gidip aşağıdaki komutu çalıştırın:
$ npm install -g yo
İşte bu kadar. Artık Yo, Grunt ve Bower'ı doğrudan komut satırından çalıştırabilirsiniz. yo
çalıştırmanın sonucu:
Polimer Oluşturucu
Daha önce de belirttiğim gibi Polymer, modern tarayıcılarda Web Bileşenlerinin kullanılmasını sağlayan bir çoklu dolgu ve şeker kitaplığıdır. Proje, geliştiricilerin geleceğin platformunu kullanarak uygulama oluşturmasına olanak tanır ve uçuş sırasındaki özelliklerin daha da iyileştirilebileceği yerleri W3C'ye bildirir.
generator-polymer, Yeoman'ı kullanarak Polymer uygulamalarını oluşturmanıza yardımcı olan yeni bir oluşturucudur. Bu oluşturucu, komut satırı üzerinden Polymer (özel) öğeleri kolayca oluşturup özelleştirmenize ve HTML Imports'ı kullanarak içe aktarmanıza olanak tanır. Bu sayede, standart kod sizin için yazılır ve zamandan tasarruf edersiniz.
Ardından, aşağıdaki komutu çalıştırarak Polymer'in jeneratörünü yükleyin:
$ npm install generator-polymer -g
Bu kadar basit. Artık uygulamanız Web Bileşeni süper güçlerine sahip.
Yeni yüklenen jeneratörümüzde erişebileceğiniz birkaç özellik vardır:
polymer:element
, yeni tekil Polymer öğelerini iskeletlemek için kullanılır. Örneğin:yo polymer:element carousel
polymer:app
, ilk index.html dosyanızı, projeniz için derleme zamanı yapılandırmasını, Grunt görevlerini ve proje için önerilen bir klasör yapısını içeren bir Gruntfile.js oluşturmak için kullanılır. Ayrıca projenizin stilleri için Sass Bootstrap kullanma seçeneği de sunulur.
Polymer uygulaması oluşturalım
Bazı özel Polymer öğelerini ve yeni jeneratörümüzü kullanarak basit bir blog oluşturacağız.
Başlamak için terminale gidin, yeni bir dizin oluşturun ve mkdir my-new-project && cd $_
kullanarak bu dizine gidin. Artık aşağıdakileri çalıştırarak Polymer uygulamanızı başlatabilirsiniz:
$ yo polymer
Bu komut, Bower'dan Polymer'in en son sürümünü alır ve iş akışınız için bir index.html, dizin yapısı ve Grunt görevleri oluşturur. Uygulamanın hazırlanmasını beklerken bir kahve içmek ister misiniz?
Peki, uygulamanın nasıl göründüğünü önizlemek için grunt server
komutunu çalıştırabiliriz:
Sunucu, LiveReload'u destekler. Yani bir metin düzenleyiciyi açıp özel bir öğeyi düzenlediğinizde tarayıcı, kaydetme işleminde yeniden yüklenir. Bu sayede uygulamanızın mevcut durumunu gerçek zamanlı olarak görebilirsiniz.
Ardından, bir blog yayınını temsil edecek yeni bir Polymer öğesi oluşturalım.
$ yo polymer:element post
Yeoman, post öğesini index.html
içine dahil etmek için bir kurucu eklemek isteyip istemediğimiz gibi birkaç soru sorar. Şimdilik ilk iki seçeneğe Hayır deyip üçüncü seçeneği boş bırakalım.
$ 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
Bu işlem, /elements
dizininde post.html adlı yeni bir Polymer öğesi oluşturur:
<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>
Şunları içerir:
- Sayfanızda özel bir DOM öğesi türü (ör.
<post-element>
) kullanmanıza olanak tanıyan özel öğeniz için şablon kod - "Yerel" istemci tarafı şablon oluşturma için bir şablon etiketi ve öğenizin stillerini kapsayacak örnek kapsamlı stiller
- Öğe kaydı şablonu ve yaşam döngüsü etkinlikleri.
Gerçek bir veri kaynağıyla çalışma
Blogumuzda yeni yayınları yazıp okuyabileceğimiz bir yer olmalıdır. Gerçek bir veri hizmetiyle çalışmayı göstermek için Google Apps E-Tablolar API'yi kullanacağız. Bu sayede, Google Dokümanlar kullanılarak oluşturulan tüm e-tabloların içeriğini kolayca okuyabiliriz.
Ayarlama işlemini başlatalım:
Tarayıcınızda (bu adımlar için Chrome önerilir) bu Google Dokümanlar e-tablosunu açın. Aşağıdaki alanlar altında örnek gönderi verileri içerir:
- Kimlik
- Başlık
- Yazar
- İçerik
- Tarih
- Anahtar kelimeler
- E-posta (yazarın)
- Slug (yayınınızın slug URL'si için)
E-tablonun kendi kopyanızı oluşturmak için Dosya menüsüne gidip Kopya oluştur'u seçin. İçeriği dilediğiniz zaman düzenleyebilir, yayın ekleyebilir veya kaldırabilirsiniz.
Tekrar Dosya menüsüne gidip Web'de yayınla'yı seçin.
Yayınlamayı başlat'ı tıklayın.
Yayınlanan verilerin bağlantısını al bölümünde, son metin kutusunda sağlanan URL'nin anahtar kısmını kopyalayın. Şu şekilde görünür: https://docs.google.com/spreadsheet/ccc?key=0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc#gid=0
Anahtarı, anahtarınız-buraya-yazılır ifadesinin yer aldığı şu URL'ye yapıştırın: https://spreadsheets.google.com/feeds/list/your-key-goes-here/od6/public/values?alt=json-in-script&callback=. Yukarıdaki anahtarı kullanan bir örnek https://spreadsheets.google.com/feeds/list/0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc/od6/public/values?alt=json-in-script şeklinde olabilir.
URL'yi tarayıcınıza yapıştırıp blog içeriğinizin JSON sürümünü görüntülemek için bu URL'ye gidebilirsiniz. URL'yi not edin ve daha sonra ekranda görüntülemek için bu verileri iterasyonla incelemeniz gerekeceğinden, bu verilerin biçimini incelemek için biraz zaman ayırın.
Tarayıcınızdaki JSON çıkışı biraz korkutucu görünebilir ancak endişelenmeyin. Yalnızca yayınlarınızla ilgili verileri isteriz.
Google E-Tablolar API, blog e-tablonuzdaki her alanı özel bir ön ek post.gsx$
ile döndürür. Örneğin: post.gsx$title.$t
, post.gsx$author.$t
, post.gsx$content.$t
vb. JSON çıkışımızdaki her "satırı" iterelediğimizde, her yayınla ilgili alakalı değerleri döndürmek için bu alanlara referans veririz.
Artık yeni iskelet oluşturulmuş gönderi öğenizi düzenleyebilir ve işaretleme bölümlerini e-tablonuzdaki verilere bağlayabilirsiniz. Bunu yapmak için gönderi başlığı, yazarı, içeriği ve daha önce oluşturduğumuz diğer alanları okuyacak bir post
özelliği ekleriz. selected
özelliği (daha sonra dolduracağız), bir gönderiyi yalnızca kullanıcı ilgili gönderinin doğru slug'una gittiğinde göstermek için kullanılır.
<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>
Ardından, yo polymer:element blog
komutunu çalıştırarak hem bir yayın koleksiyonu hem de blogunuzun düzenini içeren bir blog öğesi oluşturalım.
$ 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
Bu kez, blogu sayfada görünmesini istediğimiz şekilde HTML içe aktarma özelliğini kullanarak index.html dosyasına aktarıyoruz. Özellikle üçüncü istemde, dahil etmek istediğimiz öğe olarak post.html
öğesini belirtiriz.
Önceki gibi yeni bir öğe dosyası (blog.html) oluşturulur ve /elements dizine eklenir. Bu kez post.html içe aktarılır ve şablon etiketine <post-element>
eklenir:
<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>
Blog öğesinin dizine HTML içe aktarma (HTML dokümanlarını diğer HTML dokümanlarına ekleyip yeniden kullanmanın bir yolu) kullanılarak içe aktarılmasını istediğimizden, <head>
belgesine doğru şekilde eklendiğini de doğrulayabiliriz:
<!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>
Harika.
Bower'u kullanarak bağımlılık ekleme
Ardından, posts.json dosyasını okumak için Polymer JSONP yardımcı programı öğesini kullanacak şekilde öğemizi düzenleyelim. Adaptörü, deposu git ile klonlayarak veya bower install polymer-elements
'yi çalıştırarak Bower üzerinden polymer-elements
yükleyerek edinebilirsiniz.
Yardımcı programı indirdikten sonra blog.html öğenize aşağıdakilerle birlikte içe aktarma olarak eklemeniz gerekir:
<link rel="import" href="../bower_components/polymer-jsonp/polymer-jsonp.html">
Ardından, etiketini ekleyin ve url
'yi daha önceki blog yayınları e-tablomuza ekleyin. Sonuna &callback=
ekleyin:
<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>
Bu işlem tamamlandıktan sonra, e-tablomuz okunduktan sonra e-tablomuzda iterasyon yapacak şablonlar ekleyebiliriz. İlki, bir yayın için bağlantılı bir başlıkla birlikte yayının slug'ını gösteren bir içindekiler listesi oluşturur.
<!-- 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>
İkincisi, bulunan her giriş için bir post-element
örneği oluşturur ve gönderi içeriğini buna uygun şekilde iletir. Tek bir e-tablo satırının yayın içeriğini temsil eden bir post
özelliği ve bir rotayla dolduracağımız bir selected
özelliği iletiyoruz.
<!-- Post content -->
<template repeat="[[post in posts.feed.entry]]">
<post-element post="[[post]]" selected="[[route]]"></post-element>
</template>
Şablonumuzda kullanıldığını gördüğünüz repeat
özelliği, sağlandığında yayınlarımızın dizi koleksiyonundaki her öğe için [[ bindings ]] içeren bir örnek oluşturur ve korur.
Şimdi, mevcut [[route]] değerinin doldurulmasını sağlamak için hile yapıp URL karması değiştiğinde [[route]] değerine bağlanan Flatiron director adlı bir kitaplık kullanacağız.
Neyse ki bunun için kullanabileceğimiz bir Polymer öğesi (more-elements paketinin bir parçası) var. /elements dizinine kopyalandıktan sonra, <flatiron-director route="[[route]]" autoHash></flatiron-director>
ile referans verebiliriz. Bu referans için route
'u bağlamak istediğimiz mülk olarak belirtir ve tüm karma oluşturma değişikliklerinin değerini otomatik olarak okumasını (autoHash) söyleriz.
Tüm bunları bir araya getirdiğimizde şunu elde ederiz:
<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>
Harika! Artık JSON'dan veri okuyan ve Yeoman ile iskeleti oluşturulmuş iki Polymer öğesi kullanan basit bir blogumuz var.
Üçüncü taraf öğeleriyle çalışma
Web bileşenleri etrafındaki öğe ekosistemi, customelements.io gibi bileşen galerisi sitelerinin ortaya çıkmaya başlamasıyla birlikte son zamanlarda büyüyor. Topluluk tarafından oluşturulan öğelere göz atarken gravatar profillerini getirmeye yarayan bir öğe buldum. Bu öğeyi alıp blog sitemize de ekleyebiliriz.
Gravatar öğe kaynaklarını /elements
dizininize kopyalayın, post.html dosyasına HTML içe aktarma yoluyla ekleyin ve ardından kullanıcı adının kaynağı olarak e-posta alanını e-tablomuzdan ileterek şablonunuza
<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>
Bu sayede neler elde edebiliriz?
Çok güzel.
Yazım kalıbı kod yazmak, bağımlılıkları manuel olarak indirmek, yerel sunucu oluşturmak veya derleme iş akışı oluşturmak zorunda kalmadan nispeten kısa bir sürede çeşitli web bileşenlerinden oluşan basit bir uygulama oluşturduk.
Başvurunuzu optimize etme
Yeoman iş akışı, uygulamanızın optimize edilmiş bir sürümünü oluşturmak için bir dizi derlemeye özgü görevi (Grunt dosyasında tanımlanır) çalıştırabilen bir görev yürütücü olan Grunt adlı başka bir açık kaynak projeyi içerir. grunt
tek başına çalıştırıldığında, jeneratörün linting, test ve derleme için oluşturduğu bir default
görevi yürütülür:
grunt.registerTask('default', [
'jshint',
'test',
'build'
]);
Yukarıdaki jshint
görevi, tercihlerinizi öğrenmek için .jshintrc
dosyanızı kontrol eder ve ardından projenizdeki tüm JavaScript dosyalarında çalıştırır. JSHint ile ilgili seçeneklerinizin tam listesini görmek için dokümanları inceleyin.
test
görevi buna biraz benzer. Uygulamanızı, kutudan çıkar çıkmaz önerdiğimiz test çerçevesi olan Mocha için oluşturup sunabilir. Ayrıca testlerinizi sizin için de yürütür:
grunt.registerTask('test', [
'clean:server',
'createDefaultTemplate',
'jst',
'compass',
'connect:test',
'mocha'
]);
Bu örnekteki uygulamamız oldukça basit olduğu için test yazma işlemini ayrı bir alıştırma olarak size bırakacağız. Derleme sürecimizin yapması gereken başka birkaç şey var. Bu nedenle, Gruntfile.js
dosyamızda tanımlanan grunt build
görevinin ne yapacağını inceleyelim:
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
]);
grunt build
komutunu çalıştırın. Uygulamanızın üretime hazır sürümü derlenir ve kullanıma sunulmaya hazır olur. Bunu deneyelim.
Başarıyla gerçekleştirildi.
Sorun yaşarsanız https://github.com/addyosmani/polymer-blog adresinden polymer-blog'un önceden oluşturulmuş bir sürümüne göz atabilirsiniz.
Başka neler var?
Web bileşenleri hâlâ gelişme aşamasında olduğundan, bu bileşenlerle ilgili araçlar da gelişme aşamasındadır.
Şu anda, Vulcanize (Polymer projesinin aracısı) gibi projeler aracılığıyla daha iyi yükleme performansı için HTML içe aktarmalarını nasıl birleştirebileceğimizi ve bileşen ekosisteminin Bower gibi bir paket yöneticisiyle nasıl çalışabileceğini araştırıyoruz.
Bu sorulara daha iyi yanıtlar bulduğumuzda sizi bilgilendireceğiz. Ancak bizi bekleyen çok heyecan verici gelişmeler var.
Polymer'i Bower ile bağımsız olarak yükleme
Polymer'i daha hafif bir şekilde kullanmaya başlamak istiyorsanız aşağıdaki komutu çalıştırarak doğrudan Bower'dan bağımsız olarak yükleyebilirsiniz:
bower install polymer
Bu işlem, paketi bower_components dizininize ekler. Ardından, uygulama dizininde manuel olarak referans verebilir ve gelecekte başarılı olabilirsiniz.
Ne düşünüyorsunuz?
Artık Yeoman ile Web Bileşenleri'ni kullanarak bir Polymer uygulamasının iskeletini nasıl oluşturacağınızı biliyorsunuz. Oluşturucuyla ilgili geri bildiriminiz varsa lütfen yorumlar bölümünden bize bildirin veya Yeoman sorun izleyicisine hata kaydı gönderin ya da gönderi paylaşın. Geliştiriciyi daha iyi hale getirmek için geri bildirimlerinizi bekliyoruz. Geliştirmelerimizi yalnızca kullanımınız ve geri bildirimleriniz sayesinde yapabiliyoruz.