代々木で働く19歳エンジニアのブログ

思ったこととか、技術的なこと書きます。

Bootstrap ざっと全容把握

Bootstrapとは?

the world’s most popular framework for building responsive, mobile-first sites

要は結構有名なCSS framework

frameworkと、design pattern (atomic designとか)

Design pattern is a category of patterns that deals with object oriented software. ... It is a large entity comprising of several design patterns. Frameworks are concerned with specific application domain e.g. database, web application etc.

frameworkとは、 a reusable set of libraries or classes for a software system (or subsystem)

デザインパターンがカテゴリー(atomic designとか)で、frameworkは実際に使えるもの。

つまり、

the world’s most popular framework for building responsive, mobile-first sites

レスポンシブなサイトを作れるものってこと

how to download

Download Bootstrap to get the compiled CSS and JavaScript, source code, or include it with your favorite package managers like npm, RubyGems, and more.

  • Package managers

    $ npm install bootstrap@4.0.0-beta.3

    $ gem install bootstrap -v 4.0.0.beta3

    $ composer require twbs/bootstrap:4.0.0-beta.3

  • Compiled CSS and JS ( すでに圧縮されたファイル ) ← GHJはこれで入れてた。

  • Source files ( Sass compiler と、Autoprefixer が必要 )
  • CDN(BootstrapCDN)

    • css only

      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">

    • js, Popper.js, jQuery

      <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js" integrity="sha384-a5N7Y/aK3qNeh15eJKGWxsqtnX/wWdSZSKp+81YjTmS15nvnvxKHuzaWwXHDli+4" crossorigin="anonymous"></script>

Popper.js とは

様々な動きの制御が簡単にできるライブラリ

https://popper.js.org/

結構細かく読み込むファイルをわけられる

Official Themes がある

dashboard-screenshot_2048x2048.jpg (90.7 kB)

toolkits built on Bootstrap with new components and plugins, docs, and build tools.

Starter template

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">

    <title>Hello, world!</title>
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js" integrity="sha384-a5N7Y/aK3qNeh15eJKGWxsqtnX/wWdSZSKp+81YjTmS15nvnvxKHuzaWwXHDli+4" crossorigin="anonymous"></script>
  </body>
</html>

Support Browser

Layout

  • Overview
    • Containers
    • Responsive breakpoints
    • Z-index
  • Grid system
    • Grid options
    • Auto-layout columns
    • Responsive classes
    • Alignment
    • Reordering
    • Nesting
    • Sass mixins
  • Media object

Components

  • Alerts
  • Badge
  • Breadcrumb
  • Buttons
  • Button group
  • Card
  • Carousel
  • Collapse
  • Dropdowns
  • Forms
  • Input group
  • Jumbotron
  • List group
  • Modal
  • Navs
  • Navbar
  • Pagination
  • Popovers
  • Progress

Content

端的に言うとデフォルトのhtml にstyleが当たるもの。normalized.cssのbootstrap版みたいな感じ。

  • Reboot
  • Typography
  • Code
  • Images
  • Tables
  • Figures

Utilities

  • Borders
  • Clearfix
  • Close icon
  • Colors
  • Display
  • Embed
  • Flex
  • Float
  • Image replacement
  • Position
  • Screenreaders
  • Sizing
  • Spacing
  • Text
  • Vertical align
  • Visibility

Examples

実際にbootstrapを使ったprojectを見ることができる

まとめ・感想

reference from

読みやすいPRの書き方まとめ

前提

コードを書く前に

  • [ ] 実現したい要件はそれで合っていますか?
  • [ ] フローチャートなどで処理の流れを可視化できていますか?
  • [ ] 本当にそのソリューションで正しいですか?解決方法は本当にそれだけですか?

変数

  • [ ] それ変数化する意味ありますか?
  • [ ] その変数初期化する意味ありますか?

メソッド

  • [ ] そのメソッド本当に抽象化する必要ありますか?
  • [ ] その処理再利用できませんか?
  • [ ] そのメソッドその責務負う必要ありますか??

制御文

  • [ ] そのif文三演算子でone linerでかけないですか??
  • [ ] その評価・条件本当に必要ですか??
  • [ ] それ以外(else)の処理書き忘れていませんか?
  • [ ] そのif文、switch文にできませんか?もしそうしたら、break忘れてないですか?

