Webpack4でes6/sassをcompile

webpack4でcssをsassにes6をes5にcompileさせる

## 処理内容

- es6の記述をbabelでes5に変換
- polyfillでasync/await対応
- sassファイルをcssに変換
- postcssのautoprefixでprefixを作成
- css、jsファイルをbuildでminify
- imgファイルを圧縮
- eslint導入
- devServerでlocal作業
- jQueryを一応入れてます

## ディレクトリ構成

```
├── babel.config.js
├── dist
├── package.json
├── src
│   ├── img
│   ├── js
│   └── sass
└── webpack.config.js
```

## バージョン

- webpack ^4.17.2
- yarn 1.9.4
- node 10.5.0

## package.json

``` json
{
  "name": "hoge",
  "version": "1.0.0",
  "description": "",
  "main": "src/js/app.js",
  "scripts": {
    "start": "webpack-dev-server",
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "UNLICENSED",
  "dependencies": {
    "jquery": "^3.3.1"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/polyfill": "^7.4.4",
    "@babel/preset-env": "^7.0.0",
    "autoprefixer": "^9.1.5",
    "babel-loader": "^8.0.2",
    "copy-webpack-plugin": "^4.6.0",
    "core-js": "^3.0.1",
    "css-loader": "^1.0.0",
    "eslint": "^5.5.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jsx-a11y": "^6.1.1",
    "eslint-plugin-react": "^7.11.1",
    "file-loader": "^2.0.0",
    "imagemin-webpack-plugin": "^2.3.0",
    "mini-css-extract-plugin": "^0.4.2",
    "node-sass": "^4.9.3",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.0",
    "uglifyjs-webpack-plugin": "^2.1.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.17.2",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.7"
  },
  "eslintConfig": {
    "extends": "airbnb",
    "env": {
      "browser": true,
      "node": true
    }
  }
}
```

## webpack.config.js

``` javascript
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const AutoPrefixer = require('autoprefixer');

module.exports = [
  {
    entry: {
      app: [
        './src/js/app.js',
        './src/sass/style.scss',
      ],
    },
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'js/[name].js',
      publicPath: '/',
    },
    devServer: {
      contentBase: './dist',
      watchContentBase: true,
      port: 3000,
      open: true,
    },
    module: {
      rules: [
        {
          test: /\.js?$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
        },
        {
          test: /\.scss$/,
          use: [{
            loader: MiniCssExtractPlugin.loader,
          }, {
            loader: 'css-loader',
          }, {
            loader: 'postcss-loader',
            options: {
              plugins: [
                AutoPrefixer(
                  {
                    browsers: ['last 2 versions', 'Android >= 4'],
                  },
                ),
              ],
            },
          }, {
            loader: 'sass-loader',
          }],
        },
        {
          test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
          use: [
            {
              loader: 'url-loader?limit=100000&name=img/[name].[ext]',
            },
          ],
        },
      ],
    },
    optimization: {
      minimizer: [
        new OptimizeCSSAssetsPlugin(),
        new UglifyJsPlugin(),
      ],
    },
    resolve: {
      extensions: ['.js'],
    },
    plugins: [
      new CopyWebpackPlugin([
        {
          from: path.resolve(__dirname, 'src/img/'),
          to: path.resolve(__dirname, 'dist/img/'),
        },
      ]),
      new MiniCssExtractPlugin({
        filename: 'css/style.css',
      }),
      new ImageminPlugin({
        test: /\.(jpe?g|png|gif|svg)$/i,
        pngquant: {
          quality: '95-100',
        },
      }),
    ],
  },
];
```

``` javascript:babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: 'usage',
        corejs: '3',
        targets: {
          browsers: ['last 2 versions', '> 3% in JP'],
        },
      },
    ],
  ],
};
```

## ハマったところ

Webpack4のアップデートでbabelもそれに対応させなければならず。どのpackageをinstallしていいのか分からなかったが、[こちらのサイト](https://www.valentinog.com/blog/webpack-tutorial/)を参考に処理。

```
webpack 4.x | babel-loader 8.x | babel 7.x
npm install -D babel-loader @babel/core @babel/preset-env webpack
```

## 参考サイト

- [Webpack 4 Tutorial: from 0 Conf to Production Mode](https://www.valentinog.com/blog/webpack-tutorial/)
- [babel-loader](https://www.npmjs.com/package/babel-loader)