webpack.config.js

Download
javascript 188 lines 5.6 KB
  1/**
  2 * Webpack ์„ค์ • ํŒŒ์ผ
  3 * https://webpack.js.org/configuration/
  4 */
  5
  6const path = require('path');
  7const HtmlWebpackPlugin = require('html-webpack-plugin');
  8const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  9
 10module.exports = (env, argv) => {
 11    const isProduction = argv.mode === 'production';
 12
 13    return {
 14        // ์ง„์ž…์ 
 15        entry: {
 16            main: './src/index.js',
 17            // ๋‹ค์ค‘ ์ง„์ž…์  ์˜ˆ์‹œ
 18            // vendor: './src/vendor.js',
 19        },
 20
 21        // ์ถœ๋ ฅ ์„ค์ •
 22        output: {
 23            path: path.resolve(__dirname, 'dist'),
 24            filename: isProduction ? '[name].[contenthash].js' : '[name].js',
 25            chunkFilename: isProduction ? '[name].[contenthash].chunk.js' : '[name].chunk.js',
 26            clean: true,  // ๋นŒ๋“œ ์ „ dist ํด๋” ์ •๋ฆฌ
 27            publicPath: '/',
 28        },
 29
 30        // ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์„ค์ •
 31        devServer: {
 32            static: {
 33                directory: path.join(__dirname, 'public'),
 34            },
 35            port: 3000,
 36            open: true,
 37            hot: true,  // HMR ํ™œ์„ฑํ™”
 38            historyApiFallback: true,  // SPA ๋ผ์šฐํŒ… ์ง€์›
 39            compress: true,
 40            // ํ”„๋ก์‹œ ์„ค์ •
 41            // proxy: {
 42            //     '/api': {
 43            //         target: 'http://localhost:8080',
 44            //         changeOrigin: true,
 45            //     }
 46            // }
 47        },
 48
 49        // ๋ชจ๋“ˆ ๋กœ๋” ์„ค์ •
 50        module: {
 51            rules: [
 52                // JavaScript/JSX ์ฒ˜๋ฆฌ
 53                {
 54                    test: /\.js$/,
 55                    exclude: /node_modules/,
 56                    use: {
 57                        loader: 'babel-loader',
 58                        options: {
 59                            presets: ['@babel/preset-env'],
 60                            cacheDirectory: true,
 61                        }
 62                    }
 63                },
 64
 65                // CSS ์ฒ˜๋ฆฌ
 66                {
 67                    test: /\.css$/,
 68                    use: [
 69                        isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
 70                        {
 71                            loader: 'css-loader',
 72                            options: {
 73                                sourceMap: !isProduction,
 74                            }
 75                        }
 76                    ]
 77                },
 78
 79                // ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ (asset modules)
 80                {
 81                    test: /\.(png|jpe?g|gif|svg|webp)$/i,
 82                    type: 'asset',
 83                    parser: {
 84                        dataUrlCondition: {
 85                            maxSize: 8 * 1024, // 8KB ์ดํ•˜๋Š” ์ธ๋ผ์ธ
 86                        }
 87                    },
 88                    generator: {
 89                        filename: 'images/[name].[hash:8][ext]'
 90                    }
 91                },
 92
 93                // ํฐํŠธ ์ฒ˜๋ฆฌ
 94                {
 95                    test: /\.(woff|woff2|eot|ttf|otf)$/i,
 96                    type: 'asset/resource',
 97                    generator: {
 98                        filename: 'fonts/[name].[hash:8][ext]'
 99                    }
100                }
101            ]
102        },
103
104        // ํ”Œ๋Ÿฌ๊ทธ์ธ
105        plugins: [
106            // HTML ํ…œํ”Œ๋ฆฟ ์ฒ˜๋ฆฌ
107            new HtmlWebpackPlugin({
108                template: './src/index.html',
109                filename: 'index.html',
110                inject: 'body',
111                minify: isProduction ? {
112                    removeComments: true,
113                    collapseWhitespace: true,
114                    removeAttributeQuotes: true,
115                } : false,
116            }),
117
118            // CSS ์ถ”์ถœ (ํ”„๋กœ๋•์…˜)
119            ...(isProduction ? [
120                new MiniCssExtractPlugin({
121                    filename: 'css/[name].[contenthash].css',
122                    chunkFilename: 'css/[name].[contenthash].chunk.css',
123                })
124            ] : []),
125        ],
126
127        // ๊ฒฝ๋กœ ๋ณ„์นญ
128        resolve: {
129            extensions: ['.js', '.json'],
130            alias: {
131                '@': path.resolve(__dirname, 'src'),
132                '@components': path.resolve(__dirname, 'src/components'),
133                '@utils': path.resolve(__dirname, 'src/utils'),
134                '@styles': path.resolve(__dirname, 'src/styles'),
135            }
136        },
137
138        // ์ตœ์ ํ™”
139        optimization: {
140            // ์ฝ”๋“œ ๋ถ„ํ• 
141            splitChunks: {
142                chunks: 'all',
143                cacheGroups: {
144                    // ๋ฒค๋” ๋ฒˆ๋“ค ๋ถ„๋ฆฌ
145                    vendors: {
146                        test: /[\\/]node_modules[\\/]/,
147                        name: 'vendors',
148                        priority: -10,
149                    },
150                    // ๊ณตํ†ต ๋ชจ๋“ˆ ๋ถ„๋ฆฌ
151                    common: {
152                        minChunks: 2,
153                        priority: -20,
154                        reuseExistingChunk: true,
155                    }
156                }
157            },
158            // ๋Ÿฐํƒ€์ž„ ์ฒญํฌ ๋ถ„๋ฆฌ
159            runtimeChunk: 'single',
160        },
161
162        // ์†Œ์Šค๋งต
163        devtool: isProduction ? 'source-map' : 'eval-source-map',
164
165        // ์„ฑ๋Šฅ ํžŒํŠธ
166        performance: {
167            hints: isProduction ? 'warning' : false,
168            maxEntrypointSize: 250000,  // 250KB
169            maxAssetSize: 250000,
170        },
171
172        // ์บ์‹œ ์„ค์ •
173        cache: {
174            type: 'filesystem',
175            buildDependencies: {
176                config: [__filename],
177            }
178        },
179
180        // ํ†ต๊ณ„ ์ถœ๋ ฅ ์„ค์ •
181        stats: {
182            colors: true,
183            modules: false,
184            children: false,
185        }
186    };
187};