コメント

  • [ ] その処理コメントつけなくてもわかってもらえますか?
  • [ ] 逆にそのコメント処理の内容とか関数名とか見れば自明ではないですか?

名前

  • [ ] その名前抽象的じゃないですか?もっと具体的にできないですか?
  • [ ] そこ本当にキャメルケースでその言語はその命名規則で正しいですか?

基本

  • [ ] ちゃんと要件通りにうごいているかためしましたか?
  • [ ] もっと短く書ける書き方はありませんか?
  • [ ] その書き方は最新の安定版ですか?
  • [ ] 無駄な評価、条件はありませんか?
  • [ ] 文字リテラルの結合処理は + ではなく、interpolation使っていますか?
  • [ ] そのメソッド、変数のスコープはそれで本当にただしいですか?
  • [ ] その関数とかクラス、ちゃんと単一責任ですか?
  • [ ] もう少し早くその関数から返すことってできませんか?fast returnできませんか?
  • [ ] 既存のコードに流されていませんか?どうしてそのフォルダ構造、ファイル名になっているか考えましたか?
  • [ ] もう少しそのコード単純にできませんか?

リーダブルコード

http://tenshotanaka.hatenablog.com/entry/2017/07/05/173544

注意すること

Commit (社内の元cookpadの「R言語上級ハンドブック」共著者の人が言ってたこと転載)

  • どの commit の状態でも最低限動く状態にする
  • 試行錯誤の結果、無意味になる commit は削除する or 1 commit にまとめる
  • 変更の必要性がわかるようにする
    • 例えば、model を追加する commit、controller を追加する commit、view を追加する commit みたいに分けると、commit 順で見ても model のメソッドがどこでどう使われるかがわからないし、controller で取得した情報が view でどのように使われるかわからないので良くない
  • 開発途中で気付いた不要なコードの削除は 1 commit にする or 別 PR にする
  • commitを適切な粒度で分ける
    • 新しいtableを導入して管理画面を実装する際はCRUDの実装をそれぞれ別commit にする
    • 機能の廃止、機能の追加、リファクタリングなどは commit か PR を分ける
    • メソッドの移動等、変更量が多い場合は細かく commit を分ける

Comment

  • プルリクエストには目的を明記する
  • プルリクを読む人々が経緯に精通していると思い込まず、なぜその仕事が発生したのか概要を提供するように努める
  • 会社の誰しもがプルリクエストを読めるということを忘れないようにする。今後、今参加している人以外が読んだ時にも、内容や雰囲気がわからなくてはいけない
  • あなたがどんなフィードバックを望んでいるのか明確にする。例えば「コードに目を通して欲しい」「技術的な議論がしたい」「設計について批評してほしい」「文言を確認してほしい」などです
  • 議論に関与させたい誰かがいるなら@hogeと指定(mention)する。そしてなぜmentionしたのかを添える。(例: /cc @jesseplusplus ロジックの明確化のため)
  • チームに対してmentionする場合も同様に理由を添える。(例 /cc @github/security このやり方で問題ないですか?)

フィードバックへの対応

  • とにかくまず感謝を表明する。
  • 明確化するよう求める(「ねえよく分からないんだけど、もう少し説明してくれませんか?」)
  • 質問されたら、なぜそのような実装に辿り着いたのか説明し、しっかりとわかってもらう
  • できることなら、すべてのコメントに返信する
  • 関連するコミットやプルリクエストにリンクを貼る(「1682851でしたやつ、名案だね!」)
  • 議論の余地があったり混乱が見られる場合は、もっといい言葉をつかって彼らと会話できるのではないか自問してみる。対面で話し合っているつもりでやりとりし、オフラインで起きている議論を要約した続報をお互いに投稿してみる。(これから読む人に役にたちます)

Reference from

コードレビューまとめ

ざっと見てコードボリューム見る。 +400 くらいが妥当

https://gyazo.com/3afc1c119f16e7c32bb0207f3ea545fa

コミット粒度とコメントを見てみる

ざっくり全体感を見る、splitで見る

https://gyazo.com/6d9b026c3a625a3e253c672b23c2b91b

Reviewをするときに、なぜそうするべきなのか、cons, prosを示し、参考リンクもはる。

