React - router 4 필요 에 따라 불 러 오 는 실현 방식 및 원리 (Code Splitting)
9423 단어 자바 scriptreact.jsreact-router
router 4 이후 필요 에 따라 Component 를 불 러 오 는 방법 을 소개 합 니 다. router 4 이전에 저 희 는 getComponent 방식 으로 필요 에 따라 불 러 오 는 것 을 실 현 했 습 니 다. router 4 에서 getComponent 방법 은 제거 되 었 습 니 다. 다음은 react - router 4 가 들 어가 고 필요 에 따라 불 러 오 는 것 을 소개 합 니 다.
1. router 3 의 필요 에 따라 불 러 오 는 방식
route 3 에서 필요 에 따라 불 러 오 는 것 을 실현 하려 면 아래 코드 의 방식 으로 만 이 루어 지면 됩 니 다.
const about = (location, cb) => {
require.ensure([], require => {
cb(null, require('../Component/about').default)
},'about')
}
// route
2. router 4 필요 에 따라 불 러 오 는 방식 (three steps)
one step:
Bundle. js 파일 을 만 듭 니 다. 이 파일 은 사실 bundle - loader 로 포 장 된 구성 요 소 를 통 해 사용 합 니 다. 다음은 이 파일 을 구체 적 으로 설명 하 겠 습 니 다.
import React from 'react';
import PropTypes from 'prop-types';
class Bundle extends React.Component {
state = {
// short for "module" but that's a keyword in js, so "mod"
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({
// handle both es imports and cjs
mod: mod.default ? mod.default : mod
});
});
}
render() {
// if state mode not undefined,The container will render children
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
Bundle.propTypes = {
load: PropTypes.func,
children: PropTypes.func
};
export default Bundle;
second step:
import aContainer from 'bundle-loader?lazy!./containers/A'
const A = (props) => (
// this.props.child , Bundle render
{(Container) => }
)
third step:
render() {
return (
Welcome!
)
}
3. router 4 필요 에 따라 로드 방식 으로 분석
(1). 우선 필요 에 따라 불 러 옵 니 다. 통속 적 인 것 은 제 현재 location 이 Home 에 있 습 니 다. 그러면 저 는 Home 의 물건 만 불 러 와 야 합 니 다. About 등 다른 것 을 불 러 오지 말 아야 합 니 다.
(2). Bundle. js 이 파일 의 역할
먼저 이 코드 를 보십시오.
module.exports = function (cb) {
__webpack_require__.e/* require.ensure */(2).then((function (require) {
cb(__webpack_require__(305));
}).bind(null, __webpack_require__)).catch(__webpack_require__.oe);
};
이것 은 우리 가
import loadDashboard from 'bundle-loader?lazy!./containers/A'
이런 방식 으로 도입 한 container 컨트롤 입 니 다.우 리 는 bundle - loader 를 사용 하여 A 의 소스 코드 를 위의 코드 로 바 꾸 었 습 니 다. 구체 적 으로 실현 하면 bundle - loader 소스 코드 를 볼 수 있 고 코드 가 매우 적 습 니 다.위 에서 말 한 Bundle. js 는 사실 이 파일 을 처리 하 는 데 사 용 됩 니 다. 이 파일 은 callback 의 인자 가 필요 합 니 다. Bundle 의 load 방법 에서 이 callback 을 설정 합 니 다. 경로 가 A Container 로 바 뀌 려 면 A Container 를 불 러 오고 이 callback 을 호출 합 니 다. 이 callback 은 setState 방법 을 호출 합 니 다.우리 가 이전에 들 어 온 load 를 mod 에 설정 하고 렌 더 링 합 니 다.
4. webpack 에서 bundle - loader 를 통일 적 으로 설정 합 니 다.
src / routers / 아래 containers 폴 더 아래 의 모든 js 파일 과 일치 합 니 다. 2 급 디 렉 터 리 를 포함 합 니 다.
{
// routers
// ([^/]+)\/?([^/]*) xxx/xxx xxx
test: /containers\/([^/]+)\/?([^/]*)\.jsx?$/,
include: path.resolve(__dirname, 'src/routers/'),
// loader: 'bundle-loader?lazy'
loaders: ['bundle-loader?lazy', 'babel-loader']
}
5. 부분 소스 코드
1. bundle - loader 의 소스 코드
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var loaderUtils = require("loader-utils");
module.exports = function() {};
module.exports.pitch = function(remainingRequest) {
this.cacheable && this.cacheable();
var query = loaderUtils.getOptions(this) || {};
if(query.name) {
var options = {
context: query.context || this.options.context,
regExp: query.regExp
};
var chunkName = loaderUtils.interpolateName(this, query.name, options);
var chunkNameParam = ", " + JSON.stringify(chunkName);
} else {
var chunkNameParam = '';
}
var result;
if(query.lazy) {
result = [
"module.exports = function(cb) {
",
" require.ensure([], function(require) {
",
" cb(require(", loaderUtils.stringifyRequest(this, "!!" + remainingRequest), "));
",
" }" + chunkNameParam + ");
",
"}"];
} else {
result = [
"var cbs = [],
",
" data;
",
"module.exports = function(cb) {
",
" if(cbs) cbs.push(cb);
",
" else cb(data);
",
"}
",
"require.ensure([], function(require) {
",
" data = require(", loaderUtils.stringifyRequest(this, "!!" + remainingRequest), ");
",
" var callbacks = cbs;
",
" cbs = null;
",
" for(var i = 0, l = callbacks.length; i < l; i++) {
",
" callbacks[i](data);
",
" }
",
"}" + chunkNameParam + ");"];
}
return result.join("");
}
/*
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);
}
});
*/
2. A 의 소스 코드
import React from 'react';
import PropTypes from 'prop-types';
import * as reactRedux from 'react-redux';
import BaseContainer from '../../../containers/ReactBaseContainer';
class A extends BaseContainer {
constructor(props) {
super(props);
this.renderCustom = function renderCustom() {
return (
Hello world In A
);
};
}
render() {
// view
return super.render();
}
}
A.propTypes = {
dispatch: PropTypes.func,
};
function mapStateToProps(state) {
return { state };
}
export default reactRedux.connect(mapStateToProps)(A);
3. route. js 의 원본 코드
import React from 'react';
import { BrowserRouter, Switch, Link } from 'react-router-dom';
import { Route } from 'react-router';
import PostContainer from '../containers/PostsContainer';
// trunk the basename of the resource
import aContainer from './containers/A';
import bContainer from './containers/B';
import cContainer from './containers/C';
import Bundle from '../utils/Bundle';
const A = () => (
{Component => }
)
const app = () =>
{/* path = "/about" */}
{/* "/about/" , "/about/1" exact , , , */}
{/* path = "/about/" */}
{/* "/about/1" , "/about" strict,path , */}
{/* exact strick , */}
Link to about
{/*
*/}
;
export default function () {
//
const supportsHistory = 'pushState' in window.history;
return (
{app()}
);
}
업데이트 (필요 에 따라 불 러 오기)
oneStep
import React, { Component } from "react";
export default function asyncComponent(importComponent) {
class AsyncComponent extends Component {
constructor(props) {
super(props);
this.state = {
component: null
};
}
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? : null;
}
}
return AsyncComponent;
}
Second Step
const Buttons = asyncComponent(() => import("./button"));
babel 에 설정 이 필요 합 니 다.
"presets": [
[
"es2015"
],
"stage-1", // es7 ,
"react"
],
문장 인용
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Thymeleaf 의 일반 양식 제출 과 AJAX 제출텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.