Web uygulamalarınızı modern araçlarla güçlendirin
Giriş
Allo’ Allo". Bir web uygulaması yazan herkes, üretken olmanın ne kadar önemli olduğunu bilir. Doğru ortak metni bulma, geliştirme ve test iş akışı oluşturma ve tüm kaynaklarınızı küçültüp sıkıştırma gibi sıkıcı görevler için endişelenmeniz gerektiğinde bu oldukça zordur.
Neyse ki modern kullanıcı arabirimi araçları bu sürecin büyük ölçüde otomatikleştirilmesine yardımcı olabilir ve böylece siz de etkili bir uygulama yazmaya odaklanabilirsiniz. Bu makalede, Web Bileşenleri kullanan uygulamalar geliştirmek için bir polifiller ve şeker kitaplığı olan Polymer'i kullanarak uygulama oluşturmayı kolaylaştırmak amacıyla web uygulamalarına yönelik araçların iş akışı olan Yeoman'ı nasıl kullanacağınız gösterilmektedir.
Yo, Grunt ve Bower ile tanışın
Yeoman, üretkenliğinizi artırmak için üç araca sahip, şapka takmış bir adam:
- yo, daha önce bahsettiğim sıkıcı görevlerden bazılarını gerçekleştirmek için kullanılabilen, jeneratörler olarak adlandırılan, çerçeveye özgü iskelelerden oluşan bir ekosistem sunan bir yapı oluşturma aracıdır.
- grunt; Yeoman ekibinin seçtiği görevler ve grunt-contrib tarafından seçilen görevlerin yardımı sayesinde 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 komut dosyalarınızı artık manuel olarak indirmeniz ve yönetmeniz gerekmez.
Yeoman yalnızca bir ya da iki komutla uygulamanız için standart kod yazabilir (veya Modeller gibi ayrı ayrı parçalar oluşturabilir), Sass dosyanızı derleyebilir, CSS, JS, HTML ve resimlerinizi küçültüp birbirine bağlayabilir ve mevcut dizininizde basit bir web sunucusu çalıştırabilir. Ayrıca, birim testlerinizi ve daha fazlasını çalıştırabilir.
Düğüm Paketli Modülleri'nden (npm) oluşturucu yükleyebilirsiniz. Şu anda, birçoğu açık kaynak topluluğu tarafından yazılmış 220'den fazla oluşturucu mevcuttur. Popüler jeneratörler arasında generator-angle, jeneratör-omurga ve jeneratör-ember bulunur.
Node.js'nin yeni bir sürümü yüklüyse en yakın terminale gidip şunu çalıştırın:
$ npm install -g yo
İşte bu kadar. Artık Yo, Grunt ve Bower'ınız var ve bunları doğrudan komut satırından çalıştırabilirsiniz. yo
komutunu çalıştırmanızın sonucu aşağıda verilmiştir:
Polimer Jeneratörü
Daha önce belirttiğim gibi, Polymer, Web Bileşenlerinin modern tarayıcılarda kullanılabilmesine olanak tanıyan bir çoklu dolgu ve şeker kitaplığıdır. Proje, geliştiricilerin yarının platformunu kullanarak uygulamalar oluşturmasına ve hazırlık aşamasındaki özelliklerin daha da iyileştirilebileceği yerler hakkında W3C'yi bilgilendirmesine olanak tanır.
generator-polymer, Yeoman'i kullanarak Polymer uygulamaları oluşturmanıza yardımcı olan yeni bir oluşturma aracıdır. Polimer (özel) öğelerini komut satırını kullanarak kolayca oluşturmanıza, özelleştirmenize ve HTML İçe Aktarmaları ile içe aktarmanıza olanak tanır. Bu, sizin için standart kodu yazarak zamandan tasarruf etmenizi sağlar.
Ardından, aşağıdaki komutu çalıştırarak Polymer’in jeneratörünü yükleyin:
$ npm install generator-polymer -g
Bu kadar basit. Uygulamanız artık Web Bileşeni süper güçlerine sahip!
Yeni kurulan oluşturucumuzda erişebileceğiniz birkaç bölüm vardır:
polymer:element
, yeni bağımsız Polimer öğelerini şekillendirmek 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ı içeren bir Gruntfile.js), ayrıca Grunt görevlerini ve proje için önerilen bir klasör yapısını oluşturmak üzere kullanılır. Ayrıca, size projenizin stilleri için Sass Bootstrap kullanma seçeneği de sunar.
Bir Polymer uygulaması geliştirelim
Bazı özel Polimer öğeleri ve yeni oluşturucumuzu kullanarak basit bir blog oluşturacağız.
Başlamak için terminale gidin, yeni bir dizin oluşturun ve mkdir my-new-project && cd $_
komutunu kullanarak cd'yi girin. Artık aşağıdaki komutu çalıştırarak Polymer uygulamanızı kullanmaya başlayabilirsiniz:
$ yo polymer
Bu işlem 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çmeye ne dersiniz?
Şimdi, uygulamanın nasıl göründüğünü önizlemek için grunt server
eklentisini çalıştırabiliriz:
Sunucu LiveYeniden Yükleme'yi destekler. Böylece, bir metin düzenleyiciyi etkinleştirebilir, özel bir öğeyi düzenleyebilir ve tarayıcı kaydedildiğinde sayfayı yeniden yükleyebilirsiniz. Bu sayede uygulamanızın mevcut durumunu gerçek zamanlı ve güzel bir şekilde görebilirsiniz.
Şimdi de Blog yayınını temsil edecek yeni bir Polimer öğesi oluşturalım.
$ yo polymer:element post
Yeoman bize bir kurucu eklemek mi yoksa post öğesini index.html
içine eklemek için bir HTML İçe Aktarması kullanmak mı istediğimiz gibi birkaç soru soruyor. Şimdilik ilk iki seçeneğe "Hayır" diyelim, üçüncü seçeneği de boş bırakın.
$ 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 öğe 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 ortak metin kodu - "Yerel" istemci tarafı şablon için bir şablon etiketi ve öğenizin stillerini kapsüllemek için örnek kapsamlı stiller
- Öğe kayıt standart metni ve yaşam döngüsü etkinlikleri.
Gerçek bir veri kaynağıyla çalışma
Blogumuzun yeni yayınlar yazmak ve okumak için bir yere ihtiyacı olacak. Gerçek bir veri hizmetiyle çalışmayı göstermek için Google Apps E-Tablolar API'sını kullanacağız. Bu, Google Dokümanlar kullanılarak oluşturulan herhangi bir e-tablonun içeriğini kolayca okumamıza olanak tanır.
Bu ayarları yapalım:
Tarayıcınızda (bu adımlar için Chrome önerilir) bu Google Dokümanlar E-tablosunu açın. Aşağıdaki alanların altında örnek yayın verilerini içerir:
- Kimlik
- Başlık
- Yazar
- İçerik
- Tarih
- Anahtar kelimeler
- E-posta (yazarın)
- Sümüklü böcek (yayınınızın sümüklü böcek URL'si için)
Dosya menüsüne gidin ve e-tablonun kendi kopyanızı oluşturmak için Kopya oluştur'u seçin. Yayın ekleyerek veya kaldırarak içeriği istediğiniz zaman düzenleyebilirsiniz.
Dosya menüsüne tekrar gidin ve Web'de yayınla'yı seçin.
Yayınlamaya başla'yı tıklayın.
Yayınlanan verilerin bağlantısını alın'ın altında, son metin kutusundan, sağlanan URL'nin anahtar bölümünü kopyalayın. Şu şekilde görünür: https://docs.google.com/spreadsheet/ccc?key=0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc#gid=0
Anahtarı, your-key-goes-here ifadesinin yer aldığı aşağıdaki 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ın kullanıldığı bir örnek, https://spreadsheets.google.com/feeds/list/0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc/od6/public/values?alt=json-in-script
URL'yi tarayıcınıza yapıştırabilir ve blog içeriğinizin JSON sürümünü görüntülemek için URL'ye gidebilirsiniz. URL'yi not edin ve daha sonra ekranda gösterebilmek için tekrarlamanız gerekeceğinden bu verilerin biçimini incelemeye biraz zaman ayırın.
Tarayıcınızdaki JSON çıkışı biraz korkutucu görünebilir, ancak endişelenmeyin! Yalnızca yayınlarınıza ait verilerle ilgileniyoruz.
Google E-Tablolar API'sı, blog e-tablonuzdaki her alanı özel bir önek post.gsx$
ile çıkarır. Örneğin: post.gsx$title.$t
, post.gsx$author.$t
, post.gsx$content.$t
vb. JSON çıkışımızdaki her "satırı" tekrarlarken, her yayınla ilgili değerleri geri almak için bu alanlara başvuracağız.
Artık işaretlemenin bölümlerini e-tablonuzdaki verilere bind için yeni iskeleye eklenen yayın öğenizi düzenleyebilirsiniz. Bunu yapmak için daha önce yayın başlığı, yazarı, içeriği ve diğer alanlar için okuyacak bir post
özelliğini kullanıma sunuyoruz. Daha sonra dolduracağımız selected
özelliği, bir yayını yalnızca kullanıcı ilgili yayın için doğru alana 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>
Şimdi yo polymer:element blog
komutunu çalıştırarak hem yayın koleksiyonunu 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, blog'u, sayfada görünmesini istediğimiz şekilde HTML içe aktarmalarını kullanarak index.html içine aktarıyoruz. Özellikle üçüncü istem için eklemek istediğimiz öğe olarak post.html
değerini belirtiriz.
Daha önce olduğu gibi, yeni bir öğe dosyası oluşturulur (blog.html) ve /elements öğesine 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 dizinimize HTML içe aktarma (diğer HTML dokümanlarına ekleme ve yeniden kullanma yöntemi) kullanılarak içe aktarılmasını istediğimizden, öğenin <head>
dokümanına 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 kullanarak bağımlılık ekleme
Şimdi öğemizi, posts.json dosyasında okumak için Polymer JSONP yardımcı program öğesini kullanacak şekilde düzenleyelim. Bağdaştırıcıyı, kod deposunu git klonlayarak veya bower install polymer-elements
komutunu çalıştırarak Bower üzerinden polymer-elements
yükleyerek alabilirsiniz.
Yardımcı programı oluşturduktan sonra, bunu blog.html öğenize içe aktarma olarak eklemeniz gerekir:
<link rel="import" href="../bower_components/polymer-jsonp/polymer-jsonp.html">
Ardından bu etiketin etiketini ekleyin ve daha önceki blog yayınları e-tablomuzda en sona &callback=
ekleyerek url
öğesini sağlayın:
<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 şekilde, e-tablomuzun okunmasının ardından e-tablomuz üzerinde iterasyon yapmak için şablonlar ekleyebiliriz. İlki, bir gönderiyi gösteren, bağlantılı bir başlığın bulunduğu bir içindekiler tablosu 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 ise bulunan her giriş için bir post-element
örneği oluşturup yayın içeriğini buna uygun şekilde söz konusu girişe iletir. Tek bir e-tablo satırı için yayın içeriğini temsil eden bir post
özelliği ve rotayla dolduracağımız bir selected
özelliği geçirdiğimize dikkat edin.
<!-- 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 [[ bağlamalar ]] içeren bir örnek oluşturur ve saklar.
Şimdi mevcut [[route]] alanını doldurabilmemiz için hile yapıp URL karması her değiştiğinde [[route]] ile bağlanan Flatiron yöneticisi adlı bir kitaplık kullanacağız.
Neyse ki bunun için kullanabileceğimiz bir Polimer öğesi (more-elements paketinin parçası) var. /elements dizinine kopyalandıktan sonra, <flatiron-director route="[[route]]" autoHash></flatiron-director>
ile başvuruda bulunabiliriz. Bunu, bağlamak istediğimiz özellik olarak route
belirterek yapabilir ve karma değişikliklerinin (autoHash) değerini otomatik olarak okumasını söyleyebiliriz.
Her şeyi bir araya getirdiğimizde şimdi şunları 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>
Tebrikler! Artık, JSON verilerini okuyan ve Yeoman ile desteklenen iki Polymer öğeyi kullanan basit bir blog'umuz var.
3. taraf öğeleriyle çalışma
Web Bileşenleri etrafındaki öğe ekosistemi, customelements.io gibi bileşen galerisi sitelerinin görünmeye başlamasıyla son zamanlarda büyümektedir. Topluluk tarafından oluşturulan öğelere göz gezdirirken gravatar profillerini getirmek için bir tane buldum. Biz de bu profili alıp blog sitemize ekleyebiliriz.
Gravatar öğesinin kaynaklarını /elements
dizininize kopyalayın, bunu post.html'deki HTML içe aktarmaları aracılığıyla ekleyin ve ardından
<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>
Şimdi bunun bize neler sunduğuna bakalım:
Güzel!
Nispeten kısa bir süre içinde, ortak kod yazmak, bağımlılıkları manuel olarak indirmek veya yerel sunucu ya da derleme iş akışı ayarlamak zorunda kalmadan birçok web bileşeninden oluşan basit bir uygulama oluşturduk.
Uygulamanızı optimize etme
Yeoman iş akışında Grunt adlı başka bir açık kaynak proje yer alır. Bu proje, uygulamanızın optimize edilmiş bir sürümünü oluşturmak için derlemeye özgü birçok görevi (Gruntfile'da tanımlanır) çalıştırabilen bir görev çalıştırıcıdır. grunt
kendi başına çalıştırıldığında, oluşturucunun test etme, test etme ve derleme için ayarladığı 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 edecek ve ardından bunu projenizdeki tüm JavaScript dosyalarında çalıştırır. JSHint ile ilgili seçeneklerinizin tamamını görmek için dokümanlara göz atın.
test
görevi buna biraz benzer ve uygulamanızı kullanıma hazır olarak önerdiğimiz test çerçevesi olan Mocha'ya uygun şekilde oluşturup sunabilir. Ayrıca testlerinizi sizin için yürütür:
grunt.registerTask('test', [
'clean:server',
'createDefaultTemplate',
'jst',
'compass',
'connect:test',
'mocha'
]);
Buradaki uygulamamız oldukça basit olduğundan, bu konudaki testleri ayrı bir alıştırma olarak size bırakacağız. Derleme işlemimizi gerçekleştirmemiz gereken birkaç şey daha var. Bu nedenle şimdi Gruntfile.js
dokümanımızda tanımlanan grunt build
görevinin ne yapacağına bir göz atalım:
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
'yi çalıştırdığınızda uygulamanızın üretime hazır sürümü derlenerek gönderilmeye hazır olur. Haydi deneyelim.
Başarıyla gerçekleştirildi.
Zorlanırsanız https://github.com/addyosmani/polymer-blog adresine göz atmanız için polymer-blog'un önceden oluşturulmuş bir sürümünü kullanabilirsiniz.
Mağazamızda başka neler var?
Web Bileşenleri ve bu bileşenlerin etrafındaki araçlar hâlâ gelişme aşamasındadır.
Şu anda Vulcanize (Polymer projesinin bir aracı) gibi projeler aracılığıyla daha iyi yükleme performansı için HTML içe aktarmalarını birleştirmenin nasıl yapılabileceğini ve bileşen ekosisteminin Bower gibi bir paket yöneticisiyle nasıl çalışabileceğini inceliyoruz.
Bu sorulara daha iyi yanıtlar elde ettiğimizde sizi haberdar edeceğiz ancak önümüzdeki heyecanlı günler bizi bekliyor.
Polymer'i Bower ile bağımsız olarak yükleme
Polymer'i daha hafif bir başlangıç için tercih ederseniz aşağıdaki komutu çalıştırarak doğrudan Bower'dan bağımsız olarak yükleyebilirsiniz:
bower install polymer
Bu işlem onu bower_components dizininize ekler. Daha sonra uygulama dizininizde bunu manuel olarak referans gösterebilir ve gelecek için sağlam olabilirsiniz.
Ne düşünüyorsunuz?
Artık Yeoman ile Web Bileşenleri'ni kullanarak bir Polymer uygulamasını nasıl kaynaştıracağınızı biliyorsunuz. Oluşturucu hakkında geri bildiriminiz varsa lütfen yorumlar bölümünde bize bildirin veya Yeoman sorun izleme aracına bir hata bildiriminde bulunun ya da yayın oluşturun. Yalnızca sizin kullanımınız ve geliştirebileceğimiz geri bildirimleriniz sayesinde oluşturucunun daha iyi olmasını istediğiniz başka bir şey olup olmadığını bilmeyi çok isteriz :)