フロントエンドリソースを、HTMLで管理する設計

## まず、リソースコンパイルについて
最近、フロントエンドのリソースを開発する上で、様々なコンパイラを使用することが増えている気がします。
具体的には、
<dl>
  <dt>JS・JSX</dt>
  <dd>Browserifyとbabelでモジュール管理・ES6・JSX</dd>
  <dt>CSS</dt>
  <dd>sassやpostcssやらautoprefixerで変換</dd>
  <dt>HTML</dt>
  <dd>テンプレートエンジンで変換</dd>
</dl>
これらをタスクにして、ファイル監視して、タスクランナー走らせて、BrowserSyncして・・・
### これらの問題点（と私が感じるところ）
- Gulp等のタスクランナーはプラグイン頼みなところがある
- npm scriptsは、コマンドライン環境に影響される
- タスクランナーのタスクのパスを書く部分がやだ
- 監視するパスとかリソースのパスがごっちゃになる(/dev/*.js ⇒ /dev/bundle.js的な)
- タスク監視起動して、Webサーバー起動しての2段階が面倒
- cdnを使った場合、そこまでBundle（一つのファイルにまとめる）できない

## HTMLで管理してみる
とりあえず、図にしてみました
![image](https://qiita-image-store.s3.amazonaws.com/0/169861/49ab912b-1908-e56c-7ea9-7ad79696ce1a.png)

上の図で、「コンパイル処理」って書かれているものが、browserifyやbabelなどの処理で、基本的には、ストリームで読み込んで、吐き出すだけの共通処理を実装すればいいと思っています。
（コマンドラインの標準入出力でもOK）
Webサーバーには、mimeタイプなどで判定してコンパイルする処理を埋め込みます。

リリース時に流す処理は、それとは別で、htmlを読み込ませて、linkタグやscriptタグをもとに、読み込み⇒コンパイル⇒Bundleという風な処理をさせます。
HTMLは、このようになります。

```html:変換前.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <title>タイトル</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://hostname//framework-1.2.3.css" rel="stylesheet">
        <link href="css/1.css" rel="stylesheet">
        <link href="css/2.css" rel="stylesheet">
        <link href="css/3.css" rel="stylesheet">
    </head>
    <body>
        <div id="app"></div>
    
        <script src="https://hostname/framework-1.2.3.js"></script>
        <script src="js/1.js"></script>
        <script src="js/2.js"></script>
        <script src="js/3.js"></script>
    </body>
</html>
```

↓

```html:変換後.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <title>タイトル</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="bundle.css" rel="stylesheet">
    </head>
    <body>
        <div id="app"></div>
    
        <script src="bundle.js"></script>
    </body>
</html>
```

deferやasyncを使う場合を除けば、HTMLは上から順に読み込んでいくだけです。
ならば、linkタグとscriptタグを上から順に読み込み、コンパイル処理をし、bundleするだけで同じ挙動になるはず。（cheerioとか使えば、簡単そう）
cdnなどのリモートファイルもそのまま読み込んで一つにまとめちゃう。

開発時は、ファイルバラバラで、コンパイル処理もさせて、開発用のWebサーバーに負担かかるけど、リリース時に解消しちゃえばいいよねって考え方。

### メリット
- 開発時のコンパイルは、Webサーバーに任せ、タスクランナーは使わなくて済む
- リソースのパスはHTMLで管理できる
- CDNのファイルとかもまとめられる（本番環境は、ネットにつながっていない場合がある）
- コンパイルの処理は、タスクランナーのプラグインでない為、使いまわしやすい

### デメリット
- リリース時には、サーバーサイドのコンパイル処理をはずす必要がある
- リリース時には、ソースマップとかは、はずす必要がある

## 実際にやってみるとしたら
せっかくcheerio使うなら、\<part\>タグなんて読み込めるようにして…
（実装簡単そう）

```html:sample.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <title>タイトル</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="css/1.css" rel="stylesheet" async>
        <link href="css/1.css" rel="stylesheet" defer>
        <link href="https://hostname//framework-1.2.3.css" rel="stylesheet">
        <link href="css/2.css" rel="stylesheet">
        <link href="css/3.css" rel="stylesheet">
    </head>
    <body>
        <part src="part/header.html">
        <div id="app"></div>
        <part src="part/footer.html">
        
        <script src="https://hostname/framework-1.2.3.js"></script>
        <script src="js/1.js"></script>
        <script src="js/2.js"></script>
        <script src="js/3.js"></script>
    </body>
</html>
```

コンパイル処理

```js:compile.js
const compile = require('compile-tool')

let config = {
    // Expressのstaticとかの為に
    prefix: "static/base",
    // コンパイル前のテンプレートエンジンがあれば指定
    templateEngine: function(file, cb) {
        // パスとバッファを格納
        let buffer = file.buffer
        let path = file.path

        this.push(//コンパイル後のBuffer)

        // 最後は、コールバックを呼び出し
        cb()
    },
    // 拡張子ごとのコンパイラを指定（インターフェイスは、templateEngineに渡す関数と同じ）
    compilers: {
        "js": jsCompiler,     // browserify babelify
        "jsx": jsCompiler,    // browserify babelify
        "css": cssCompiler    // postcss autoprefixer
    }
}

// HTMLのパスをglobで指定・configで初期化・outのパスは、config.prefixを指定しない場合のみ有効
compile("./dev/*.html", config).out("./out/")
```

こんな感じですかね～