• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    해결됨

CRA를 사용하지 않았을 경우 React.lazy에 대해...

21.01.14 15:57 작성 조회수 233

1

안녕하세요 강의 정말 유익하게 보고 있습니다 !!

다름이 아니라, 기존에 했던 프로젝트에 

React의 lazy를 이용하여 코드 분할을 시도하였는데 

청크파일로 나누어 로드되지 않더라구요...!

강의 중간에 CRA를 이용하면 이를 위한 웹팩 설정이 자동으로 되어있다고 하셨는데 ... 혹시 웹팩에 어떤 설정을 추가해줘야 할까요 !? 

제 웹팩 파일은 아래와 같습니다 !.. 

좋은강의 감사합니다 ㅎㅎ

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const Dotenv = require('dotenv-webpack');

module.exports = {
entry: './src/index',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: 'bundle.[hash].js',
chunkFilename: 'chunk.[hash].js',
},
optimizations: {
splitChunks: {
chunks: 'all',
},
},
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
modules: false,
targets: {
browsers: ['> 1% in KR'],
},
},
],
'@babel/preset-react',
],
plugins: ['@babel/plugin-proposal-class-properties'],
},
},
{
test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader' },
],
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
},
{
test: /\.(svg)$/, // .svg 확장자로 마치는 모든 파일
use: ['@svgr/webpack', 'url-loader'], // 파일 로더를 적용한다
},
],
},
devtool: 'eval-source-map',
devServer: {
contentBase: path.join(__dirname, 'public/'),
historyApiFallback: true,
host: '127.0.0.1',
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.scss'],
alias: {
'@interfaces': path.resolve(__dirname, 'src/interfaces'),
},
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
changeOrigin: true,
}),
new CleanWebpackPlugin(),
new Dotenv(),
new webpack.SourceMapDevToolPlugin({
exclude: [/node_modules/],
test: /\.(ts|tsx)/i,
}),
],
};

답변 4

·

답변을 작성해보세요.

2

안녕하세요 minseob님,

코드 분할(Code Splitting) 에 대해서 질문을 주셨는데요.

우선 강의에서 해당 내용을 명확하게 설명하지 못한 점 사과드립니다.
기본적으로 웹팩에서 코드 분할을 위한 다양한 방법과 설정들을 제공을 하는데요,
단순한 동적로딩을 위해서 웹팩 설정을 따로 건드리실 필요는 없습니다.

제가 직접 위의 웹팩 설정을 테스트 해봤는데,
해당 설정에서 문제는

1. webpack 설정 중, optimization 설정에서 오타가 있습니다. (optimizations 가 아니라 optimization 입니다. 뒤에 s가 빠져야 합니다.)
2. 굳이 optimization 설정을 하실 필요 없습니다. 해당 설정을 모두 지워주시고 작업하시면 됩니다. (올려주신 코드처럼 설정하면 청크파일들이 충돌이 나면서 에러가 납니다.)

이렇게 하시고, 강의에서 얘기한 것 처럼 Suspense 와 lazy 를 적절히 사용하면 코드 분할이 되고 동적 로딩을 합니다.

답변이 도움되었기를 바라며, 강의에 관심을 가져주셔서 감사합니다. :)

1

minseob님의 프로필

minseob

질문자

2021.01.15

아 좋은 방법을 제시해주셔서 감사합니다 !! 

코드 분할이 이루어지고 있어서인지는 모르겠지만 Light House로 performance를 측정했을 때 꽤나 유의미해 보이는 차이가 확인되기는 하였습니다 !! 

다만 network탭에서 lazy loading되는 파일이 확인되지 않다보니, 분할이 안되고 있다고 판단하였습니다 ! ... 

제시해주신 두가지 방법으로 더 시도해봐야겠습니다 ㅎㅎ

많은 도움이 되었습니다 ! 정말 감사합니다 ~ 

앞으로 나올 강의 또한 유익하게 수강하겠습니다 !

1

안녕하세요 minseob님,

올려주신 코드 상에서는 크게 문제가 없어보이는데요, 저것 만으로는 정확하게 어떤 부분이 문제인지 파악하기 어렵습니다.
제가 전체 코드(git repo)를 확인하고 돌려보지 않으면 정확히 파악이 힘들 것 같습니다.

제가 추천드리는 방법은,

