Webpackで行っていることを順番に試して、webpack-dev-serverで確認したメモ

# webpack4 実験場

webpackと組み合わせて使われているツールをひとつひとつ順番に試してみた。
webpackは、最後にjsとcssをまとめることと、
webpack-dev-serverを使ってhot loadを試すところで使用。

## 環境

* virtualbox 5.2.22
* vagrant 2.2.1
* ubuntu-18.04
* Docker version 18.09.0, build 4d60db4
* docker-compose version 1.23.1, build b02f1306

### bashまとめ
|コマンド|ソース|出力|
|:--|:--|:--|
|bin/up.sh|src|ブラウザで確認|
|bin/pug/build.sh|src/templates|dist/html|
|bin/ts/build.sh|src/assets/js|pre-dist/assets/js|
|bin/elm/build.sh|src/assets/elm|pre-dist/assets/elm|
|bin/js/build.sh|pre-dist/assets/js, pre-dist/assets/elm|dist/assets/js|
|bin/scss/build.sh|src/assets/css|pre-dist/assets/css|
|bin/postcss/build.sh|pre-dist/assets/css|dist/assets/css|
|bin/webpack/build.sh|dist|app|

## docker

```yaml:docker/docker-compose.yml
version: '3'
services:
  # ビルドツール
  webpack:
    build: ./webpack
    volumes:
      - ./config/webpack/.babelrc:/app/.babelrc
      - ./config/webpack/elm.json:/app/elm.json
      - ./config/webpack/tsconfig.json:/app/tsconfig.json
      - ./config/webpack/webpack.config.js:/app/webpack.config.js
      - ../src/:/app/src
      - ../app/public:/app/dist
      - ../bkup:/bkup
      - ../dist/html:/app/html
    environment:
      - NODE_ENV=develop
    command: [yarn, start, --config, ./webpack.config.js]
    ports:
      - 3000:3000
      - 3002:3002
  # htmlテンプレートエンジン
  pug:
    build: ./pug
    volumes:
      - ../src/templates:/app/src
      # - ../app/public:/app/dist
      - ../dist/html:/app/dist
    environment:
      - SHELL=/bin/bash
    command: [npm, run, watch]
  # デプロイツール
  firebase:
    build: ./firebase
    env_file: .env
    volumes:
      - ../app/public:/app/public
      - ../app/.firebaserc:/app/.firebaserc
      - ../app/firebase.json:/app/firebase.json
    ports:
      - 5000:5000
      - 9005:9005
```

```docker:docker/webpacks/Dockerfile
FROM node:11.2.0

# コンテナ上の作業ディレクトリ作成
WORKDIR /app

# 後で確認出来るようにpackage.jsonを作成
RUN npm init -y

## for js
### babel
RUN yarn add --dev @babel/core \
                  @babel/cli \
                  @babel/preset-env
RUN yarn add @babel/polyfill

### lint
RUN yarn add --dev eslint \
                   eslint-plugin-import \
                   eslint-config-airbnb-base \
                   eslint-plugin-jasmine

### esdoc
RUN yarn add --dev esdoc esdoc-standard-plugin

## for ts
RUN yarn add --dev typescript
RUN yarn add --dev tslint tslint-config-airbnb
RUN yarn add --dev typedoc 

## for css
### sass
RUN yarn add --dev node-sass

### postcss
RUN yarn add --dev postcss postcss-cli
RUN yarn add --dev autoprefixer

### lint
RUN yarn add --dev stylelint 
RUN yarn add --dev stylelint-scss
RUN yarn add --dev stylelint-order
RUN yarn add --dev stylelint-config-sass-guidelines

## elm

RUN yarn add --dev elm
RUN yarn add --dev elm-format
### elm minify
RUN yarn add --dev uglify-js
RUN npm i -g uglify-js

## webpackインストール
RUN yarn add --dev webpack
RUN yarn add --dev webpack-cli
RUN yarn add --dev webpack-merge
RUN yarn add --dev webpack-dev-server

## plugin
RUN yarn add --dev mini-css-extract-plugin
RUN yarn add --dev html-minifier-webpack-plugin
RUN yarn add --dev clean-webpack-plugin
RUN yarn add --dev copy-webpack-plugin

### loaders
RUN yarn add --dev babel-loader
RUN yarn add --dev file-loader
RUN yarn add --dev style-loader
RUN yarn add --dev css-loader
RUN yarn add -D html-loader

## pug
RUN yarn add --dev pug
RUN yarn add --dev pug-cli#master
RUN yarn add --dev https://github.com/pugjs/pug-cli.git

## watch
RUN yarn add --dev chokidar
RUN yarn add --dev chokidar-cli

## script
### elm
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"build-elm\": \"yarn run elm make \/app\/src\/assets\/elm\/ElmTest.elm --output=\/app\/dist\/elm\/ElmTest.js\",/g" /app/package.json
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"elm-watch\": \"yarn run chokidar '\/app\/**\/*.elm' -p -c 'yarn run build-elm' \",/g" /app/package.json

### pug
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"pug\": \"pug -o \/app\/dist -P \",/g" /app/package.json
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"build-pug\": \"pug \/app\/src -o \/app\/dist \",/g" /app/package.json
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"watch\": \"chokidar '\/app\/**\/*.pug' -p -c 'npm run build-pug' \",/g" /app/package.json
```

