3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CoffeeScriptAdvent Calendar 2017

Day 9

webpack.configはCoffeeScriptで書くと幸せになれる

Last updated at Posted at 2017-12-08

「CoffeeScript信者として何か書かねばならぬが、ネタが思い浮かばないぜ。」

皆さん日々、四苦八苦しながらwebpack.configを書いているでしょうか?その四苦八苦、CoffeeScriptを使うと少し楽になりますよ。

webpack.configをCoffeeScriptで使う方法

まずは、coffeescriptをpackageに含めます。

$ yarn add -D coffeescript

あとは拡張子を.coffeeにしてwebpack.config.coffeeとするだけです。偉いぞwebpack!

CoffeeScriptの何が嬉しいか

記述が簡潔になる

CoffeeScriptを使うと記述が簡潔になる気がします。実際に見比べてみてください。

webpack.config.js
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

let loader = {};
loader.coffee = ['babel-loader', 'coffee-loader'];
loader.css = [
  { loader: 'css-loader'    , options: { sourceMap: true } },
  { loader: 'postcss-loader', options: { sourceMap: true } },
  { loader: 'stylus-loader' , options: { sourceMap: true } },
];
loader.stylus = [
  { loader: 'style-loader'  , options: { sourceMap: true } },
  { loader: 'css-loader'    , options: { sourceMap: true } },
  { loader: 'postcss-loader', options: { sourceMap: true } },
  { loader: 'stylus-loader' , options: { sourceMap: true } },
  {
    loader: 'stylus-resources-loader',
    options: {
      resources: [
        path.resolve(__dirname, './src/styles/_variables.styl'),
        path.resolve(__dirname, './src/styles/_mixins.styl')
      ]
    }
  },
];
loader.json = ['json-loader'];

baseConfig = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: ''
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: {
          loader: 'vue-loader',
          options: {
            loaders: {
              coffee: loader.coffee,
              stylus: loader.stylus
            }
          }
        }
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]?[hash]'
            }
          }
        ]
      },
      {
        test: /\.coffee$/,
        use: loader.coffee
      },
      {
        test: /\.css$/,
        use: loader.css
      },
      {
        test: /\.styl$/,
        use: loader.stylus
      },
      {
        test: /\.json$/,
        use: loader.json
      }
    ]
  },
  resolve: {
    alias: {
      '@root':       path.resolve(__dirname),
      '@src':        path.resolve(__dirname, 'src'),
      '@scripts':    path.resolve(__dirname, 'src', 'scripts'),
      '@components': path.resolve(__dirname, 'src', 'components'),
      '@pages':      path.resolve(__dirname, 'src', 'pages'),
      '@assets':     path.resolve(__dirname, 'src', 'assets'),
      '@styles':     path.resolve(__dirname, 'src', 'styles'),
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'src', 'index_template.html')
    }),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: `'${process.env.NODE_ENV}'`
      }
    }),
    new webpack.ProvidePlugin({
      '_': 'lodash',
      'axios': 'axios'
    })
  ]
};

if (process.env.NODE_ENV === 'production') {
  config = merge(baseConfig, {
    output: {
      filename: 'build-[hash].js'
    },
    devtool: '#source-map',
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        compress: {
          warnings: false
        }
      }),
      new webpack.LoaderOptionsPlugin({
        minimize: true
      })
    ]
  });
} else {
  config = merge(baseConfig, {
    output: {
      filename: 'build.js'
    },
    devtool: '#eval-source-map',
    devServer: {
      contentBase: 'dist',
      historyApiFallback: true,
      noInfo: true
    },
    performance: {
      hints: false
    }
  });
}

module.exports = config;
webpack.config.coffee
path = require('path')
webpack = require('webpack')
merge = require('webpack-merge')
HtmlWebpackPlugin = require('html-webpack-plugin')
CleanWebpackPlugin = require('clean-webpack-plugin')

