reset.cssを自作してみた
リセットCSSを導入した。
作成したもの
reset.css(自作)
期待する動き
デフォルトのマージンやパディングなどの無駄なスタイリングを削除し、ブラウザ間の差異を吸収する。
結果
不明
手順など
styles ディレクトリに reset.css を作成する。
ROOT_DIRECTORY/ + node_modules/ + build/ + source/ | + renderer/ | | + components/ | | | + app/ | | | | + view.js | | | | + style.css | | | | | | | + header/ | | | + view.js | | | + style.css | | | | | + renderer.js | | | + styles/ | | + reset.css | | | + index.html | + gulpfile.babel.js + .babelrc + package.json
source/index.html
reset.css を読み込めるようにする。
<!DOCTYPE html> <html> <head> <title>Nukindex</title> <link rel="stylesheet" href="./styles/reset.css"> <link rel="stylesheet" href="./styles/bundle.css"> </head> <body> <div id="app"></div> <script src="./renderer/bundle.js"></script> </body> </html>
source/styles/reset.css
とりあえずよく気になる部分をリセットしてみた。
html, body { margin: 0; padding: 0; font-weight: 300; font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", "Noto Sans Japanese", "ヒラギノ角ゴ ProN W3", Meiryo, sans-serif; } p { line-height: 1.5; font-size: 16px; } h1 { margin: 0; padding: 0; line-height: 1.2; font-size: 32px; } h2, h3, h4, h5, h6 { margin: 0; padding: 0; line-height: 1.2; font-size: 16px; } ol, ul { margin: 0; padding: 0; list-style: none; } input, textarea { box-sizing: border-box; } input:focus, textarea:focus { outline: none; } [hidden="true"] { display: none; }
gulpfile.babel.js
CSSをビルドする関数を追加する。
React 用のCSSはビルドしたくないので gulp.src
から renderer 以下を除外する。
import gulp from "gulp"; import browserify from "browserify"; import babelify from "babelify"; import source from "vinyl-source-stream"; import transform from "vinyl-transform"; import cssModulesify from "css-modulesify"; gulp.task("build", () => { buildHTML(); buildCSS(); buildRenderer(); }); function buildHTML() { gulp.src(["source/**/*.html", "!source/renderer/**/*"]) .pipe(gulp.dest("build")); } function buildCSS() { gulp.src(["source/**/*.css", "!source/renderer/**/*"]) .pipe(gulp.dest("build")); } function buildRenderer() { browserify({ "entries": ["source/renderer/renderer.js"], "extensions": ["", ".js", ".jsx", ".css"] }).plugin(cssModulesify, { "output": "./build/styles/bundle.css" }).transform(babelify).bundle() .pipe(source("bundle.js")) .pipe(gulp.dest("build/renderer")); }
CSS Moduleを導入した
View に関してはこれで一段落。
作成したもの
CSS Moduleの導入
期待する動き
cssファイルを使ってコンポーネント毎にスタイルを定義する。ビルド時にひとつのcssファイルにまとめて出力する。
結果
成功
事例が探せなかったので苦労した。
手順など
各コンポーネントディレクトリに style.css を作成する。
ROOT_DIRECTORY/ + node_modules/ + build/ + source/ | + renderer/ | | + components/ | | | + app/ | | | | + view.js | | | | + style.css | | | | | | | + header/ | | | + view.js | | | + style.css | | | | | + renderer.js | | | + index.html | + gulpfile.babel.js + .babelrc + package.json
gulpfile 内にCSSモジュールの使用準備をする。
$ npm install css-modulesify --save-dev
gulpfile.babel.js
browserify のプラグインとして導入する。
import gulp from "gulp"; import browserify from "browserify"; import babelify from "babelify"; import source from "vinyl-source-stream"; import transform from "vinyl-transform"; import cssModulesify from "css-modulesify"; gulp.task("build", () => { buildHTML(); buildRenderer(); }); function buildHTML() { gulp.src("source/**/*.html") .pipe(gulp.dest("build")); } function buildRenderer() { browserify({ "entries": ["source/renderer/renderer.js"], "extensions": ["", ".js", ".jsx", ".css"] }).plugin(cssModulesify, { "output": "./build/styles/bundle.css" // CSSファイルの出力先を指定 }).transform(babelify).bundle() .pipe(source("bundle.js")) .pipe(gulp.dest("build/renderer")); }
source/renderer/components/header/style.css
普通のCSSファイル。
.container { background-color: #fff; } .title { margin: 16px 0 12px; padding: 0 24px; } .description { margin: 12px 0 16px; padding: 0 24px; }
source/renderer/components/header/view.js
styles
にCSSファイルをインポートする。
styles
にはCSSファイルに定義したクラス名がプロパティとして入る。
className
にそのプロパティを入れ込む。
import React from "react"; import CSSModules from "react-css-modules"; import styles from "./style"; export default class Component extends React.Component { render() { return ( <header className={styles.container}> <h1 className={styles.title}> <a href="/">Nukindex</a> </h1> <p className={styles.description}> 毎日のおかずを提供するサイトです </p> </header> ); } }
source/index.html
ビルドしたCSSファイルを読み込む。
<!DOCTYPE html> <html> <head> <title>Nukindex</title> <link rel="stylesheet" href="./styles/bundle.css"> </head> <body> <div id="app"></div> <script src="./renderer/bundle.js"></script> </body> </html>
React のスタイリングとしては CSS in JS がメジャーなのか、 CSS modules の使用例はあまり見つけられなかった。
先例がないと初心者にはつらい。
React + Redux 開発用のディレクトリ構造を作った
先を見据えて丁寧に作っていきたいが先がどうなるか分からない。
作成したもの
React + Redux 開発用のディレクトリ構造
期待する動き
結果
成功
手順など
ROOT_DIRECTORY/ + node_modules/ + build/ + source/ | + renderer/ | | + components/ | | | + app/ | | | | + view.js | | | | | | | + header/ | | | + view.js | | | | | + renderer.js | | | + index.html | + gulpfile.babel.js + .babelrc + package.json
source/index.html
React 描画エリアと React 描画ファイルを配置する。
<!DOCTYPE html> <html> <head> <title>Nukindex</title> </head> <body> <div id="app"></div> <script src="./renderer/bundle.js"></script> </body> </html>
source/renderer/renderer.js
React コンポーネントと DOM を結びつける。
React
クラスは処理部分で使用していないが、これを削除するとブラウザ実行時にエラーになる。
import React from "react"; import ReactDOM from "react-dom"; import App from "./components/app/view"; ReactDOM.render( <App />, document.getElementById("app") );
source/renderer/components/header/view.js
各コンポーネントは components 以下に配置していく。 コンポーネント毎に MVC を用意していく予定なので js ファイルではなくディレクトリにまとめる。
import React from "react"; export default class HeaderComponent extends React.Component { render() { return ( <header> <h1> <a href="/">Nukindex</a> </h1> <p>毎日のおかずを提供するサイトです</p> </header> ); } }
source/renderer/components/app/view.js
コンポーネントは別コンポーネントを呼び出し、使用することができる。
import React from "react"; import HeaderComponent from "../header/view"; export default class App extends React.Component { render() { return ( <div> <HeaderComponent /> </div> ); } }
詰まったのは ReactDOM
クラスが React
クラスに依存しているところくらいだった。
React
クラスは処理部分で使用していないが、これを削除するとブラウザ実行時にエラーになる。
gulpを使ってES2015+で書いたReactのファイルをトランスパイルする。
日本語がよく分からなくなってきた。 「gulpを使ってES2015+で書いたReactのファイルをトランスパイルする。」 もっと分かりやすい題にならないのか。
とにかく題の通り環境構築に成功した。 失敗の積み重ねの上に成功した。
主にbrowserify周りの失敗だ。 なんとなくWebpackが流行っている理由が分かった気がする。
作成したもの
gulp build
コマンド
期待する動き
JSX と ES2015+ で書かれた依存関係のあるファイルを、ブラウザで実行可能な bundle.js ファイルとして出力する。
結果
成功
手順など
ROOT_DIRECTORY/ + node_modules/ + build/ + source/ | + index.html | + renderer.js | + gulpfile.babel.js + .babelrc + package.json
React のファイルを作成する
$ npm install react --save-dev $ npm install react-dom --save-dev
index.html
React 描画エリアになる要素を作っておく。ここでは <div id="app"></div>
のとこ。
React のファイルはコンポーネントごとに分けて作成することになるので、トランスパイル時に bundle.js としてまとめて出力し、それを HTML で読み込む予定。
<!DOCTYPE html> <html> <head> <title>Nukindex</title> </head> <body> <div id="app"></div> <script src="./renderer/bundle.js"></script> </body> </html>
renderer.js
今回の目的はブラウザで読み込んで描画できる形で出力することなので複雑にしない。
import React from "react"; import ReactDOM from "react-dom"; class App extends React.Component { render() { return ( <div> <h1>Nukindex</h1> </div> ); } } ReactDOM.render( <App />, document.getElementById("app") );
gulpfile を設定する。
$ npm install browserify --save-dev $ npm install babelify --save-dev $ npm install vinyl-source-stream --save-dev $ npm install vinyl-transform --save-dev
gulpfile.babel.js
返り値はストリームになるのでそれをパイプしていくとのこと(謎)
gulpデビュー - Nukindex 開発ブログ
これな。。。こうなると思ってたけどstream関係の仕様が謎過ぎてめっちゃ時間かかった。 とりあえず中身。
import gulp from "gulp"; import browserify from "browserify"; import babelify from "babelify"; import source from "vinyl-source-stream"; import transform from "vinyl-transform"; gulp.task("build", () => { buildHTML(); buildRenderer(); }); function buildHTML() { gulp.src("source/**/*.html") .pipe(gulp.dest("build")); } function buildRenderer() { // ブラウザでも読み込める形にしてくれるやつ。 // 主に require などで依存関係を持つファイルをうまいこと結合してくれる。 browserify({ "entries": ["source/renderer.js"], // 指定した拡張子を省略できる。 // import Abc from "abc.js"; を import Abc from "abc"; と書ける。 "extensions": ["", ".js", ".jsx"] }).transform(babelify).bundle() // transform も babelify も bundle も謎 .pipe(source("bundle.js")) // source も謎 .pipe(gulp.dest("build/renderer")); }
ここらへんはググっても「これが正解!」みたいなやり方を見つけられなかった。 みんな同じところで同じように困ってるみたい。
gulp.src("source/renderer.js") .pipe(babel({ "target": "browser", "presets": ["react", "es2015"] }) .pipe(rename("bundle.js")) .pipe(gulp.dest("source/renderer"));
とか
browserify({ "entries": ["source/renderer.js"], "extensions": ["", ".js", ".jsx"], "presets": ["react", "es2015"] }) .pipe(gulp.dest("build/renderer"));
みたいな感じでシンプルにできるようにしてほしい。。。
.babelrc
わすれがち
{ "presets": [ "react", "es2015" ] }
ここまでで gulp build
コマンドによりブラウザで読み込める bundle.js ファイルを出力することができる。
めんどくさかった上にすっきりしない。
gulpデビュー
「Reactデビュー」と言う題で書き始めたが、道が遠いので「gulpデビュー」に変えた。
gulpというのはタスクランナーの一種で、現在最も主流であるらしい。 感覚的には開発の面倒なことを自動化してくれるお助けツールだ。 一部では脱gulpの動きもあるようだが、どうも便利そうなので使っておきたい。
作成したもの
gulp build
コマンド
期待する動き
source ディレクトリのファイルを build ディレクトリへ移動する
結果
成功
手順など
npmの初期化
> npm init
gulp のパッケージをインストール
gulp 自体も ES2015+ で書きたいのでそのためのパッケージもインストール
> npm install babel --save-dev > npm install babel-preset-es2015 --save-dev > npm install gulp --save-dev > npm install gulp-babel --save-dev
必要なディレクトリ、ファイルを作成
ROOT_DIRECTORY/ + node_modules/ + build/ + source/ | + index.html | + gulpfile.babel.js + .babelrc + package.json
.babelrc
babel の設定ファイル。 babel は ES2015+ で書かれたJSファイルを古い環境でも実行できるように変換するツール。
{ "presets": [ "es2015" ] }
gulpfile.babel.js
gulp
コマンドの設定ファイル。
import gulp from "gulp"; // この部分が gulp build コマンドで動く gulp.task("build", () => { buildHTML(); }); function buildHTML() { // gulp で操作する対象ファイルを指定 // 返り値はストリームになるのでそれをパイプしていくとのこと(謎) gulp.src("source/**/*.html") // 最後は出力先を指定する .pipe(gulp.dest("build")); }
返り値はストリームになるのでそれをパイプしていくとのこと(謎)
ここな。このブラックボックス感が嫌でいつもライブラリ使わずにフルスクラッチしてるんだけど。
でもそんなこと言い出したらマシン語まで理解しないといけないような気もしてきた。 どこで妥協するかの問題か。
ここまでで gulp build
コマンドが通って期待どおりの動きとなった。
調べながらだと時間がかかる。