1. 웹팩 설정을 그대로 카피해서 테스트 프로젝트를 생성해보기
2. 해당 소스코드를 카피해서 CRA로 만들어진 프로젝트 위에 소스코드만 올려보기

이렇게 두 가지 방법으로 테스트를 해보면 어느 부분에서 문제가 있는지 알 수 있을 것 같습니다. 

또한, 혹시 이미 코드 분할이 되고 있을 수도 있으니, build 스크립트를 통해 Suspense, lazy를 사용한 코드와 사용하지 않는 코드를 각각 빌드해 보고 그 결과물을 비교해 보면, 정말 코드 분할이 안된 것인지를 확인 할 수 있을 것 같습니다.

명확한 해답을 드리지 못해 죄송합니다.

0

minseob님의 프로필

minseob

질문자

2021.01.15

아 옮기다가 오타가 있었네요 ㅠㅠ 죄송합니다 !!

Suspense와 Lazy를 사용할 때는 CRA로 만든 프로젝트가 아닌 경우에도 웹팩 설정이 따로 필요없다고 받아들여도 괜찮을까요!?

따로 웹팩 설정을 하지않고 진행한 후 네트워크 탭을 통해 확인해보았는데, 제대로 스플리팅이 이루어지지 않는것 같아서요 !

(강의에서처럼 해당 라우트에 접근하는 시점에 chunk파일을 받아와야하는데 딱히 받아오지 않는걸 보니 첫 로딩때 다 받아오는것 같습니다 ㅠㅠ)

바쁘시겠지만 조금만 더 상황을 구체적으로 말씀드리고 조언을 구하고 싶은데 ...

한번만 더 읽어봐주시면 정말 큰 도움이 될 것같습니다 .. !

아래와 같이 작성한 후 기대한 것은 라우트의 path에 해당하는 주소로 접근할 경우에 

그에 해당하는 컴포넌트가 동적으로 로딩되는 것이었습니다. ( 강의에서 리스트페이지와 뷰페이지처럼 ...)

제가 고려한 사항은 아래와 같이 두 가지였습니다.

1. default로 export된 컴포넌트여야 한다. 

2. chunk파일로 스플릿되기 위해 webpack에 어떤 설정이 필요한가? 

2번 사항에 대해서는 따로 설정해줄 것이 없다라고 하셨고, 1번 사항은 잘 지켜서 export 하였는데

어떠한 오류도 없지만 제대로 동적로딩이 이루어지지도 않는 것 같습니다...

혹시 제가 빼먹은 고려사항이 있을까요 !? 서칭을 해봐도 lazy를 사용할 때에 대한 답을 찾기가 힘들어서 결국 또 질문드립니다ㅠㅠ

감사합니다 !!

import React, { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';

import PaymentProvider from './store/PaymentMethod/paymentMethodContext';
import DateInfoProvider from './store/DateInfo/dateInfoContext';
import TransactionInfoProvider from './store/AccountBook/accountBookDataContext';
import ThemeProvider from './store/Theme/themeContext';
import './app.scss';

import GithubLoginProcess from './pages/Login/GithubLoginProcess';
import NaverLoginProcess from './pages/Login/NaverLoginProcess';

const LoginPage = lazy(() => import('./pages/Login'));
const CalendarPage = lazy(() => import('./pages/Calendar'));
const AccountBookListPage = lazy(() => import('./pages/AccountBook'));
const TransactionPage = lazy(() => import('./pages/transaction'));
const ChartPage = lazy(() => import('./pages/Chart'));
const SettingPage = lazy(() => import('./pages/SettingPage'));
const App = () => {
if (!localStorage.getItem('theme')) {
localStorage.setItem('theme', 'dark');
}

return (
<ThemeProvider>
<DateInfoProvider>
<TransactionInfoProvider>
<PaymentProvider>
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route path="/" component={AccountBookListPage} exact />
<Route path="/login" component={LoginPage} exact />
<Route
path="/auth/github"
component={GithubLoginProcess}
exact
/>
<Route
path="/auth/naver"
component={NaverLoginProcess}
exact
/>
<Route path="/calendar" exact>
<CalendarPage />
</Route>
<Route
exact
path="/transaction"
component={TransactionPage}
/>
<Route path="/chart" component={ChartPage} exact />
<Route path="/setting" component={SettingPage} exact />
</Switch>
</Suspense>
</Router>
</PaymentProvider>
</TransactionInfoProvider>
</DateInfoProvider>
</ThemeProvider>
);
};

export default App;