メタ言語の続きです。前回はdel
を使って破壊神になり、ファイルを削除しました。今回はこれまで作ってきたコードを元にフロントエンド開発スターターキットを作ります。メタ言語(EJS、Sass(SCSS)、TypeScript)のコンパイル&画像圧縮を行う環境です。それではいきましょう!
【目次】
- 前回のおさらい
- フロントエンド開発スターターキットを作る
- フロントエンド開発スターターキット
- EJSからHTMLにコンパイル
- Sass(SCSS)からCSSにコンパイル
- TypeScriptからJSにコンパイル
- 画像の圧縮
- 姉妹リポジトリ「Webコーディングスターターキット」
- 最後に
※参考:前回記事
【gulp】我、破壊神となりてdelをもってファイルを削除すべし - クモのようにコツコツと
※参考:【メタ言語】HTMLテンプレートエンジン、AltCSS、AltJSのまとめ
qiita.com
前回のおさらい
詳細は前回の記事を参照
※参考:【gulp】我、破壊神となりてdelをもってファイルを削除すべし - クモのようにコツコツと
ここまでで環境構築系はいったん一区切りにする。
フロントエンド開発スターターキットを作る
これまで作ったコードを元にフロントエンド開発スターターキットを作りたい。
※参考:GitHub - ryo-i/frontendMetaLanguage at 7d153d6de2fb00624691f0e15fcf38128e9b0de7
こちらの記事の手順で既存リポジトリをローカルにクローン(git clone
コマンド)
※参考:【Express】Heroku CLIを使ってNode.js環境をHeroku上にデプロイする - クモのようにコツコツと
ファイル構成を最低限の内容に変更する。
こちらの記事の手順で新規リポジトリと連携(git remote
)
※参考:【Express】HerokuとGitHubを連携して自動デプロイ(環境変数は除外) - クモのようにコツコツと
フロントエンド開発スターターキット
フロントエンド開発スターターキットを作った
ソース(GitHub)
※参考:GitHub - ryo-i/front-end-getting-sterted: メタ言語(EJS、Sass(SCSS)、TypeScript)のコンパイル環境です。画像も圧縮します。
プレビュー(GitHub Pages)
全体構成
全体的な環境は下記のような構成、挙動になっている。
/src
フォルダを修正するとコンパイル実行(ブラウザも更新)/src
フォルダ ->/dest
フォルダにコンパイルされる/src/ejs
->/dest
直下(.ejs
->.html
)/src/scss
->/dest/css
(.scss
->.css
)/src/ts
->/dest/js
(.ts
->.js
)/src/img
->/dest/img
(.jpg
,.jpeg
,.png
,.gif
,.svg
画像を圧縮)/src/json
->/src/ejs
,/src/ts
で読み込み
環境構築の過程はこちらを参照
※参考:【メタ言語】HTMLテンプレートエンジン、AltCSS、AltJSのまとめ
qiita.com
導入手順
ターミナルのcd
コマンドで導入したいフォルダに移動
$ cd /(パス)
リポジトリをするクローンする
$ git clone https://github.com/ryo-i/front-end-getting-sterted.git
「front-end-getting-sterted.git」というフォルダが作られる。
フォルダに移動する
$ cd front-end-getting-sterted
パッケージのインストール
npm install
「node_modules」フォルダが作られる
gulp起動、終了
gulpの起動
$ npm start
localhostの3000でブラウザが立ち上がる
gulpの終了 「Contrl + C」
新規リポジトリにコミット
GitHub上の新規リポジトリにコミットする場合はgit remote
コマンドで紐付け
$ git remote add origin https://github.com/ユーザ名/リポジトリ名.git
EJSからHTMLにコンパイル
ファイル構成
/src/ejs
はこのようなファイル構成になっている
BEMのブロックごとにファイルを分けている。
/src/json
フォルダのdata.json
にHTMLのテキスト部分がある
/dest
フォルダの直下のindex.html
にコンパイルされる
コンパイル前(/src/ejs)
index.ejs
ページ本体ファイル
<!doctype html> <html> <head> <%- include('base/_head', {header: data.header}); %> </head> <body> <%- include('block/_header', {header: data.header}); %> <%- include('block/_main', {main: data.main, inner: data.inner}); %> <%- include('block/_footer', {footer: data.footer}); %> </body> </html>
include()
の第一引数でモジュールファイルをインクルードinclude()
の第二引数でモジュールファイルにjsonファイルのデータを渡す
_head.ejs
headファイルにインクルードするモジュール
<meta charset="UTF-8"> <title><%= header.title %></title> <meta name="description" content="<%= header.text %>"> <link rel="stylesheet" href="css/style.css"> <script src="js/script.js"></script>
header
という名前でjsonファイルのデータを読み込む(下記のheaderタグと共通の内容)
なお、モジュールファイルはファイル名の頭に_
が付けていて、コンパイルから除外される。
_header.ejs
headerタグにインクルードするモジュール
<header class="header"> <h1 class="header__title"><%- header.title %></h1> <p class="header__text"><%- header.text %></p> </header>
header
という名前でjsonファイルのデータを読み込む
_main.ejs
mainタグにインクルードするモジュール
<main> <section class="main"> <h1 class="main__title"><%- main.title %></h1> <p class="main__text"><%- main.text %></p> <%- include('_inner', {inner: inner}); %> </section> </main>
main
という名前でjsonファイルのデータを読み込む- pタグの下でさらに
_inner
モジュールをインポートしている
_inner.ejs
上記の_main
タグにインポートしているモジュール
<% for (var i = 0; i < inner.length; i++) { %> <section class="inner"> <h2 class="inner__title"><%- inner[i].title %></h2> <p class="inner__text"><%- inner[i].text %></p> </section> <% } %>
inner
という名前でjsonファイルのデータを読み込む- for文で配列の数繰り返して読み込む
_footer.ejs
footerタグにインクルードするモジュール
<footer class="footer"> <p class="footer__text"><%- footer.text %></p> </footer>
footer
という名前でjsonファイルのデータを読み込む
data.json
HTMLに読み込まれているテキストのコンテンツ
{ "data": { "header": { "title":"フロントエンド開発スターターキット", "text": "メタ言語(EJS、Sass(SCSS)、TypeScript)のコンパイル環境です。画像も圧縮します。" }, "main": { "title":"タイトルです", "text": "テキストです。テキストです。テキストですったらテキストです。" }, "inner": [ { "title": "CSS(文字色)", "text": "CSSでタイトルの文字色変更。" }, { "title":"JS(文字列)", "text": "JSでテキストの文字列追加「<span class='inner__text--hello'></span>」" } ], "footer": { "text":"©️ front-end-getting-sterted" } } }
外部jsonファイルにすることでHTMLタグの構造とコンテンツを分離している。
コンパイル後(/dest/index.html)
index.htmlにこのような形でコンパイルされる
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>フロントエンド開発スターターキット</title> <meta name="description" content="メタ言語(EJS、Sass(SCSS)、TypeScript)のコンパイル環境です。画像も圧縮します。"> <link rel="stylesheet" href="css/style.css"> <script src="js/script.js"></script> </head> <body> <header class="header"> <h1 class="header__title">フロントエンド開発スターターキット</h1> <p class="header__text">メタ言語(EJS、Sass(SCSS)、TypeScript)のコンパイル環境です。画像も圧縮します。</p> </header> <main> <section class="main"> <h1 class="main__title">タイトルです</h1> <p class="main__text">テキストです。テキストです。テキストですったらテキストです。</p> <section class="inner"> <h2 class="inner__title">CSS(文字色)</h2> <p class="inner__text">CSSでタイトルの文字色変更。</p> </section> <section class="inner"> <h2 class="inner__title">JS(文字列)</h2> <p class="inner__text">JSでテキストの文字列追加「<span class='inner__text--hello'></span>」</p> </section> </section> </main> <footer class="footer"> <p class="footer__text">©️ front-end-getting-sterted</p> </footer> </body> </html>
Sass(SCSS)からCSSにコンパイル
ファイル構成
/src/scss
はこのようなファイル構成になっている
BEMのブロックごとにファイルを分けている。
/dest/css
フォルダのstyle.css
にコンパイルされる
コンパイル前(/src/scss)
style.scss
インクルードするモジュールファイルをコンパイルしたい順に並べている
@import 'setting/_variable'; @import 'setting/_mixin'; /***** base *****/ @import 'base/_base'; /***** block *****/ @import 'block/_header'; @import 'block/_main'; @import 'block/_inner'; @import 'block/_footer';
/setting
フォルダは他のモジュールに渡す設定値/base
フォルダは全体に共通するスタイル/block
フォルダはBEM記法のブロックごとのファイル
Sass(SCSS)でもファイル名に_
がついたモジュールファイルはコンパイルで除外される
_variable.scss
変数値を設定しているファイル
$base-color: #ff0000; $text-color: #333; $text-color_w: #fff; $bg-color_g: #eee; $text-size: 14px;
ブロックを跨いで共通する色やサイズなど
_mixin.scss
共通スタイルを設定しているファイル
@mixin pageSize($width: 1000px) { width: 100%; max-width: $width; padding: 20px; margin: 0 auto; }
pageSize
という名前でページサイズの設定。幅は1000pxより狭い場合は100%になる。
_base.scss
bodyタグに設定しているページ全体に共通する設定
body { margin: 0; padding: 0; font-family: sans-serif; font-size: $text-size; color: $text-color; *, *:before, *:after { box-sizing: border-box; } a { color: $base-color; } }
$
で_variable.scssの変数を読み込んでいる
_header.scss
header
ブロックのスタイル
/* header */ .header { @include pageSize(); text-align: center; background: $bg-color_g; padding: 20px; &__title { font-size: 2em; } }
@include
で_mixin.scssのスタイル設定を読み込んでいる。$
で_variable.scssの変数を読み込んでいる
_main.scss
main
ブロックのスタイル
/* main */ .main { @include pageSize(); &__title { font-size: 1.5em; } }
@include
で_mixin.scssのスタイル設定を読み込んでいる。
_inner.scss
inner
ブロックのスタイル
/* inner */ .inner { &__title { font-size: 1.25em; color: $base-color; } }
$
で_variable.scssの変数を読み込んでいる
_footer.scss
footer
ブロックのスタイル
/* footer */ .footer { @include pageSize(); text-align: center; }
@include
で_mixin.scssのスタイル設定を読み込んでいる。$
で_variable.scssの変数を読み込んでいる
コンパイル後(/dest/css/style.css)
style.cssにはこのようにコンパイルされる
/***** base *****/ body { margin: 0; padding: 0; font-family: sans-serif; font-size: 14px; color: #333; } body *, body *:before, body *:after { box-sizing: border-box; } body a { color: #ff0000; } /***** block *****/ /* header */ .header { width: 100%; max-width: 1000px; padding: 20px; margin: 0 auto; text-align: center; background: #eee; padding: 20px; } .header__title { font-size: 2em; } /* main */ .main { width: 100%; max-width: 1000px; padding: 20px; margin: 0 auto; } .main__title { font-size: 1.5em; } /* inner */ .inner__title { font-size: 1.25em; color: #ff0000; } /* footer */ .footer { width: 100%; max-width: 1000px; padding: 20px; margin: 0 auto; text-align: center; }
TypeScriptからJSにコンパイル
ファイル構成
/src/ts
フォルダはこのような構成になっている
/modules
フォルダにhello
モジュールがあり、その中も機能ごとにモジュールファイルを分けている
/src/json
フォルダのhello.json
にJSに使用する値を入れている
/dest/js
フォルダのscript.js
にコンパイルされる
コンパイル前(/src/ts)
script.ts
モジュールファイルを読み込むファイル
import { hello } from './modules/hello/hello'; // modules hello();
hello
モジュールをインポートしてhello()
で実行している
hello.ts
hello
モジュールの本体
import { message } from './message'; const text: string = message.text; const selector: string = message.selector; const hello = (): void => { document.addEventListener('DOMContentLoaded', () => { const dom: HTMLButtonElement = document.querySelector(selector) as HTMLButtonElement; dom.innerHTML = text; console.log('text-> ' + text); }); } export { hello }
message.ts
をインポートhello ()
関数でタグにテキストを入れたりコンソールにテキストを表示するhello ()
関数をhello
モジュールとしてエクスポート
message.ts
JSONファイルを読み込んでオブジェクトを作成
import hello from '../../../json/hello.json'; const message: {[key: string]: string;} = { text: hello.message.text, selector: hello.message.selector }; export { message };
hello.json
をインポート変数
messageはオブジェクト(連想配列)で
hello.jsonの
textと
selector`を設定message
オブジェクトをmessage
モジュールとしてエクスポート
hello.json
hello
モジュールで読み込んでいる設定値
{ "message": { "text": "こんにちは、ふろんとえんど。", "selector": ".inner__text--hello" } }
message
のtext
キーはテキストmessage
のselector
キーはタグのclass名
コンパイル後(/dest/js/script.js)
script.jsにこのようにコンパイルされる
(()=>{"use strict";const e=JSON.parse('{"y":{"f":"こんにちは、ふろんとえんど。","n":".inner__text--hello"}}');var t={text:e.y.f,selector:e.y.n},n=t.text,o=t.selector;document.addEventListener("DOMContentLoaded",(function(){document.querySelector(o).innerHTML=n,console.log("text-> "+n)}))})();
webpackでバンドルしているので圧縮されている。JSONデータはJSON.parse()
でオブジェクトに変換している。
整形するとこのようになる
(()=>{ "use strict"; const e = JSON.parse('{"y":{"f":"こんにちは、ふろんとえんど。","n":".inner__text--hello"}}'); var t = { text: e.y.f, selector: e.y.n } , n = t.text , o = t.selector; document.addEventListener("DOMContentLoaded", (function() { document.querySelector(o).innerHTML = n, console.log("text-> " + n) } )) } )();
画像の圧縮
初期状態は空
/src/img
フォルダの初期状態は空
/dest/img
フォルダも空
画像圧縮(/src/img -> /dest/img)
対応している拡張子は.jpg
,.jpeg
,.png
,.gif
,.svg
姉妹リポジトリ「Webコーディングスターターキット」
Webコーディングスターターキットも作った
※参考:GitHub - ryo-i/web-coding-getting-sterted: HTML/CSS/JSコーディングの最小環境です。
ファイル構成
基本的には「フロントエンド開発スターターキット」の「/dest」フォルダとほぼ同じ。
script.js
先ほどのwebpackを整形したコードを少し手直し
const hello = JSON.parse( '{"message":{"text":"こんにちは、ふろんとえんど。","selector":".inner__text--hello"}}' ); const message = { text: hello.message.text, selector: hello.message.selector }; const text = message.text; const selector = message.selector; document.addEventListener("DOMContentLoaded", () => { document.querySelector(selector).innerHTML = text; console.log("text-> " + text); });
- 変数名をTypeScriptの設定名に戻す
- 変数
var
をconst
に - function関数をアロー関数に
最後に
とうことでフロントエンド開発スターターキットを作りました。なるべく最低限の構成を心がけましたが、同時にモジュール分割でのフロントエンド開発がイメージできるようにバランスを取りました。
メタ言語(EJS、Sass(SCSS)、TypeScript)はこちらの記事で書いたように、HTML、CSS、JSの上位互換になっている言語で、既存コードからの移行が可能な言語を選定しています。
※参考:フロントエンドのメタ言語のコンパイル環境を作る(言語選定編) - クモのようにコツコツと
今後、自分自身のフロントエンド開発環境としてもこのリポジトリを使って行きたいと思っています。(また何か修正をするときには記事にしていこうと思います)
それではまた!
※参考:【メタ言語】HTMLテンプレートエンジン、AltCSS、AltJSのまとめ
qiita.com