react-router 4 에서 코드 분할 방법(웹 팩 기반)
전단 프로젝트 가 계속 확대 되면 서 간단 한 웹 애플 리 케 이 션 에서 인용 한 js 파일 이 점점 커 질 수 있 습 니 다.특히 최근 유행 하 는 단일 페이지 애플 리 케 이 션 에 서 는 패키지 도구(예 를 들 어 웹 팩)에 점점 의존 하고 있 습 니 다.이 패키지 도 구 를 통 해 처리 하고 의존 하 는 모듈 을 하나의 bundle 파일 로 직접 포장 하여 페이지 를 처음 불 러 올 때 모든 js 를 불 러 옵 니 다.그러나 많은 장면 이 있 습 니 다.우 리 는 한 페이지 의 응용 에 대한 모든 의존 도 를 한꺼번에 불 러 올 필요 가 없습니다.예 를 들 어 우 리 는 현재 권한 을 가 진'주문 백 스테이지 관리'단일 페이지 응용 프로그램 이 있 습 니 다.일반 관리 자 는'주문 관리'부분 에 만 들 어 갈 수 있 고 슈퍼 사용 자 는'시스템 관리'를 할 수 있 습 니 다.또는,우 리 는 방대 한 단일 페이지 응용 프로그램 을 가지 고 있 습 니 다.사용자 가 처음 페이지 를 열 때,무관 한 자원 을 오래 불 러 올 때 까지 기 다 려 야 합 니 다.이 럴 때 우 리 는 일정한 코드 분할(code splitting)을 고려 할 수 있다.
실현 방식
간단하게 필요 에 따라 불 러 오기
코드 분할 의 핵심 목적 은 자원 의 필요 에 따라 로드 하 는 것 이다.이러한 장면 을 고려 하면 우리 사이트 에서 오른쪽 아래 에 채 팅 상자 와 유사 한 구성 요소 가 있 습 니 다.우리 가 원형 단 추 를 눌 렀 을 때 페이지 는 채 팅 구성 요 소 를 보 여 줍 니 다.
btn.addEventListener('click', function(e) {
// chat chat.js
});
이 예 에서 알 수 있 듯 이 chat.js 를 불 러 오 는 작업 을 btn 클릭 이벤트 에 연결 하면 채 팅 단 추 를 누 른 후 채 팅 구성 요 소 를 필요 에 따라 불 러 올 수 있 습 니 다.js 자원 을 동적 으로 불 러 오 는 방식 도 간단 하 다.페이지 에
btn.addEventListener('click', function(e) {
// chat chat.js
var ele = document.createElement('script');
ele.setAttribute('src','/static/chat.js');
document.getElementsByTagName('head')[0].appendChild(ele);
});
코드 분할 은 필요 에 따라 불 러 오 는 작업 을 실현 하기 위해 서 입 니 다.상상 해 보 세 요.우 리 는 포장 도 구 를 사용 하여 모든 js 를 bundle.js 라 는 파일 에 포장 했다.이런 상황 에서 위 에서 말 한 필요 에 따라 불 러 올 수 없 기 때문에 우 리 는 불 러 올 코드 에 따라 포장 과정 에서 분리 하 는 것 을 말 해 야 합 니 다.이것 이 바로 코드 분할 입 니 다.그렇다면 이 자원 들 에 대해 우 리 는 수 동 으로 분할 해 야 합 니까?물론 아 닙 니 다.포장 도 구 를 빌려 야 합 니 다.웹 팩 의 코드 분할 을 소개 합 니 다.코드 분할
웹 팩 에서 코드 분할 을 하 는 방법 을 소개 합 니 다.웹 팩 에 서 는 구축 을 위 한 다양한 방식 이 있 습 니 다.
import()
이 곳 의 import 는 모듈 이 도 입 될 때의 import 와 달리 동적 으로 불 러 오 는 모듈 의 함수(function-like)로 이해 할 수 있 습 니 다.그 안에 들 어 오 는 매개 변 수 는 해당 모듈 입 니 다.예 를 들 어 기 존 모듈 에 import react from'react'를 도입 하면 import('react')라 고 쓸 수 있 습 니 다.그러나 주의해 야 할 것 은 import()가 Promise 대상 을 되 돌려 줍 니 다.따라서 다음 과 같은 방식 으로 사용 할 수 있다.
btn.addEventListener('click', e => {
// chat chat.js
import('/components/chart').then(mod => {
someOperate(mod);
});
});
평소 우리 가 사용 하 던 Promise 와 다 르 지 않 게 사용 방식 이 간단 하 다 는 것 을 알 수 있다.물론 이상 처 리 를 추가 할 수도 있다.
btn.addEventListener('click', e => {
import('/components/chart').then(mod => {
someOperate(mod);
}).catch(err => {
console.log('failed');
});
});
물론 import()는 Promise 대상 을 되 돌려 주기 때문에 호환성 문제 에 주의해 야 합 니 다.이 문 제 를 해결 하 는 것 도 어렵 지 않 습 니 다.Promise 의 poly fill 을 사용 하여 호 환 을 실현 할 수 있 습 니 다.이 를 통 해 알 수 있 듯 이 동적 import()의 방식 은 의미 적 으로 나 문법 적 으로 나 비교적 뚜렷 하고 간결 하 다.require.ensure()
웹 팩 2 홈 페이지 에 이렇게 적 혀 있 습 니 다.
require.ensure() is specific to webpack and superseded by import().
따라서 웹 팩 2 에 서 는 require.ensure()라 는 방법 을 사용 하 는 것 을 권장 하지 않 을 것 입 니 다.하지만 아직 은 이 방법 이 효과 가 있 기 때문에 간단하게 소개 할 수 있다.웹 팩 1 에 도 사용 가능 합 니 다.다음은 require.ensure()의 문법 입 니 다.
require.ensure(dependencies: String[], callback: function(require), errorCallback: function(error), chunkName: String)
require.ensure()는 세 개의 인 자 를 받 아들 입 니 다.
btn.addEventListener('click', e => {
require.ensure([], require => {
let chat = require('/components/chart');
someOperate(chat);
}, error => {
console.log('failed');
}, 'mychat');
});
Bundle Loader상기 두 가지 방법 을 사용 하 는 것 외 에 웹 팩 의 일부 구성 요 소 를 사용 할 수 있 습 니 다.예 를 들 어 Bundle Loader 사용 하기:
npm i --save bundle-loader
require 사용("bundle-loader!./file.js")에 해당 하 는 chunk 로 딩 을 진행 합 니 다.이 방법 은 function 을 되 돌려 줍 니 다.이 function 은 반전 함 수 를 매개 변수 로 받 아들 입 니 다.
let chatChunk = require("bundle-loader?lazy!./components/chat");
chatChunk(function(file) {
someOperate(file);
});
다른 loader 와 유사 하 며,Bundle Loader 도 webpack 설정 파일 에 해당 하 는 설정 을 해 야 합 니 다.Bundle-Loader 의코드도 간단 합 니 다.읽 어 보면 실제 적 으로 require.ensure()를 사용 하여 이 루어 진 것 을 알 수 있 습 니 다.Bundle-Loader 에 되 돌아 오 는 함수 에 해당 하 는 모듈 처리 리 턴 함 수 를 입력 하면 require.ensure()에서 처리 할 수 있 습 니 다.코드 는 마지막 에 해당 하 는 출력 형식 을 보 여 줍 니 다.
/*
Output format:
var cbs = [],
data;
module.exports = function(cb) {
if(cbs) cbs.push(cb);
else cb(data);
}
require.ensure([], function(require) {
data = require("xxx");
var callbacks = cbs;
cbs = null;
for(var i = 0, l = callbacks.length; i < l; i++) {
callbacks[i](data);
}
});
*/
react-router v4 의 코드 분할마지막 으로 실제 작업 으로 돌아 가 웹 팩 을 기반 으로 react-router 4 에서 코드 분할 을 실현 합 니 다.react-router 4 는 react-router 3 에 비해 비교적 큰 변동 이 있 었 다.그 중에서 코드 분할 에 있어 서 react-router 4 의 사용 방식 도 react-router 3 과 큰 차이 가 있다.
react-router 3 에 서 는 Route 구성 요소 에서 getComponent 라 는 API 를 사용 하여 코드 를 나 눌 수 있 습 니 다.getComponent 는 비동기 적 이 며 경로 가 일치 할 때 만 호출 됩 니 다.그러나 react-router 4 에서 이 API 를 찾 지 못 했 습 니 다.코드 분할 은 어떻게 하 시 겠 습 니까?
react-router 4홈 페이지 에 코드 분할 의 예 가 있다.그 중에서 Bundle Loader 를 사용 하여 필요 에 따라 로드 와 동적 도입 을 진행 합 니 다.
import loadSomething from 'bundle-loader?lazy!./Something'
그러나 프로젝트 에서 유사 한 방식 을 사용 한 후 이러한 경고 가 나 타 났 다.Unexpected '!' in 'bundle-loader?lazy!./component/chat'. Do not use import syntax to configure webpack loaders import/no-webpack-loader-syntax
Search for the keywords to learn more about each error.
웹 팩 2 에 서 는 import 와 같은 방식 으로 loader 를 도입 할 수 없습니다no-webpack-loader-syntax
Webpack allows specifying the loaders to use in the import source string using a special syntax like this:
var moduleWithOneLoader = require("my-loader!./my-awesome-module");
This syntax is non-standard, so it couples the code to Webpack. The recommended way to specify Webpack loader configuration is in a Webpack configuration file.내 응용 프로그램 은 create-react-app 을 비계 로 사용 하여 웹 팩 의 일부 설정 을 차단 했다.물론 npm run eject 를 실행 하여 웹 팩 등 프로필 을 노출 시 킬 수도 있 습 니 다.하지만 다른 방법 을 써 도 될까요?그럼요.
앞에서 말 한 두 가지 방식 으로 처리 할 수 있 습 니 다:import()또는 require.ensure().
공식 인 스 턴 스 와 유사 합 니 다.우선 비동기 로 불 러 오 는 포장 구성 요소 Bundle 이 필요 합 니 다.Bundle 의 주요 기능 은 구성 요소 의 비동기 로드 방법 을 받 아들 이 고 해당 하 는 react 구성 요 소 를 되 돌려 주 는 것 입 니 다.
export default class Bundle extends Component {
constructor(props) {
super(props);
this.state = {
mod: null
};
}
componentWillMount() {
this.load(this.props)
}
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps)
}
}
load(props) {
this.setState({
mod: null
});
props.load((mod) => {
this.setState({
mod: mod.default ? mod.default : mod
});
});
}
render() {
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
기 존의 예 에서 Bundle Loader 를 통 해 모듈 을 도입 합 니 다.
import loadSomething from 'bundle-loader?lazy!./About'
const About = (props) => (
<Bundle load={loadAbout}>
{(About) => <About {...props}/>}
</Bundle>
)
Bundle Loader 를 더 이상 사용 하지 않 기 때문에 import()를 사용 하여 이 코드 를 고 칠 수 있 습 니 다.
const Chat = (props) => (
<Bundle load={() => import('./component/chat')}>
{(Chat) => <Chat {...props}/>}
</Bundle>
);
주의해 야 할 것 은 import()가 Promise 대상 을 되 돌려 주기 때문에 Bundle 구성 요소 의 코드 도 상응 하 게 조정 해 야 합 니 다.
export default class Bundle extends Component {
constructor(props) {
super(props);
this.state = {
mod: null
};
}
componentWillMount() {
this.load(this.props)
}
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps)
}
}
load(props) {
this.setState({
mod: null
});
// , Promise ; mod.default
props.load().then((mod) => {
this.setState({
mod: mod.default ? mod.default : mod
});
});
}
render() {
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
경로 부분 에 변화 가 없습니다.
<Route path="/chat" component={Chat}/>
이 때 npm run start 를 실행 하면 최초의 페이지 를 불 러 올 때 불 러 온 자원 을 다음 과 같이 볼 수 있 습 니 다./chat 경 로 를 터치 하면 볼 수 있 습 니 다.
2.chunk.js 라 는 js 파일 을 동적 으로 불 러 왔 습 니 다.이 파일 을 열 어 보면 이것 이 바로 우리 가 방금 동적 import()에 들 어 온 모듈 임 을 알 수 있 습 니 다.
물론 import()를 사용 하 는 것 외 에 도 require.ensure()를 사용 하여 모듈 의 비동기 로드 를 할 수 있 습 니 다.관련 예시 코드 는 다음 과 같다.
const Chat = (props) => (
<Bundle load={(cb) => {
require.ensure([], require => {
cb(require('./component/chat'));
});
}}>
{(Chat) => <Chat {...props}/>}
</Bundle>
);
export default class Bundle extends Component {
constructor(props) {
super(props);
this.state = {
mod: null
};
}
load = props => {
this.setState({
mod: null
});
props.load(mod => {
this.setState({
mod: mod ? mod : null
});
});
}
componentWillMount() {
this.load(this.props);
}
render() {
return this.state.mod ? this.props.children(this.state.mod) : null
}
}
또한 웹 팩 config 를 직접 사용 하면 다음 과 같은 설정 을 할 수 있 습 니 다.
output: {
// The build folder.
path: paths.appBuild,
// There will be one main bundle, and one file per asynchronous chunk.
filename: 'static/js/[name].[chunkhash:8].js',
chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
},
끝나다코드 분할 은 한 페이지 응용 에서 흔히 볼 수 있 고 한 페이지 응용 의 성능 과 체험 을 향상 시 키 는 데 도움 이 된다.저 희 는 첫 번 째 방문 응용 을 통 해 필요 하지 않 은 모듈 을 분리 하고 scipt 태그 동적 로드 원 리 를 통 해 효과 적 인 코드 분 리 를 실현 할 수 있 습 니 다.실제 항목 에 서 는 웹 팩 의 import(),require.ensure()또는 일부 loader(예 를 들 어 Bundle Loader)를 사용 하여 코드 분할 과 구성 요 소 를 필요 에 따라 불 러 옵 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
nginx 에서 사이트 아이콘 표시 설정전단 개발 환경: react:^16.4.1 webpack:^4.16.0 웹 팩 에 favicon. ico 설정 추가: nginx 는 ico 에 대한 지원 을 추가 합 니 다:...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.