Polymer Power Tools

96270e4c3e5e9806cf7245475c00b275?s=47 Addy Osmani
September 20, 2015

Polymer Power Tools

We'll cover the new tools now available to help you build with Polymer in production including Polymer Starter Kit, Vulcanize, Crisper, Polyup, Polylint, PolyGit, web-component-tester, our docs and code viewer tools and much more!

Video: https://www.youtube.com/watch?v=LMqM4PfrFxs

Presented at Polymer Summit 2015.

96270e4c3e5e9806cf7245475c00b275?s=128

Addy Osmani

September 20, 2015
Tweet

Transcript

  1. Images: Dreamstime.

  2. Today we’ll take an in-depth look at Polymer tooling. We’ll

    cover tools for creating elements & apps, setting up a build process, keeping your projects lean and a few new tools for improving your developer productivity.
  3. https://goo.gl/lqZyhu Images: Dreamstime.

  4. But..before that, a quick story. A few weeks ago I

    was visiting Japan. A place that’s really big on automation - the idea of solving repetitive tasks with tools & systems. They’ve really taken this concept to a whole other level. One example of this is the idea of parking a bike.
  5. https://www.flickr.com/photos/szipiszopi/5159559474/

  6. Now, Polymer Summit being in Amsterdam, you may be familiar

    with the number of bikes here. There are many. Statistically speaking, I’m pretty sure every person in Amsterdam owns 3 million bikes. Parking bikes is a hard problem.
  7. None
  8. Japan has solved this problem using the ECO Cycle -

    an automated system that has a giant robotic arm that pulls down your bike and parks it for you underground. If this is the first time you’ve seen that, you’re probably wondering.. what type of crazy Matrix sorcery is this?!. This is automation saving us time. Why is automation important for webapp developers?
  9. If you want to be fast, you have to give

    up the things keeping you slow.
  10. Obviously, we can’t automate everything. If we did we would

    be out of a job. Japan has struck a balance between automation and where manual craftsmanship still has its place. At my hotel, they would include a paper crane with meals. Someone manually crafted this origami each time rather than automating it with a machine.
  11. https://goo.gl/lqZyhu Images: Dreamstime.

  12. Paper cranes look pretty graceful.

  13. https://goo.gl/lqZyhu Images: Dreamstime, Addy Osmani.

  14. I thought..Hey, I can JavaScript. Surely folding paper can’t be

    all that hard. I’m going to make a paper crane! And, well. The TL;DR is that I’m no longer allowed back in Japan.
  15. https://goo.gl/lqZyhu

  16. Where are the tools for our declarative shift? 3,427,000 tools

    HTML Getting better!
  17. The JavaScript tooling ecosystem has a huge number of existing

    tools available. If you’ve used Polymer & Web Components a while, you may have run into few places where running these tools against HTML can be tricky. Things like linting. Good news is that tooling for these problems is getting better.
  18. Build Test Lint Serve CSP CDN 127.0.0.1 git </> The

    New Polymer Toolbox¬ Images: Dreamstime.
  19. Let’s walk through tools for: Writing Reusable elements Automatically porting

    elements to Polymer 1.0 Unit Testing elements Adding elements to apps Productionising apps ~ Vulcanize, Crisper, PolyBuild, PolyLint, PolyGit (CDN) Bonus tools for your workflow
  20. Tool Requirements¬ Windows / Mac / Linux

  21. https://goo.gl/lqZyhu Images: NPM, Node foundation, Bower.

  22. Writing Reusable Elements¬ Elements we can share. Images: Dreamstime.

  23. <seed-element>¬ Seed for new Polymer elements github.com/polymerlabs/seed-element

  24. <seed-element> /demo /test seed-element.html index.html hero.svg bower.json README.md

  25. <head> <script src=“../webcomponentsjs/webcomponents-lite.js"> </script> <link rel="import" href=“../iron-component-page/iron-component-page.html"> </head> <body unresolved>

    <iron-component-page></iron-component-page> </body> </html> <seed-element> index.html API docs Images: Google Powered by Hydrolysis
  26. <html> <head> <script src=“../../webcomponentsjs/webcomponents-lite.js"> </script> <link rel="import" href="../seed-element.html"> </head> <body

    unresolved> <seed-element></seed-element> </body> </html> <seed-element> demo/index.html Your demo
  27. <link rel="import" href="../polymer/polymer.html"> <!-- An element providing a solution to

    no problem in particular. --> <dom-module id="seed-element"> <template> <style> ... </style> </template> </dom-module> <script> Polymer({ is: 'seed-element', properties: { <seed-element> seed-element.html Your element Images:JSConf
  28. <emoji-text text=“tear”></emoji-text> https://github.com/addyosmani/emoji-text

  29. <emoji-text text=“tear clap”></emoji-text> https://github.com/addyosmani/emoji-text

  30. <!-- An element that translates text to emoji! Example: <emoji-text

    text="Cats love eating donuts!”></emoji-text> @demo demo/index.html --> <dom-module id="emoji-text"> <template> <style>:host { display: block; }</style> <div id=“output"></div> </template> </dom-module> <script> Polymer({ is: 'emoji-text', properties: { text: { type: 'String', notify: true, observer: '_textChanged' } }, _textChanged: function() { ... } textToEmoji: function() { ... } }); </script> <emoji-text> seed-element.html > emoji-text.html Images: Polymer
  31. $  npm  install  -­‐g  bower   $  bower  install  

    > Before we forget, install our dependencies
  32. PolyServe¬ Serving elements to a browser. 127.0.0.1 github.com/polymerlabs/polyserve Images: Dreamstime,

    Addy Osmani.
  33. $  npm  install  -­‐g  polyserve   $  cd  seed-­‐element  

    $  polyserve   Starting  Polyserve  on  port  8000     Serving  components  from  bower_components > Simple server for using components locally $  polyserve  -­‐p  9999 > Customise port number
  34. None
  35. None
  36. #  Navigate  back  to  your  development  directory   $  cd

     ..   #  git  clone  the  Polymer  tools  repository   $  git  clone  git://github.com/Polymer/tools.git   #  Create  a  temporary  directory  for  publishing  your  element  and  cd  into  it   $  mkdir  temp  &&  cd  temp   #  Run  the  gp.sh  script.   $  ../tools/bin/gp.sh  <username>  emoji-­‐text   #  Finally,  clean-­‐up  your  temporary  directory  as  you  no  longer  require  it   $  cd  ..   $  rm  -­‐rf  temp > Deploy? Publish to GitHub pages with gp.sh
  37. PolyUp¬ Automate levelling up 0.5 > 1.0 github.com/polymerlabs/polyup Images: Dreamstime,

    Polymer.
  38. <polymer-element name='emoji-text' attributes='text'> <template> <style>:host { display: block; }</style> <div

    id='output' on-tap='{{_showOriginalText}}'></div> </template> <script> Polymer({ textToEmoji: function(str) { }, _showOriginalText: function() { }, … }); </script> </polymer-element> <emoji-text> 0.5
  39. $  npm  install  -­‐g  polyup   $  polyup  emoji-­‐text.html >

    Automate your upgrades Polymer 0.5>
  40. HTML Transformations <polymer-element name='my-elem'> <dom-module id='my-elem'> <template repeat='{{x, i in

    xs}}'> <template is='dom-repeat' items='{{xs}}' as='{{x}}' index-as='{{i}}'> <template if='{{x}}'> <template is="dom-if" if="{{x}}">
  41. <dom-module id='emoji-text'> <style>:host { display: block; }</style> <template> <div id='output'

    on-tap='_showOriginalText'></div> </template> <script> Polymer({ is: 'emoji-text', properties: { text: { notify: true } }, textToEmoji: function(str) { }, _showOriginalText: function() { }, ... }); </script> </dom-module> 1.0
  42. $  find  .  -­‐name  "*.html"  -­‐execdir  polyup   -­‐-­‐overwrite  "{}"

     \;   > PRO-TIP. Recursive upgrades! WIN
  43. None
  44. Unit Testing Elements¬ Verifying elements are legit. Images: Dreamstime.

  45. Web Component Tester¬ Unit testing for Elements github.com/polymer/web-component-tester

  46. $  npm  install  -­‐g  web-­‐component-­‐tester   $  wct > Test

    your Web Components Images: Mocha & Chai projects.
  47. <html> <head> <meta charset="utf-8"> <script src="../../webcomponents-lite.js"></script> <script src=“../../web-component-tester/browser.js"> </script> </head>

    <body> <script> // Load and run all tests (.html, .js): WCT.loadSuites([ 'basic-test.html' ]); </script> </body> </html> test/index.html
  48. <emoji-text text=“top gun”></emoji-text> <script> suite('emoji-text tests', function() { var emojiText

    = document.querySelector(‘emoji-text’); test('Defines the "text" property', function() { assert.equal(emojiText.text, 'top gun'); }); test('Converts text to emoji', function() { emojiText.textToEmoji(); assert.include(emojiText.innerHTML, ''); assert.include(emojiText.innerHTML, ''); }); }); </script> test/basic-test.html
  49. None
  50. $  wct  -­‐l  chrome > only run tests in chrome

    $  wct  -­‐p > keep browsers alive after test runs $  wct  test/some-­‐file.html > test only the files you specify Testing #protips
  51. Adding Elements To Apps¬ Using Polymer Starter Kit Images: Dreamstime.

  52. Polymer Starter Kit Images: Polymer.

  53. thestocks.im first-class components end-to-end build process application theming responsive app

    layout offline-first (optional) 67K DOWNLOADS
  54. None
  55. None
  56. None
  57. Let’s walk through building a quick app that builds on

    the <emoji-text> element. Something that clearly has a niche in the market.
  58. Emoji Quiz App¬

  59. <emoji-quiz-card> <dom-module id="emoji-quiz-card"> ... <emoji-text text=“{{question}}"> </emoji-text> <paper-input required pattern="{{questionPattern}}"

    value="{{answer}}" error-message="OMG NO!" label="Enter your answer"> </paper-input> <paper-button on-tap=“validate"> Submit Answer ... Images: EmojiLib
  60. <emoji-quiz-questions> ready: function() { this.items = [ 'princess diaries', 'back

    to the future', 'sound of music', 'ghost ship', 'china town', 'evil dead', 'money ball']; } Images: EmojiLib
  61. <emoji-quiz-category> <neon-animated-pages id="pages" selected="0"> <x-cards-list> <div class="horizontal layout"> <emoji-quiz-category title="Music"

    emoji="music"></emo <emoji-quiz-category title="Movies" emoji="movies"></e </div> <div class="layout horizontal"> <emoji-quiz-category title=“Knowledge" theme="red" emo <emoji-quiz-category title="Books" theme="green" emoji </div> </x-cards-list> <x-card> <emoji-quiz-questions category="movies"></emoji-quiz-ques </x-card> <x-card> <emoji-quiz-questions category="music"></emoji-quiz-quest </x-card> … </neon-animated-pages>
  62. https://goo.gl/lqZyhu Make BUILD TOOLS & TASK RUNNERS Images: Grunt, Gulp,

    NPM, Fotosearch.
  63. $  npm  install  —g  gulp  bower  &&  npm  install  &&

     bower  install   > Install tooling & PSK dependencies Node 0.12+
  64. ALL THE INTERNET NPM INSTALL Images: Allie Brosh

  65. $  gulp  serve > Serve our application

  66. Images: Addy Osmani, EmojiLib

  67. Images: Addy Osmani, EmojiLib

  68. Images: Addy Osmani, EmojiLib

  69. CSS IS AWESOME CUSTOM PROPERTIES MAKE IT BETTER.

  70. None
  71. <style is="custom-style"> :root { --dark-primary-color: #388E3C; --default-primary-color: #4CAF50; --light-primary-color: #C8E6C9;

    --text-primary-color: #FFFFFF; --accent-color: #CDDC39;
  72. Production-ising Apps¬ Polymer Build Tools Images: Dreamstime.

  73. A build process is a promise to your users.

  74. build process Images: Addy Osmani, Hannah Lee, Gulp

  75. Vulcanize Crisper PolyBuild PolyLint PolyGit

  76. Vulcanize¬ Concatenate Imports for Production github.com/polymer/vulcanize Images: https://www.flickr.com/photos/ssoosay/16771481611/.

  77. $  npm  install  -­‐g  vulcanize   $  vulcanize  emoji-­‐app.html  >

     build.html   > Reduce an app & its dependents into one file.
  78. $  vulcanize  -­‐-­‐inline-­‐scripts  emoji-­‐app.html     > Inline scripts and

    Imports > Inline Polymerized stylesheets $  vulcanize  -­‐-­‐inline-­‐css  emoji-­‐app.html
  79. Crisper¬ Make HTML files CSP compliant github.com/polymerlabs/crisper Images: Dreamstime

  80. $  npm  install  -­‐g  crisper   $  crisper  -­‐-­‐source  index.html

     -­‐-­‐html  build.html  -­‐-­‐js  build.js   > Split inline scripts from HTML for CSP
  81. $  vulcanize  index.html  -­‐-­‐inline-­‐script  |  crisper  -­‐-­‐html  build.html   build.js

      > Using Vulcanize? Crisper accepts HTML string output directly.
  82. PolyBuild¬ Combines Vulcanize, Crisper & Polyclean github.com/polymerlabs/polybuild

  83. vulcanize  -­‐-­‐inline-­‐css  -­‐-­‐inline-­‐scripts  -­‐-­‐strip-­‐comments  index.html  |   polyclean  |  crisper

     -­‐-­‐html  index.build.html  -­‐-­‐js  index.build.js   Rather than this.. $  npm  install  -­‐g  polybuild   $  polybuild  index.html     Just do this:
  84. PolyBuild with Gulp! var gulp = require('gulp'); var polybuild =

    require('polybuild'); gulp.task('build', function() { return gulp.src('index.html') .pipe(polybuild()) .pipe(gulp.dest('.')); }); Images: Gulp
  85. $  polybuild  —maximum-­‐crush  index.html > MAXIMUM CRUSH! JS MINIFIED ||

    whitespace removed https://www.flickr.com/photos/stigster/4574486940/
  86. WIP TOOLS

  87. PolyLint¬ </> Linting for Elements github.com/polymerlabs/polylint Images: Dreamstime

  88. $  npm  install  -­‐g  polylint   $  polylint  index.html >

    Keep your elements clean and functional
  89. $ polylint sample/imports/ bind-to-class.html sample/imports/bind-to- class.html:12:5 The expression [[myVars]] bound

    to the attribute 'class' should use $= instead of =. <span class=“[[myVars]]"> I love styling with Polymer! </span> ❌ <span class$=“[[myVars]]"> I love styling with Polymer! </span> ✅
  90. $ polylint sample/imports/bound- variables-declared.html sample/imports/bound-variables- declared.html:12:11 Property myVar not found

    in 'properties' for element 'bound- variables-declared' <dom-module id="bound-variables-declared"> <template> <span>[[myVar]]</span> ❌ <span>{{myVars}}</span> ✅ </template> </dom-module> <script> Polymer({ is: 'bound-variables-declared', properties: { myVars: { type: String, value: 'Hello linter!' } } }); </script>
  91. $ polylint sample/imports/computed- binding.html sample/imports/computed- binding.html:13:11 Computed Binding using property

    'notAFunction', which is not a function for element'computed- binding' <dom-module id="computed-binding"> <template> <span>{{notAFunction(myVars)}}</span> ❌ <span>[[isAFunction(myVars)]]</span> ✅ </template> </dom-module> <script> Polymer({ is: 'computed-binding', properties: { myVars: { type: String, value: ‘Hey big linter!' } }, isAFunction: function() { return ''; }, notAFunction: 3 }); </script>
  92. PolyGit¬ A stateless CDN compatible with deduping polygit.org Images: Dreamstime

  93. Loading without configuration <link rel="import" href="https://polygit.org/components/polymer/polymer.html"> <link rel="import" href="https://polygit.org/components/paper-toolbar/paper-toolbar.html"> polygit.org/components/<element>/<import>.html

    Even better with the <base> tag <base href="http://polygit.org/components/"> <link href="polymer/polymer.html" rel="import">
  94. Auto-organisation selection <base href=“http://polygit.org/components/"> github.com/WebComponents <script src="webcomponentsjs/webcomponents-lite.min.js"></script> github.com/PolymerElements <link href=“paper-button/paper-button.html”

    rel=“import”> github.com/GoogleWebComponents <link href=“google-signin/google-signin.html” rel="import">
  95. <base href="http://polygit.org/polymer+:master/components/"> <link href="polymer/polymer.html" rel="import"> Control orgs, branches & versions

    Default org, specific version: paper-button+v1.0.2 Default org, master branch: polymer+:master Different org, specific component: super-gif+sjmiles+*
  96. Bonus Tools¬ Productivity boosters

  97. Polymer Ready Extension

  98. Polymer is now used in Chrome!

  99. New Chrome PDF Viewer

  100. New Chrome Downloads page

  101. Upcoming Chrome Settings page

  102. Sublime & Atom Snippets

  103. PolySearch Images: Eiji Kitamura

  104. BUILD & EXPERIMENT

  105. gravatar-photo.html <dom-module id="gravatar-photo"> <template> <img src$="[[url]]"> </template> </dom-module> <script src=“src/gravatar-photo.js"></script>

    <script> Polymer({ is: 'gravatar-photo', .. attached: function () { this.url = window.gravatar.url(this.email, { s: this.size }); } }); </script> Polymer + https://github.com/polymerlabs/gravatar-photo var gulp = require("gulp"); var browserify = require("gulp-browserify"); gulp.task("build", function () { gulp.src("gravatar-photo.js") .pipe(browserify()) .pipe(gulp.dest("build")) }); src/gravatar-photo.js window.gravatar = require("gravatar"); gulpfile.js <gravatar-photo email="robdodson@gmailz.com" size="400"></gravatar-photo>
  106. gravatar-photo.html <dom-module id="gravatar-photo"> <template> <img src$="[[url]]"> </template> </dom-module> <script src=“src/gravatar-photo.js"></script>

    <script> Polymer({ is: 'gravatar-photo', .. attached: function () { this.url = window.gravatar.url(this.email, { s: this.size }); } }); </script> Polymer + https://github.com/polymerlabs/gravatar-photo var gulp = require("gulp"); var browserify = require("gulp-browserify"); gulp.task("build", function () { gulp.src("gravatar-photo.js") .pipe(browserify()) .pipe(gulp.dest("build")) }); src/gravatar-photo.js window.gravatar = require("gravatar"); gulpfile.js <gravatar-photo email="robdodson@gmailz.com" size="400"></gravatar-photo>
  107. gravatar-photo.html <dom-module id="gravatar-photo"> <template> <img src$="[[url]]"> </template> </dom-module> <script src=“src/gravatar-photo.js"></script>

    <script> Polymer({ is: 'gravatar-photo', .. attached: function () { this.url = window.gravatar.url(this.email, { s: this.size }); } }); </script> Polymer + https://github.com/polymerlabs/gravatar-photo var gulp = require("gulp"); var browserify = require("gulp-browserify"); gulp.task("build", function () { gulp.src("gravatar-photo.js") .pipe(browserify()) .pipe(gulp.dest("build")) }); src/gravatar-photo.js window.gravatar = require("gravatar"); gulpfile.js
  108. Future Polymer Designer Polymer DevTools

  109. Polymer Starter Kit¬ NEW Recipes: ES6, Perf, CDE Better tooling

    pipeline Lots of bug fixes!
  110. // Transpile all JS to ES5. gulp.task('js', function () {

    return gulp.src(['app/{elements,scripts}/**/*.{js,html}']) .pipe($.sourcemaps.init()) .pipe($.if('*.html', $.crisper())) // Extract JS from .html files .pipe($.if('*.js', $.babel())) .pipe($.sourcemaps.write('.')) .pipe(gulp.dest('.tmp/')) .pipe(gulp.dest('dist/')); }); ES6 support via { "preset": "google", "esnext": true } Images: BabelJS, JSCS. Optional
  111. Support for the new Chrome for Android Splashscreen When a

    webapp is launched from the Homescreen, this themes the white screen you see until the renderer has something to show.
  112. Tool on!¬ With special thanks to our tool makers.

  113. Fin.¬ +AddyOsmani @addyosmani