## package.json

```json
{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch": "chokidar '/app/**/*.pug' -p -c 'npm run build-pug' ",
    "build-pug": "pug /app/src -o /app/dist ",
    "pug": "pug -o /app/dist -P ",
    "elm-watch": "yarn run chokidar '/app/**/*.elm' -p -c 'yarn run build-elm' ",
    "build-elm": "yarn run elm make /app/src/assets/elm/ElmTest.elm --output=/app/dist/elm/ElmTest.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.1.5",
    "@babel/core": "^7.1.6",
    "@babel/preset-env": "^7.1.6",
    "autoprefixer": "^9.3.1",
    "babel-loader": "^8.0.4",
    "chokidar": "^2.0.4",
    "chokidar-cli": "^1.2.1",
    "clean-webpack-plugin": "^1.0.0",
    "copy-webpack-plugin": "^4.6.0",
    "css-loader": "^1.0.1",
    "elm": "^0.19.0-bugfix2",
    "elm-format": "^0.8.1",
    "esdoc": "^1.1.0",
    "esdoc-standard-plugin": "^1.0.0",
    "eslint": "^5.9.0",
    "eslint-config-airbnb-base": "^13.1.0",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jasmine": "^2.10.1",
    "file-loader": "^2.0.0",
    "html-loader": "^0.5.5",
    "html-minifier-webpack-plugin": "^2.0.0",
    "mini-css-extract-plugin": "^0.4.5",
    "node-sass": "^4.10.0",
    "postcss": "^7.0.6",
    "postcss-cli": "^6.0.1",
    "pug": "^2.0.3",
    "pug-cli": "https://github.com/pugjs/pug-cli.git",
    "style-loader": "^0.23.1",
    "stylelint": "^9.8.0",
    "stylelint-config-sass-guidelines": "^5.2.0",
    "stylelint-order": "^1.0.0",
    "stylelint-scss": "^3.4.0",
    "tslint": "^5.11.0",
    "tslint-config-airbnb": "^5.11.1",
    "typedoc": "^0.13.0",
    "typescript": "^3.1.6",
    "uglify-js": "^3.4.9",
    "webpack": "^4.26.0",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.10",
    "webpack-merge": "^4.1.4"
  },
  "dependencies": {
    "@babel/polyfill": "^7.0.0"
  }
}
```

## pug

htmlのテンプレートエンジン

