futu-no

ページトップ

二日費やしてやっぱり使わなかったwebpack.config.js

Web
webpack

最近WebGLを触ることが多いが、「VueやNuxtだと全体のJSをVue向けに変えていかんといけないし面倒だな」→「webpackだけで回せるシンプルなビルドタスクをつくろうか」 という動機で始めたが、webpackも気が付けば4になっており、もはやconfigの読み方もわからないので勉強がてらフルスクラッチで組んでみた。


ただ、やってみると辛さばかり。

  • 単一ページが乱立するレガシーなサイト構成なら、結局今あるGulpfile.jsで十分パワフルに動くし、minify・autoprefixer・Babel・sourceMapsと、ファイル単体への干渉しかないのでプロジェクト構成が自由。webpackでやろうとすると、「まずwebpack作法で癖のある構成に変えられたものを元の形に戻す」大変で虚無感しかないフローを作らないといけない。
  • モジュールバンドラー以外、全て今Gulpでできていることの再発明になってしまう。
  • タスクランナー(正確にはバンドラーと区別されるが)としてのふるまいを制御するコードと、サイト設計を記述するコードが混在するのがなんか嫌。別プロジェクトへのwebpack.config.jsの使いまわしがしづらい。
  • モダンフロント方式で行くにしても、今はVue.jsのボイラーテンプレやNuxt.jsという完成されたプロジェクトがあるので、ここから始めたほうがなにかと早い。環境構築は制作の本質ではないのだ。

というわけでお蔵入り。一応ソースだけここに残しておきます。HTML+SCSS+TypeScriptの解釈ができる程度です。

{
  "name": "webpack",
  "version": "1.0.0",
  "main": "index.js",
  "private": true,
  "scripts": {
    "start": "run-s clean webpack:dev server",
    "dev": "run-s clean webpack:dev server",
    "build": "run-s clean webpack:prod server",
    "clean": "rimraf ./dist/",
    "webpack:dev": "webpack --mode=development --watch",
    "webpack:prod": "webpack --mode=production --watch",
    "server": "webpack-serve"
  },
  "devDependencies": {
    "autoprefixer": "^9.1.1",
    "css-loader": "^1.0.0",
    "file-loader": "^1.1.11",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.4.1",
    "node-sass": "^4.9.3",
    "npm-run-all": "^4.1.3",
    "postcss-loader": "^3.0.0",
    "rimraf": "^2.6.2",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.22.1",
    "ts-loader": "^4.4.2",
    "typescript": "^3.0.1",
    "webpack": "^4.16.5",
    "webpack-cli": "^3.1.0",
    "optimize-css-assets-webpack-plugin": "^5.0.0",
    "webpack-serve": "^2.0.2"
  }
}
const path                    = require('path');
const HtmlWebpackPlugin       = require('html-webpack-plugin');
const MiniCssExtractPlugin    = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = (env, argv) => {

  // モード判定
  const IS_DEVELOPMENT = argv.mode === 'development';

  return {

    // sourceMaps形式
    devtool: 'source-map',

    // ==================
    // エントリーポイント
    // ==================

    entry: './src/index.ts',

    // ============
    // アウトプット
    // ============

    output: {
      path: `${__dirname}/dist`,
      filename: 'main.js',
    },

    // ==========
    // プラグイン
    // ==========

    plugins: [

      // HTMLの書き出し
      new HtmlWebpackPlugin(),

      // CSSの書き出し
      new MiniCssExtractPlugin({
        filename: '[name].css',
        chunkFilename: '[id].css',
      }),

    ],

    // ======
    // 最適化
    // ======

    optimization: {
      minimizer: [
        new OptimizeCSSAssetsPlugin({}),
      ]
    },

    // ============
    // ビルドルール
    // ============

    module: {
      rules: [

        // ===
        // Vue
        // ===

        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: {
            loaders: {
              scss: {
                loader: ['css-loader', 'postcss-loader', 'sass-loader'],
              },
            },
          },
        },

        // =================
        // CSS / SASS / SCSS
        // =================

        {
          test: /\.(sa|sc|c)ss$/,
          use: [
            MiniCssExtractPlugin.loader,

            // css-loader
            {
              loader: 'css-loader',
              options: {
                sourceMap: IS_DEVELOPMENT,
                url: false, // url()メソッドの外部ファイル取り込み

                // 0 => no loaders (default);
                // 1 => postcss-loader;
                // 2 => postcss-loader, sass-loader
                importLoaders: 2,
              },
            },

            // postcss-loader
            {
              loader: 'postcss-loader',
              options: {
                sourceMap: true,
                plugins: [
                  require('autoprefixer')({ grid: true })
                ],
              },
            },

            // sass-loader
            {
              loader: 'sass-loader',
              options: {
                sourceMap: IS_DEVELOPMENT,
              },
            },

          ],
        },

        // ==========
        // TypeScript
        // ==========

        {
          test: /\.ts$/,
          use: 'ts-loader',
          exclude: /node_modules/,
        },

        // ==========
        // img / font
        // ==========

        {
          test: /\.(gif|png|jpg|svg)$/,
          use: [

            // file-loader
            {
              loader: 'file-loader',
              options: {
                name: './img/[name].[ext]',
                limit: 100 * 1024, // 100KB以上の場合は静的ファイルのまま扱う
              },
            },

          ],
        },

        // ====
        // font
        // ====

        {
          test: /\.(eot|wof|woff|woff2|ttf)$/,
          use: [

            // file-loader
            {
              loader: 'file-loader',
              options: {
                name: './font/[name].[ext]'
              },
            },

          ],
        },

      ],
    },

    // ====
    // 解決
    // ====

    resolve: {

      // requireやimport時の拡張子を省略
      extensions: [
        '.ts',
      ],

      alias: {
        vue: 'vue/dist/vue.esm.js', // Webpack + Vueの設定
      },

    },

  }
}
Writer トロサーモン
Date
Categories Web
Tags