npm i -D webpack webpack-cli webpack-dev-server
open: 서버가 시작될 때 default 브라우저 창을 자동으로 띄워줌
historyApiFallback : History API 또는 react-router 등을 사용하는 경우 새로고침 시 404 에러를 해결해줌
client의 overlay 옵션 : 컴파일러 오류 또는 경고가 있는 경우 브라우저에 전체 화면 오버레이를 표시해줌
module.exports = {
...
devServer: {
open: true,
historyApiFallback: true,
static: {
directory: path.join(__dirname, 'public'),
},
hot: true,
client: {
overlay: {
errors: true,
warnings: false,
},
},
},
}
npm i -D @pmmmwh/react-refresh-webpack-plugin react-refresh
npm i -D html-webpack-plugin
npm i -D mini-css-extract-plugin
mini-css-extract-plugin : 번들링 파일에서 CSS 파일을 별도로 추출해줌
webpack.ProvidePlugin : 모듈을 import 또는 require 할 필요 없이 자동으로 로드
webpack.DefinePlugin : 모든 JS 파일에서 접근 가능한 전역 변수를 선언하기 위해서 사용
const definePlugin = new webpack.DefinePlugin({
BASE_URL: JSON.stringify(BASE_URL),
}); //배포할 때 필요한 기본 URL을 저장해둠
module.exports = {
...
plugins: [
new webpack.ProvidePlugin({
React: 'react',
}),
definePlugin,
miniCssExtractPlugin,
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.html'),
}),
refreshWebpackPlugin,
],
}
resolve.alias : import
나 require
로 불러오는 특정한 module의 별칭을 정할 수 있음
resolve.fallback : 정상적인 확인이 실패하면 module 요청을 redirect해줌
preset.useBuiltIns
entry
: target 환경에서 요구되는 특정한 module만 import됨usage
: target 환경에서 지원하지 않는 feature를 사용할 때 자동으로 polyfill이 더해짐false
: 추가적인 polyfill이 자동으로 더해지지 않는 기본적인 값const path = require('path');
const RefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
module.exports = (env) => {
const { NODE_ENV } = env;
console.log(`[NODE_ENV] >>> ${NODE_ENV}`);
if (!['production', 'development'].includes(NODE_ENV))
throw Error('[NODE_ENV] must be production or development');
const DEV = NODE_ENV === 'development';
const mode = DEV ? 'development' : 'production';
const devtool = DEV ? 'eval-source-map' : false;
const lastCssLoader = DEV ? 'style-loader' : MiniCssExtractPlugin.loader;
const miniCssExtractPlugin = DEV
? { apply: () => {} }
: new MiniCssExtractPlugin({ filename: 'css/style.css' });
const refreshWebpackPlugin = DEV ? new RefreshWebpackPlugin() : { apply: () => {} };
const refreshBabel = DEV ? 'react-refresh/babel' : {};
const BASE_URL = DEV ? '' : 'fe-vm';
const definePlugin = new webpack.DefinePlugin({
BASE_URL: JSON.stringify(BASE_URL),
});
return {
mode,
devtool,
resolve: {
fallback: { fs: false, path: false },
alias: {
'@': path.resolve(__dirname, 'src'),
'@Utils': path.resolve(__dirname, 'src/utils'),
},
extensions: ['.js', '.ts', '.jsx', '.tsx'],
},
entry: {
main: './src/index.tsx',
},
module: {
rules: [
{
test: /\.(ts|tsx|js|jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [
[
'@babel/preset-env',
{
targets: {
browsers: ['> 0.5% in KR, not dead'],
},
useBuiltIns: 'usage',
corejs: { version: 3, proposals: true },
debug: true,
},
],
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [refreshBabel, 'styled-components'],
},
},
{
test: /\.(sc|c|sa)ss$/,
use: [lastCssLoader, 'css-loader'],
},
],
},
plugins: [
new webpack.ProvidePlugin({
React: 'react',
}),
definePlugin,
miniCssExtractPlugin,
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.html'),
}),
refreshWebpackPlugin,
],
devServer: {
open: true,
historyApiFallback: true,
static: {
directory: path.join(__dirname, 'public'),
},
hot: true,
client: {
overlay: {
errors: true,
warnings: false,
},
},
},
output: {
clean: true,
path: path.resolve(__dirname, 'dist'),
},
};
};