https://gyazo.com/898fcc6f08cf00b87ae3737a41dd7c3d

hogeしたほうがいい。
fugaということが考えられるから。
具体的に示すとこんな感じ

` bar foo puts hoge`

ref: http://tenshotanaka.hatenablog.com/

レビューコメントにラベルをつける

[MUST] 問題があり、必ず治す
[IMO] 意見、緩やかな指摘。自分ならこう書くけどどう?
[nits] ほんの小さな指摘。インデントやタイポ
  • 問題の内容や、どうしてこのプルリクエストが発生したのか把握する
  • 全く同意できない場合は、反応する前に数分自分の意見を検討する
  • 命令するのではなく、質問する(「…しないでください」よりも「…についてどう思いますか?」)
  • 誰かの作成した仕事を参照する際に、「バカな」などのような軽蔑的な言葉は避ける
  • 謙虚にやる。(「あまり分からないけど、試してみましょう…」)
  • 誇張を避ける。(「絶対に…しない」)
  • オンラインのコミュニケーションでは、ネガティブなバイアスがかかることに注意する。(内容が中立であれば、我々はネガティブな発言だと仮定しがちです)。→肯定的な書き方をする
  • 雰囲気を明確にするために絵文字を使う「いいじゃん」と「 :sparkles: :sparkles: いいじゃん :thumbsup: :sparkles: :sparkles: 」を比べてみてください。

Reference from

(随時更新) JS著名ツールなんとなくまとめ

Package manager

npm

  • npm is the package manager for JavaScript and the world's largest software registry.
  • a package manager for javascript
  • npm makes it easy for JavaScript developers to share and reuse code, and makes it easy to update the code that you’re sharing, so you can build amazing things.

install

how to use

$ npm install <package>
$ ls
node_modules      package-lock.json package.json

Reference from

bower

  • A package manager for the web

...psst! While Bower is maintained, we recommend using Yarn and Webpack for front-end projects read how to migrate!

だそうです。

install

$ npm install -g bower

how to use

$ bower install <package>
$ ls
bower.json       bower_components

Reference from

yarn

  • FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT

install

$ brew install yarn

how to use

$ yarn init
$ yarn add [package]
$ ls
node_modules package.json yarn.lock
$ yarn install

Reference from

component

  • frontend package manager and build tool for modular web applications

install

$ npm install -g component

how to use

$ ls
component.json index.css      index.html     index.js

$ component install necolas/normalize.css
github remote: 54 of 60 requests remaining, resetting at Thu Oct 30 2014 00:23:36 GMT+0100 (CET)
github remote: see https://github.com/component/guide/blob/master/changelogs/1.0.0.md#required-authentication for more information.
   installed : necolas/normalize.css@3.0.2 in 283ms
     install : complete
     
$ cat component.json
{
  "name": "my-first-component",
  "dependencies": {
    "necolas/normalize.css": "^3.0.2"
  },
  "scripts": ["index.js"],
  "styles": ["index.css"]
}

$ component build
$ ls
build          component.json index.css      index.html     index.js

Reference from

Duo

  • Duo is a next-generation package manager that blends the best ideas from Component, Browserify and Go to make organizing and writing front-end code quick and painless.

install

$ npm install -g duo

how to use

$ cat index.js
var uid = require('matthewmueller/uid');
var fmt = require('yields/fmt');

var msg = fmt('Your unique ID is %s!', uid());
window.alert(msg);

$ duo index.js
     building : index.js
        using : compatibility
        using : stoj
    installed : yields-fmt@0.1.0
    installed : matthewmueller-uid@0.0.2
        built : index.js
        wrote : index.js

$ ls
build      components index.js        
<script src="build/index.js"></script>

Reference from

Loader

RequireJS

  • RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node.
  • A file and module loader for JavaScript

install

http://requirejs.org/docs/download.html#requirejs

how to use

project-directory/
    index.html
    scripts/
        main.js
        require.js
        helper/
            util.js
<!DOCTYPE html>
<html>
    <head>
        <title>My Sample Project</title>
        <!-- data-main attribute tells require.js to load
             scripts/main.js after require.js loads. -->
        <script data-main="scripts/main" src="scripts/require.js"></script>
    </head>
    <body>
        <h1>My Sample Project</h1>
    </body>
</html>
requirejs(["helper/util"], function(util) {
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
});