[この時点のソース](https://github.com/hibohiboo/develop/tree/b52da33ee917a226673ce01629acc242241542e0/tutorial/lesson/webpack/webpack4)  

## js

### babel

jsのトランスパイラ

#### IE対応

[この時点のソース](https://github.com/hibohiboo/develop/tree/d18e14389602e71f79591832968e0a0722f3db80/tutorial/lesson/webpack/webpack4)  


#### chromeのみ

[この時点のソース](https://github.com/hibohiboo/develop/tree/192a01c5e15395a25d422d8105db7ebc0284e208/tutorial/lesson/webpack/webpack4)  


[参考](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)
[参考：builtins](https://babeljs.io/docs/en/babel-preset-env)

### lint

eslintのairbnbを追加

[この時点のソース](https://github.com/hibohiboo/develop/tree/bd5f0809a4f0ea034a3363ba4570c23d43a1d631/tutorial/lesson/webpack/webpack4)  

## docs

esdocを追加

[この時点のソース](https://github.com/hibohiboo/develop/tree/d2e7e06489f5e52e22ce8d73b87f6912a8f76509/tutorial/lesson/webpack/webpack4)  

## typescript

[参考：ts3](https://qiita.com/vvakame/items/57a0559c45b88b2ae168)


[この時点のソース](https://github.com/hibohiboo/develop/tree/0e31ac98b46a044bfa0150089c91ccf6539299b8/tutorial/lesson/webpack/webpack4)  

### elmとtypescriptをつなぐ

```ts:src/assets/elm/ElmTest.d.ts
/**
 * Elmの引数
 */
interface ElmInitArgs {
  node: HTMLElement;
  flags?: any;
}

declare namespace ElmTest.Elm {
  /**
   * メイン
   */
  class Main{
    /**
     * 
     * @param args 
     */
    public static init(args:ElmInitArgs): any;
  }
}
export = ElmTest;
```

### lint

* air-bnb-tsingtのduplicateのtypeCheckがrequireとwarningが出るのでfalseにする。
  * strict-boolean-expressions
  * no-boolean-literal-compare
[この時点のソース](https://github.com/hibohiboo/develop/tree/c350a05ad5cef36fdad93817d26bfc3a1263658e/tutorial/lesson/webpack/webpack4)  

## css

### sass
[この時点のソース](https://github.com/hibohiboo/develop/tree/b015d5d66d3c0e1f4b02970687bcfec987852ba9/tutorial/lesson/webpack/webpack4)  

[node-sassでSassファイルをコンパイルする](https://qiita.com/setouchi/items/2f7ae68764abe74934fb)
[超絶・超速のNODE-SASSでSASSコンパイルのすすめ](https://its-office.jp/blog/sass/2018/05/12/node-sass.html)

### postcss

`bin/postcss/autoprefix.sh` : sassから出力されたdist/css/*.cssを置き換える。

[この時点のソース](https://github.com/hibohiboo/develop/tree/b1a0cd64eb5f5041bac8e6ba421ba4809b24e23f/tutorial/lesson/webpack/webpack4)  

[PostCSS まとめ](https://qiita.com/morishitter/items/4a04eb144abf49f41d7d)

#### postcss.config.json の使用

[この時点のソース](https://github.com/hibohiboo/develop/tree/6a649b5f23756333a2e6b8b3b0f6351c636e455a/tutorial/lesson/webpack/webpack4)  

* ついでにminifyも行う

[postcss](https://github.com/postcss/postcss#usage)
[css nano](https://cssnano.co/guides/getting-started)
[cssnanoを通したらベンダープレフィックスが消えて困った時のメモ](https://qiita.com/syannu/items/3f04f0e962df42cf25f7)

### sass-lint
情報が少ない。。

[sass](https://stackoverflow.com/questions/39307087/how-i-should-check-indentation-in-sass-file-with-stylelint)
[sass-lint](https://morizyun.github.io/javascript/node-js-npm-library-sass-lint.html)
[sass-lintのエラールールを日本語で分かるようにした](https://qiita.com/nezurika/items/4cc858ee9ebd6154dd44)

### stylelint

sass記法は対応していなさそう。
sassにこだわりがあるわけではないので、scss記法に直した。

[この時点のソース](https://github.com/hibohiboo/develop/tree/c750f3a4d1ce521851c2d5ad6bef02b9f6d37606/tutorial/lesson/webpack/webpack4)  


[npmのみでSassのstylelint 〜webpackとPostCSS不要編〜](https://qiita.com/pprhr/items/b61f84944e1e869161cc)
[チームで美しくメンテナブルなCSSを書くための 「Stylelint」導入のすすめ](https://www.webprofessional.jp/taking-css-linting-next-level-stylelint/)
[stylelintのorderモジュール選定](https://qiita.com/nabepon/items/4168eae542861cfd69f7)
[実務でstylelintを導入して3ヶ月ぐらいたった感想](https://qiita.com/DesignChips/items/309a8cce0d744f2dfef6)
[stylelintとBackstopJSで安全にcssを書ける環境を作った](https://devblog.thebase.in/entry/2018/06/06/110000)

## elm

最初のHTML表示時点でのソース

[この時点のソース](https://github.com/hibohiboo/develop/tree/7e83836e5b0616363f1e53f6a6d9b9d69947be33/tutorial/lesson/webpack/webpack4)  
[elm ドキュメント 日本語版](https://guide.elm-lang.jp/)

### optimized調査

100kb -> 15kb まで圧縮

[この時点のソース](https://github.com/hibohiboo/develop/tree/7e83836e5b0616363f1e53f6a6d9b9d69947be33/tutorial/lesson/webpack/webpack4)  

[How to optimize Elm code](https://elm-lang.org/0.19.0/optimize)

## webpack

[[webpack]尖りすぎない人のwebpack設定 ](http://www.kantenna.com/pg/2018/05/webpack_scss.php)

[[webpack]CSS LoaderでCSSの圧縮してる人は最新版でminimizeオプションが削除されてるから気をつけて。](http://www.kantenna.com/pg/2018/09/webpack_css-loader.php)

### css-loaderとstyle-loaderの違い

* Style-Loaderの仕事はSTYLEタグの出力
* CSS-LoaderがCSSファイル間の依存関係の解決を行う
[WebpackってCSS周りのLoaderがいっぱいあって分かりにくいので整理してみる](https://qiita.com/shuntksh/items/bb5cbea40a343e2e791a) 
[なんとなくで理解しないWebpackのCSS周辺](https://qiita.com/terrierscript/items/0574ab1ef358fecb55b9)

### mini-css plugin

* jsファイルに import '../css/style.css'; のように書き込んだものをcssファイルとして出力する。

[この時点のソース](https://github.com/hibohiboo/develop/tree/b1040ae4b45360e9f2110502a233ca0540091108/tutorial/lesson/webpack/webpack-separate)  
[webpack@4 でCSSを抽出する際は mini-css-extract-plugin を使う](https://numb86-tech.hatenablog.com/entry/2018/10/24/221130)

### cssもcopyfileでまかなう

* postcssでminifyを行ったので、webpackで行う必要はない、、？

[gulp.distをCopyWebpackPluginで再現する](https://qiita.com/pepoipod/items/e41105e8f3afd47dc01c)
[この時点のソース](https://github.com/hibohiboo/develop/tree/1a74a60c17606e1a2e821691204b3f7cf809d699/tutorial/lesson/webpack/webpack-separate)

### webpack-dev-serverのhotloadでcssも賄いたい欲

* hotloadは便利。


## webpack-dev-server

* --hotオプションをつけるか、webpack.config.jsにwebpack.HotModuleReplacementPluginが必要
[devServer.hot ](https://webpack.js.org/configuration/dev-server/#devserver-hot)

### watchに対応

* `bin/up.sh`で起動したときに、watchコマンドを実行するようにしている

[この時点のソース](https://github.com/hibohiboo/develop/tree/a6918716a40be3f6d4b03bb8a77f2a94691e4aba/tutorial/lesson/webpack/webpack-separate)