개발 이야기/Webpack

Webpack 설정 파일 예시

석구석구 2020. 2. 17. 20:06

회사에서 진행 중인 프로젝트에 쓰고 있는 웹팩 설정 파일이다.

 

웹팩 설정을 하기 위해 처음에는 오랜 시간이 걸렸는데, 이제는 눈 감고도 뚝딱할 정도가 되었다.

 

누군가에게 조금이라도 도움이 되길 바라면서 올린다.

 

// webpack.common.js
// 웹팩 설정 파일 - 공통

const path = require('path');
const webpack = require('webpack');
const I18nPlugin = require('i18n-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { version } = require('./package.json');

// 다국어 처리
const languages = {
  ja: require('./src/language/ja.json'),
  ko: require('./src/language/ko.json'),
};

// 컴파일 선택 언어
const COMPILE_LANGUAGE = 'ko';

// 외부 리소스 서버
const ASSET_PATH = 'https://sandbox-mk.kakaocdn.net/dn/';

// 웹팩 설정
module.exports = {
  output: {
    path: `${__dirname}/build`,
    filename: `bundle.${version}.js`,
    chunkFilename: `chunks/[name].${version}.chunks.js`,
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: 'fonts/',
            },
          },
        ],
      },
      {
        test: /\.(png|jp(e*)g|svg|gif)$/,
        loader: 'url-loader',
        options: {
          outputPath: 'images/',
          name: '[hash]-[name].[ext]',
          limit: 3000,
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(), // 폴더 클린
    new HtmlWebpackPlugin({
      // 기본 확장 템플릿
      template: 'public/index.html',
    }),

    new I18nPlugin(languages.ko, {
      // 다국어 설정
      nested: true,
    }),
    new webpack.EnvironmentPlugin({
      COMPILE_LANGUAGE,
      ASSET_PATH,
    }),
  ],
  resolve: {
    extensions: ['.jsx', '.ts', '.tsx', '.js'],
    alias: {
      '@': path.resolve(__dirname, 'src/'),
      '@Route': path.resolve(__dirname, 'src/route/'),
      '@Pages': path.resolve(__dirname, 'src/pages/'),
      '@Modules': path.resolve(__dirname, 'src/store/modules/'),
      '@Components': path.resolve(__dirname, 'src/components/'),
      '@Style': path.resolve(__dirname, 'public/scss/'),
      '@Public': path.resolve(__dirname, 'public/'),
      '@Config': path.resolve(__dirname, 'src/config/'),
      '@Json': path.resolve(__dirname, 'src/json/'),
      '@Stores': path.resolve(__dirname, 'src/store_mobx/stores/'),
    },
  },
};

 

// webpack.config.development.js
// 웹팩 설정 파일 - 개발용
const path = require('path');

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
  entry: {
    app: ['./src/entry'],
  },
  module: {
    rules: [
      {
        test: /\.(js|ts|tsx)$/,
        include: /(src)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              configFile: path.resolve('babel.config.js'),
            },
          },
          {
            loader: 'ts-loader',
          },
        ],
      },
      {
        test: /\.(sa|sc|c)ss$/,
        include: /(src|public)/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
    ],
  },
  devtool: 'inline-source-map',
});

 

//  webpack.config.production.js
// 웹팩 설정 파일 - 배포용

const path = require('path');
const AsyncChunkNames = require('webpack-async-chunk-names-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  entry: {
    app: ['core-js', './src/entry'],
  },
  module: {
    rules: [
      {
        test: /\.(js)$/,
        include: /(src|node_modules)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              configFile: path.resolve('babel.config.js'),
            },
          },
        ],
      },
      {
        test: /\.(ts|tsx)$/,
        include: /(src)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              configFile: path.resolve('babel.config.js'),
            },
          },
          {
            loader: 'ts-loader',
          },
        ],
      },
      {
        test: /\.(sa|sc|c)ss$/,
        include: /(src|public)/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: () => [require('autoprefixer')()],
            },
          },
          'sass-loader',
        ],
      },
    ],
  },
  plugins: [
    new AsyncChunkNames(), // 스플릿 네임 관리
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
  optimization: {
    minimizer: [
      new TerserPlugin({
        cache: true,
        parallel: true,
        sourceMap: false,
      }),
      new OptimizeCSSAssetsPlugin(),
    ],
  },
});