JavaScript 用のモジュール管理フレームワークの1つ。

JavaScript を実装していて、 view や model などで細かくファイルを分割していると、ファイル間の依存関係を意識して読み込む順序を注意しないといけなくなる。

ファイル数が少なかったり、個人で開発しているのであれば手動管理でも大きな問題はない。 しかし、ファイル数が多くなってきたり複数人で開発していると、手動管理では限界がある。

RequireJS では、 JavaScript のコードをモジュールという単位で管理する。 そして、各コードは実装の先頭で使用するモジュールを宣言する。

RequireJS は使用するモジュールの宣言を元に、各モジュール間の依存関係を調べ、適切な順序で JavaScript のコードを読み込むようにしてくれる(<script>タグが自動で HTML に埋め込まれる)。

Reference from

Browserify

  • Browserify lets you require('modules') in the browser by bundling up all of your dependencies.
  • require('modules') in the browser
  • モジュール間の依存解決やファイルの結合を行う

install

$ npm install -g browserify

how to use

Browsers don't have the require method defined, but Node.js does. Browserify you can write code that uses require in the same way that you would use it in Node.

var unique = require('uniq');

var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];

console.log(unique(data));
$ npm install uniq

$ ls
index.html main.js node_modules/

$ browserify main.js -o bundle.js
<script src="bundle.js"></script>

Reference from

Module bundlers

Browserify

  • 省略

Webpack

  • bundle your assets(scripts, images, styles)
  • A bundler for javascript and friends. Packs many modules into a few bundled assets.
  • webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

install

$ npm install -D webpack
$ yarn add webpack --dev

how to use

  webpack-demo
  |- package.json
+ |- index.html
+ |- /src
+   |- index.js
function component() {
  var element = document.createElement('div');

  // Lodash, currently included via a script, is required for this line to work
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component());
<html>
  <head>
    <title>Getting Started</title>
    <script src="https://unpkg.com/lodash@4.16.6"></script>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>
  • 外部のライブラリに依存していることが見かけ上はわからない
    • It is not immediately apparent that the script depends on an external library.
  • 依存関係が考慮されていない
    • If a dependency is missing, or included in the wrong order, the application will not function properly.
  • 依存関係が含まれていたとしても、使われておらず、browserは余計なコードをダウンロードしてしまう
    • If a dependency is included but not used, the browser will be forced to download unnecessary code.

Creating a Bundle

  webpack-demo
  |- package.json
+ |- /dist
+   |- index.html
- |- index.html
  |- /src
    |- index.js

To bundle the lodash dependency with index.js, we'll need to install the library locally...

$ npm install --save lodash

src/index.js

+ import _ from 'lodash';
+
  function component() {
    var element = document.createElement('div');

-   // Lodash, currently included via a script, is required for this line to work
+   // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    return element;
  }

  document.body.appendChild(component());

dist/index.html

  <html>
   <head>
     <title>Getting Started</title>
-    <script src="https://unpkg.com/lodash@4.16.6"></script>
   </head>
   <body>
-    <script src="./src/index.js"></script>
+    <script src="bundle.js"></script>
   </body>
  </html>

The npx command, which ships with Node 8.2 or higher, runs the webpack binary (./node_modules/.bin/webpack) of the webpack package we installed in the beginning:

$ npx webpack src/index.js dist/bundle.js
Hash: 80992cf8fa2cd6324ca0
Version: webpack 3.10.0
Time: 391ms
    Asset    Size  Chunks                    Chunk Names
bundle.js  544 kB       0  [emitted]  [big]  main
   [0] ./src/index.js 267 bytes {0} [built]
   [2] (webpack)/buildin/global.js 509 bytes {0} [built]
   [3] (webpack)/buildin/module.js 517 bytes {0} [built]
    + 1 hidden module

Using a Configuration

Most projects will need a more complex setup, which is why webpack supports a configuration file.

  webpack-demo
  |- package.json
+ |- webpack.config.js
  |- /dist
    |- index.html
  |- /src
    |- index.js
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};
$ npx webpack --config webpack.config.js

Hash: 857f878815ce63ad5b4f
Version: webpack 3.9.1
Time: 298ms
    Asset    Size  Chunks                    Chunk Names