loader = {}
loader.coffee = ['babel-loader', 'coffee-loader']
loader.css    = [
  { loader: 'css-loader'    , options: sourceMap: true }
  { loader: 'postcss-loader', options: sourceMap: true }
  { loader: 'stylus-loader' , options: sourceMap: true }
]
loader.stylus = [
  { loader: 'style-loader'  , options: sourceMap: true }
  { loader: 'css-loader'    , options: sourceMap: true }
  { loader: 'postcss-loader', options: sourceMap: true }
  { loader: 'stylus-loader' , options: sourceMap: true }
  {
    loader: 'stylus-resources-loader'
    options:
      resources: [
        path.resolve(__dirname, './src/styles/_variables.styl')
        path.resolve(__dirname, './src/styles/_mixins.styl')
      ]
  }
]
loader.json = ['json-loader']

baseConfig =
  entry: './src/main.js'
  output:
    path: path.resolve(__dirname, './dist')
    publicPath: ''
  module:
    rules: [
      test: /\.vue$/
      use:
        loader: 'vue-loader'
        options:
          loaders:
            coffee: loader.coffee
            stylus: loader.stylus
    ,
      test: /\.(png|jpg|gif|svg)$/
      use: [
        loader: 'file-loader'
        options:
          name: '[name].[ext]?[hash]'
      ]
    ,
      test: /\.coffee$/
      use: loader.coffee
    ,
      test: /\.css$/
      use: loader.css
    ,
      test: /\.styl$/
      use: loader.stylus
    ,
      test: /\.json$/
      use: loader.json
    ]
  resolve:
    alias:
      '@root':       path.resolve(__dirname)
      '@src':        path.resolve(__dirname, 'src')
      '@scripts':    path.resolve(__dirname, 'src', 'scripts')
      '@components': path.resolve(__dirname, 'src', 'components')
      '@pages':      path.resolve(__dirname, 'src', 'pages')
      '@assets':     path.resolve(__dirname, 'src', 'assets')
      '@styles':     path.resolve(__dirname, 'src', 'styles')
      'vue$': 'vue/dist/vue.esm.js'
  plugins: [
    new HtmlWebpackPlugin
      template: path.resolve(__dirname, 'src', 'index_template.html')
    new webpack.DefinePlugin
      'process.env':
        NODE_ENV: "'#{process.env.NODE_ENV}'"
    new webpack.ProvidePlugin
      '_': 'lodash'
      'axios': 'axios'
  ]

if process.env.NODE_ENV == 'production'
  config = merge baseConfig,
    output:
      filename: 'build-[hash].js'
    devtool: '#source-map'
    plugins: [
      new CleanWebpackPlugin(['dist'])
      new webpack.optimize.UglifyJsPlugin
        sourceMap: true
        compress:
          warnings: false
      new webpack.LoaderOptionsPlugin
        minimize: true
    ]
else
  config = merge baseConfig,
    output:
      filename: 'build.js'
    devtool: '#eval-source-map'
    devServer:
      contentBase: 'dist'
      historyApiFallback: true
      noInfo: true
    performance:
      hints: false

module.exports = config

どうでしょうか?webpack.config.coffeeのほうが余計なブレースやカンマがなくなり、スッキリした見た目になっていると思いませんか?そうでもないですか?

まぁ、分かる人にだけわかってもらえれば結構。

試行錯誤しやすい

webpack.configを試行錯誤しながら編集することはままあります。そんなときjsだと結構いらいらさせられます。

webpack.config.js
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        compress: {
          warnings: false
        }
      }),
      new webpack.LoaderOptionsPlugin({
        minimize: true
      })
+     new CleanWebpackPlugin(['dist']) // pluginを足してみて動きを確かめたい。
    ]

このweboack.config.jsはシンタックスエラーになります。追加した行の手前にカンマがないからです。憎い!

CoffeeScriptならこのようなイライラとは無縁です。

webpack.config.coffee
    plugins: [
      new webpack.optimize.UglifyJsPlugin
        sourceMap: true
        compress:
          warnings: false
-     new webpack.LoaderOptionsPlugin # 削除も
-       minimize: true
+     new CleanWebpackPlugin(['dist']) # 追加も自由自在!
    ]

まとめ

どうですか?CoffeeScriptが使ってみたくなりましたか?なりませんか?そうですか。残念です・・・。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?