LoginSignup
10
5

More than 5 years have passed since last update.

使いまわしを想定したWebアプリプロジェクトを考える

Last updated at Posted at 2017-12-12

この記事は FUJITSU Advent Calendar 2017 part2 の13日目です。

最近困っていたこと

最近、デモ用のWebアプリを作る機会が増えてきて、以下のことに困っていました。

  1. アプリをシンプルに作ったつもりが、使いまわしを考慮してないので、別件を頼まれたときに、新規にアプリケーションプロジェクトを作る羽目になる。
    • そのため
      • アプリとしての体裁を整えるまでに時間がとられ、見た目含めクオリティが上がらない。
      • 作り方を思い出すまでに時間がかかる。
      • 新しいことを試したい欲求にかられる。
  2. 他の人が作ったときのクオリティにばらつきが出る。
  3. デモアプリなので、内部のコードは汚くていいという心理が働く。

それぞれ言い訳をする。

  1. 突発的に頼まれたりしたときに、後先考えずに作ってしまう。
    • 新規にプロジェクトを作って、ある程度アプリとしての体裁を整えるまでが時間がかかる。一番面倒。
    • 前に作ったのをコピペしただけのはずなのに動かないことがある。
  2. 製品ならば、引継ぎ資料などを作りますが、デモ用なので、個人技でホイっと作ってしまう。
  3. 自家製の汚いソースを作ってしまい、後で誰かに渡すのが申し訳ないと考えてしまう。

改善したいポイント

  • 毎回、レベル1からのスタートはつらい。せめて、"強くてニューゲーム"を
    ⇒ プロジェクトをcloneし、コマンドを実行(npm installとgulp)するだけで、最低限の動きは保証。作り込みたい場所、差し替えればよい場所を誘導するアプリケーションプロジェクトを布教する。
    • 同時に以下にも対応。
      • 新しいことを試したい欲求。
      • 汚いコードの除去。

+α(ちょっとした願望) 新人にも少しずつ触れてもらい、Webアプリに慣れていってほしい。

// 残りの課題について。

  • 人間なので、忘れるのは仕方がない。

以上から、自分なりに使いまわしを想定したプロジェクトを考えてみた。

準備

  • Node.js・・・stableで良い。
    • gulpとbrowser-syncはインストール済みであること
$ npm install -g gulp browser-sync

npm install 前に、Proxy設定を確認。参考

技術選定

モバイル利用も想定して、SPAにすること前提で選定します。
ターゲットは、普段Webアプリを書いてない人。

  • フレームワーク
    • Riot.js
      • 今回、v3.7.4を利用
      • SPAの設定が簡単
      • タグベースのコンポーネント指向
      • scoped cssがある
      • ファイルが軽い
      • ドキュメントが日本語対応してる
  • HTMLテンプレートエンジン
    • pug
      • ファイル分割と、HTML/CSS/JSをincludeできる。
      • 記述量が減らせる。
        • もし、Pugが覚えられず、htmlで書いても許される。(しつこいですが、includeだけは使ってください。ごちゃまぜでも大丈夫)
      • ゴリラでもわかる
  • タスクランナー
    • gulp
      • pugの実行や集約を任せる
      • 各Alt系のビルド(必要なら)

テスト関連の話は今回触れません。

ビルドタスクの全体イメージ

画像のように、PostCSSやTypeScriptなど、Alt系をビルドしてから、Pugのincludeを利用し、CSSとJavaScriptを取り込んだHTMLを生成します。(Alt系を使わない場合は、真ん中の列(Pug+CSS+JS)だけやればよいです。今回、サンプルで紹介するソースにはpostcss/typescriptは出てきません。)

pugをビルドすると、デフォルトで拡張子がhtmlになります。拡張子を変えたい場合は各自変更してください。筆者は.tagに変更し、dist/tag/にコピーしてます。

プロジェクト構成

以下のようにしてみました。

<project_root>/
      ┣━assets/        ライブラリや変更を加えないファイルを格納
      ┣━dist/          ビルド後の資産格納
      ┃  ┣━css/
      ┃  ┣━tag/        pugをビルドした後のファイルを格納
      ┃  ┣━js/
      ┃  ┗━index.html
      ┣━node_modules/  使用するnode_moduleを格納
      ┣━src/           変更を加えるファイルを格納
      ┃  ┣━css/        postcsファイルの格納
      ┃  ┣━pug/        pugファイルのみ格納
      ┃  ┣━ts/         TS or JSファイルの格納
      ┃  ┗━index.html  開発序盤のライブラリの入れ替えを想定。src直下に置く。
      ┣━tmp            postcss/tsのビルド後の資産を一時格納
      ┃  ┣━ css/       ビルド後のCSS一時格納
      ┃  ┗━ js/        ビルド後のJS一時格納
      ┣━ .gitignore
      ┣━ gulpfile.js
      ┗━ package.json