bundle.js  544 kB       0  [emitted]  [big]  main
   [0] ./src/index.js 222 bytes {0} [built]
   [2] (webpack)/buildin/global.js 509 bytes {0} [built]
   [3] (webpack)/buildin/module.js 517 bytes {0} [built]
    + 1 hidden module
webpack-demo
|- package.json
|- webpack.config.js
|- /dist
  |- bundle.js
  |- index.html
|- /src
  |- index.js
|- /node_modules

Reference from

Parcel

  • Blazing fast, zero configuration web application bundler

install

$ npm install -g parcel-bundler
$ yarn global add parcel-bundler

how to use

<html>
<body>
  <script src="./index.js"></script>
</body>
</html>
$ parcel index.html
$ cat package.json
{
  "name": "parcel-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "parcel-bundler": "^1.3.1"
  },
  "devDependencies": {},
  "scripts": {
     "start": "parcel index.html"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Bundler Time ---
browserify 22.98s
webpack 20.71s
parcel 9.98s
parcel - with cache 2.64s

https://github.com/parcel-bundler/parcel#benchmarks

Parcel — Small to medium sized projects (<15k lines of code) Webpack — Large to enterprise sized projects. Rollup — For NPM packages.

Reference from

Task runners

Gulp

  • Automate and enhance your workflow
  • The streaming build system

install

$ npm install gulp-cli -g
$ npm install gulp -D

how to use

$ ls
gulpfile.js       node_modules      package-lock.json package.json

$ cat package.json
{
  "name": "gulp-sample",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "dependencies": {},
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-sass": "^3.1.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
$ npm install -D gulp gulp-sass
$ cat gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass');

gulp.task('default', function () {
  gulp.src('css/style.scss')
    .pipe(sass())
    .pipe(gulp.dest('css'));
});
$ npx gulp
[16:42:47] Using gulpfile ~/src/local/frontend/gulp-sample/gulpfile.js
[16:42:47] Starting 'default'...
[16:42:47] Finished 'default' after 7.99 ms
onst gulp = require('gulp');
const sass = require('gulp-sass');

gulp.task('default', function () {
  gulp.watch('css/style.scss', function () {
    gulp.src('css/style.scss')
      .pipe(sass({
        outputStyle: 'expanded'
      })
      .on('error', sass.logError))
      .pipe(gulp.dest('css'));
  });
});
$ npx gulp

Reference from

Grunt

install

$ npm install grunt -D
$ npm install grunt-cli -D

how to use

$ ls 
Gruntfile.js      node_modules      package-lock.json package.json
$ cat package.json
{
  "name": "grunt-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {},
  "devDependencies": {
    "grunt": "^1.0.1",
    "grunt-cli": "^1.2.0",
    "grunt-contrib-cssmin": "^2.2.1",
    "grunt-contrib-watch": "^1.0.0",
    "grunt-init": "^0.3.2"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

$ cat Gruntfile.js
module.exports = function(grunt) {
  grunt.initConfig({
    cssmin: {
      minify: {
        files: {
          'css/style.min.css':'css/style.css'
        }
      }
    },
    watch: {
      files: ['css/style.css'],
      tasks: ['cssmin']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-watch');
};
$ grunt watch
Running "watch" task
Waiting...

Reference from

Compiler

babel

install

ES2015 and beyond

$ npm install -D babel-cli babel-preset-env
$ echo '{ "presets": ["env"] }' > .babelrc

Polyfill

$ npm install -D babel-polyfill

how to use

$ babel example.js --out-file compiled.js
import "babel-polyfill";

https://babeljs.io/docs/usage/polyfill/

Reference from

まとめ

  • 何よりやっているなのは、依存管理。package間、file間とかで依存管理をするtoolとかが多い。ということは依存管理というのはみんな苦労しているということか。
--- github star count stable version
npm 14935 5.6.0
bower 15286 1.8.2
yarn 29386 1.3.2
component 4635 1.1.0
duo 3553 0.15.7
RequireJS 11230 2.3.5
Browserify 11635 14.5.0
Webpack 35301 3.10.0
Parcel 13451 1.3.1
Gulp 28273 CLI:2.0.0/Local version:3.9.1
Grunt 11694 CLI:1.2.0/Local version:1.0.1
Babel 24910 6.26.0
golang/go 35647 1.9.2

Reference from

いつも学校のreport書くときに迷うのでメモ、markdownをpdfに変換

$ markdown-pdf hoge.md
$ ls
hoge.md hoge.pdf

Reference from

rbenvによるrubyのバージョンを切り換え備忘録

$ ruby --version
$ rbenv versions
$ rbenv install -l
$ rbenv install 2.5.0
$ rbenv global 2.5.0
  • global, local, shell

    • global: ~/.rbenv/version
    • local: ./.ruby-version
    • shell: RBENV_VERSION
  • インストールしたいrubyのバージョンがリストにない場合

$ brew update
$ brew upgrade rbenv ruby-build

Reference from

headless-chromeとpuppeteerを使った、web操作の自動化とscraping

headless-chromeとpuppeteerを使った、web操作の自動化とscraping

puppeteerとは

Puppeteer is a Node library API that allows us to control headless Chrome.

$ npm i puppeteer

Headless Chromeとは

Headless Chrome is a way to run the Chrome Browser without actually running Chrome.

Taking a Screenshot

1  const puppeteer = require('puppeteer');
2 
3  async function getPic() {
4   const browser = await puppeteer.launch();
5   const page = await browser.newPage();
6   await page.goto('https://google.com');
7   await page.screenshot({path: 'google.png'});
8 
9   await browser.close();
10 }
11 
12 getPic();

Something important to note is that our getPic() function is an async function and makes use of the new ES 2017 async/await features.

L4 We’re essentially launching an instance of Chrome and setting it equal to our newly created browser variable.

L5 Here we create a new page in our automated browser.

L6 In this example, we’re navigating to google. Our code will pause until the page has loaded.

L7 Now we’re telling Puppeteer to to take a screenshot of the current page

L9 we close down our browser

google.png

- const browser = await puppeteer.launch();
+ const browser = await puppeteer.launch({headless: false});

you can actually watch Google Chrome work as it navigates through your code.

+ await page.setViewport({width: 1000, height: 500})

google.png

Scrape some Data

1 const puppeteer = require('puppeteer');
2 
3 let scrape = async () => {
4     const browser = await puppeteer.launch({headless: false});
5     const page = await browser.newPage();
6 
7     await page.goto('http://books.toscrape.com/');
8     await page.click('#default > div > div > div > div > section > div:nth-child(2) > ol > li:nth-child(1) > article > div.image_container > a > img');
9     await page.waitFor(1000);
10
11    const result = await page.evaluate(() => {
12        let title = document.querySelector('h1').innerText;
13        let price = document.querySelector('.price_color').innerText;
14
15        return {
16            title,
17            price
18        }
19
20    });
21
22      browser.close();
23      return result;
24. };
25
26  scrape().then((value) => {
27      console.log(value); // Success!
28  });

L8 We now have our selector copied and we can insert our click method into our program.

L11 In order to retrieve these values, we’ll use the page.evaluate() method. This method allows us to use built in DOM selectors like querySelector().

https://gyazo.com/1bde38cca9ff1e0ad7fba0383c308ba2

❯ node scrape.js
{ title: 'A Light in the Attic', price: '£51.77' }

Perfecting it

     const page = await browser.newPage();

     await page.goto('http://books.toscrape.com/');
-    await page.click('#default > div > div > div > div > section > div:nth-child(2) > ol > li:nth-child(1) > article > div.image_container > a > img');
-    await page.waitFor(1000);

     const result = await page.evaluate(() => {
-        let title = document.querySelector('h1').innerText;
-        let price = document.querySelector('.price_color').innerText;
+        let data = []; // Create an empty array that will store our data
+        let elements = document.querySelectorAll('.product_pod'); // Select all Products

-        return {
-            title,
-            price
+        for (var element of elements){ // Loop through each proudct
+            let title = element.childNodes[5].innerText; // Select the title
+            let price = element.childNodes[7].children[0].innerText; // Select the price
+
+            data.push({title, price}); // Push an object with the data onto our array
         }

+        return data; // Return our data array
     });

     browser.close();

感想

結構簡単なコードでいろいろ動かせるので、おもしろい。 ただ、今回なんとなくの理解だったES2017のasync/awaitは勉強したい。

https://github.com/tenshotanaka/scripts/pull/3/commits/51c934da451de50978401370f2bec908c97e47ad

Reference from