pugのビルド後、ビルド後資産格納領域dist/に格納、この時、assets/に入れた、ライブラリもコピー・格納します。

格納後、サーバーを起動、テスト環境なら、browser-syncを使いましょう。
ライブリロードを活用した開発はオススメです。参考URL:Browsersyncを利用してお手軽ブラウザ確認環境をつくろう


//browser-syncの起動
gulp.task('setupBrowserSync', function () {
    browserSync({
        server: {
            baseDir: "./dist/"
        }
    });
});

// src/以下の資産の変更を検知すると、ビルドして、参照しているブラウザをリロードします。

gulp.task('watch', ['prepareBuild','setupBrowserSync'], function (cb) {
    gulp.watch(["./src/**"], function () {
        return runSequence(
      //      'build_PostCss', //PostCSSのビルド
      //     'build_TS',      // TypeScriptのビルド
            'build_Pug',      // Pugのビルド
            'copyExceptionFiles',     // 例外的なファイルのコピー(index.htmlなど)
            'reload'     // browser-syncの強制更新
        );
    });
});

gulp.task('prepareBuild', function (cb) {
  // 省略: watchのrunSequenceと同じ順でタスクを実行(reloadは不要)
});

タスクの実行順が重要です。run-sequenceを使用し、実行順を制御してください。

実装側

index.html

headerタグはheadernav.tagを固定参照、mainタグは各パスの情報を見て切り替わります。
具体的には、ルート以下が//#default のとき、default.tagを使用、
/#contentのとき、content.tagを使用します。

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <title>sample</title>

</head>
<body>
  <header></header>
  <main></main>

<!-- 利用するtagファイルを以下のようにして、取り込みます。 -->
  <script type="riot/tag" src="tags/headernav.tag"></script>
  <script type="riot/tag" src="tags/content.tag"></script>
  <script type="riot/tag" src="tags/default.tag"></script>

  <script src="assets/js/libs/riot+compiler.min.js"></script>
  <script src="assets/js/libs/route.min.js"></script>

  <script>
    // SPAのルーティングの設定。ヘッダー部
    route(function (tagName) {
      riot.mount('header', 'headernav');
    });
    // SPAのルーティングの設定。メイン部
    route(function (tagName) {
      tagName = tagName || 'default';
      riot.mount('main', tagName);
    });
    route.start(true);
  </script>
</body>
</html>

default.pug

defaultページのpugファイルのサンプルです。今回、css、jsの参照先は、default.pugから相対座標で指定してます。

default
  style
    include ../../tmp/css/default.css
  h1.test
  a(href="#content") gotoContentPage
  .default_container
    button(onclick="{sayHello}") Hello
  script
    include ../../tmp/js/default.js

css、jsのinclude先を変えるだけで、過去の負の遺産を封印したり、新しいことを試したときに、実験コードに入れ替えができます。

これだけで、新しいことを試したい欲求。汚いコードの除去の両方達成

webpackだと、loaderに引っかかったり、ファイルの退避が必要になってしまうこともあります。


content.pug

defaultページにあるリンクの遷移先のファイルです。
content.csscontent.jsは省略します。

content
  style
    include ../../tmp/css/content.css
  h1.test
  a(href="#") goBackDefaultPage
    include ../../tmp/js/content.js

default.css

dafault.pugで使用するcss

.test{
  color:red;
}
.default_container{
  width:100%;
  padding-top:25px;
}
.default_container>button{
  width:200px;
  height:40px;
}

default.js

default.pugで使用するJS

// this. で書くのはriotのお作法。
this.sayHello=function(){
  alert("Hello");
}

おわりに

Pugの使い方を見て、webpackで良くないか?ReactやAngular、Vueで良いのでは?と思う人もいると思います。筆者もこれを考え始めた当初、その線で考えていました。
しかし、今回、ターゲットとしたのが、普段Webアプリをやってない人ということで、デバッグさせるとき、webpack使わせるのも酷なのと(ソースマップがあればよいが)、筆者がgulpならまだマシ(人間が把握しきれる)という主観の元、この構成にしました。

別の狙いとして、browser-syncを使ったWebアプリの開発速度に毒したかったというのがあります。
riotについては、今回のパターンに都合がよかったのと、単に使ってみたい欲にかられました。

反省点
  • 実はけっこうガチなのを作ってありますが、自部署の製品向けに作りこみ過ぎてしまって、この記事を書くときに、プロジェクトを作り直しました。
  • もっとぶっ飛んだ記事を書きたい。JavaScriptで~~をやってみたとか。(それやる意味あった?と突っ込みがあるぐらいの)
10
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5