찾다
웹 프론트엔드JS 튜토리얼React-Router4에서 코드 분할 방법
React-Router4에서 코드 분할 방법Mar 12, 2018 am 09:38 AM
암호방법

프런트엔드 프로젝트가 계속 확장됨에 따라 원래 단순한 웹 애플리케이션에서 참조하는 js 파일이 점점 더 커질 수 있습니다. 특히 최근 인기가 높은 단일 페이지 애플리케이션에서는 일부 패키징 도구(예: webpack)에 대한 의존도가 증가하고 있습니다. 이러한 패키징 도구를 통해 서로 의존하고 처리해야 하는 모듈을 별도의 번들 파일로 직접 패키징하여, 페이지가 처음 로드될 때 로드됩니다. 그러면 모든 js가 로드됩니다. 그러나 단일 페이지 애플리케이션의 모든 종속성을 한 번에 다운로드할 필요가 없는 시나리오가 종종 있습니다. 예를 들어, 이제 권한이 있는 단일 페이지 "주문 관리" 단일 페이지 애플리케이션이 있습니다. 일반 관리자는 "주문 관리" 섹션에 들어갈 수 있지만 슈퍼 사용자는 "시스템 관리"를 수행할 수 있습니다. 관리 페이지 애플리케이션의 경우, 사용자가 페이지를 처음 열 때 관련 없는 리소스를 로드하기 위해 오랜 시간을 기다려야 합니다. 이 경우 특정 코드 분할 수행을 고려할 수 있습니다.

구현 방법

간단한 온디맨드 로딩

코드 분할의 핵심 목적은 온디맨드 리소스 로딩을 달성하는 것입니다. 이 시나리오를 고려해 보세요. 웹사이트 오른쪽 하단에 채팅 상자와 유사한 구성 요소가 있습니다. 원형 버튼을 클릭하면 채팅 구성 요소가 페이지에 표시됩니다.


btn.addEventListener('click', function(e) {
  // 在这里加载chat组件相关资源 chat.js
});

이 예에서 chat.js 로딩 작업을 btn 클릭 이벤트에 바인딩하면 채팅 버튼을 클릭한 후 채팅 구성 요소의 온디맨드 로딩이 달성될 수 있음을 알 수 있습니다. js 리소스를 동적으로 로드하는 방법도 매우 간단합니다(익숙한 jsonp와 유사). 페이지에 태그를 동적으로 추가하고 src 속성을 리소스에 지정하면 됩니다.


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 파일로 패키징한다고 상상해 보세요. 이 경우 위에서 설명한 온디맨드 로딩을 ​​달성할 수 있는 방법이 없습니다. 따라서 우리는 온디맨드 로딩 코드에 대해 이야기해야 합니다. 코드 분할인 패키징 프로세스 중에 분할합니다. 그렇다면 이러한 리소스를 수동으로 분할해야 합니까? 물론 그렇지 않습니다. 여전히 패키징 도구를 사용해야 합니다. 다음으로 webpack의 코드 분할을 소개하겠습니다.

코드 분할

여기에서는 응용 시나리오로 돌아가 웹팩에서 코드 분할을 수행하는 방법을 소개합니다. Webpack의 빌드에서 코드 분할을 구현하는 방법에는 여러 가지가 있습니다.

import()

여기서 import는 모듈이 도입될 때의 import와는 다릅니다. 동적으로 로드되는 모듈의 함수와 유사한 것으로 이해될 수 있으며, 전달되는 매개변수는 해당 모듈입니다. 예를 들어, 원래 모듈 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 폴리필을 사용하면 호환성을 얻을 수 있습니다. 동적 import() 메서드는 의미와 구문 측면에서 비교적 명확하고 간결하다는 것을 알 수 있습니다.

require.ensure()

webpack 2의 공식 웹사이트에 다음 문장을 작성했습니다:

require.ensure()는 webpack에만 해당되며 import()로 대체됩니다.

따라서 webpack 2에서는 require.ensure() 메서드 사용을 권장하지 마세요. 하지만 이 방법은 현재에도 여전히 유효하므로 간단히 소개하겠습니다. webpack 1에 포함된 경우에도 사용할 수 있습니다. 다음은 require.ensure()의 구문입니다.

require.ensure(dependencies: String[], callback: function(require), errorCallback: function(error), chunkName: String)

require.ensure()는 세 가지 매개변수를 허용합니다:

  1. 첫 번째 매개변수 종속성은 현재 필요한 모듈의 일부 종속성을 나타내는 배열입니다. 두 번째 매개변수 콜백은 콜백 함수입니다. 주목해야 할 점은 이 콜백 함수에는 require 매개변수가 있으며 이를 통해 콜백 함수 내에서 다른 모듈을 동적으로 도입할 수 있다는 것입니다. 이 require는 콜백 함수의 매개변수이지만 이론상으로는 다른 이름으로 변경할 수 있지만 실제로는 변경할 수 없습니다. 그렇지 않으면 webpack이 정적 분석 중에 이를 처리할 수 없습니다.

    세 번째 매개변수 errorCallback 비교 이해하기 쉽습니다. 오류 처리를 위한 콜백입니다.
  2. 네 번째 매개변수인 ChunkName은 패키징을 지정하는 청크 이름입니다.
  3. 따라서 require.ensure()의 구체적인 사용법은 다음과 같습니다.
  4. btn.addEventListener('click', e => {
      require.ensure([], require => {
        let chat = require('/components/chart');
        someOperate(chat);
      }, error => {
        console.log('failed');
      }, 'mychat');
    });
Bundle Loader

위의 두 가지 방법을 사용하는 것 외에도 webpack의 일부 구성 요소를 사용할 수도 있습니다. 예를 들어, 번들 로더를 사용하세요:

npm i --save bundle-loader
require("bundle-loader!./file.js")를 사용하여 해당 청크를 로드하세요. 이 메소드는 콜백 함수를 매개변수로 받아들이는 함수를 반환합니다.

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 中的代码拆分

最后,回到实际的工作中,基于webpack,在react-router4中实现代码拆分。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 &#39;bundle-loader?lazy!./Something&#39;

然而,在项目中使用类似的方式后,出现了这样的警告:

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.

在webpack 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作为脚手架,屏蔽了webpack的一些配置。当然,也可以通过运行npm run eject使其暴露webpack等配置文件。然而,是否可以用其他方法呢?当然。

这里就可以使用之前说到的两种方式来处理: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 &#39;bundle-loader?lazy!./About&#39;

const About = (props) => (
  <Bundle load={loadAbout}>
    {(About) => <About {...props}/>}
  </Bundle>
)

由于不再使用Bundle Loader,我们可以使用import()对该段代码进行改写:


const Chat = (props) => (
  <Bundle load={() => import(&#39;./component/chat&#39;)}>
    {(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(&#39;./component/chat&#39;));
    });
  }}>
  {(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
  }
}

此外,如果是直接使用webpack config的话,也可以进行如下配置


output: {
  // The build folder.
  path: paths.appBuild,
  // There will be one main bundle, and one file per asynchronous chunk.
  filename: &#39;static/js/[name].[chunkhash:8].js&#39;,
  chunkFilename: &#39;static/js/[name].[chunkhash:8].chunk.js&#39;,
 },

结束

代码拆分在单页应用中非常常见,对于提高单页应用的性能与体验具有一定的帮助。我们通过将第一次访问应用时,并不需要的模块拆分出来,通过scipt标签动态加载的原理,可以实现有效的代码拆分。在实际项目中,使用webpack中的import()、require.ensure()或者一些loader(例如Bundle Loader)来做代码拆分与组件按需加载。

위 내용은 React-Router4에서 코드 분할 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
演示win7调整屏幕亮度的方法演示win7调整屏幕亮度的方法Jul 08, 2023 pm 07:49 PM

不同的电脑系统在调整屏幕亮度的操作方法上会有些不同,最近就有使用win7系统的网友不知道win7怎么调整屏幕亮度,看久了电脑眼睛比较酸痛。下面小编就教下大家win7调整屏幕亮度的方法。具体的操作步骤如下:1、点击win7电脑左下角的“开始”,在弹出的开始菜单中选择“控制面板”打开。2、在打开的控制面板中找到“电源选项”打开。3、也可以用鼠标右键电脑右下角的电源图标,在弹出的菜单中,点击“调整屏幕亮度”,如下图所示。两种方法都可以用。4、在打开的电源选项窗口的最下面可以看到屏幕亮度调整的滚动条,直

win10监控摄像头打开照片的方法win10监控摄像头打开照片的方法Jul 10, 2023 pm 09:41 PM

如果我们手头没有手机,只有电脑,但我们必须拍照,我们可以使用电脑内置的监控摄像头拍照,那么如何打开win10监控摄像头,事实上,我们只需要下载一个相机应用程序。打开win10监控摄像头的具体方法。win10监控摄像头打开照片的方法:1.首先,盘快捷键Win+i打开设置。2.打开后,进入个人隐私设置。3.然后在相机手机权限下打开访问限制。4.打开后,您只需打开相机应用软件。(如果没有,可以去微软店下载一个)5.打开后,如果计算机内置监控摄像头或组装了外部监控摄像头,则可以拍照。(因为人们没有安装摄

基于Java的机器视觉实践和方法介绍基于Java的机器视觉实践和方法介绍Jun 18, 2023 am 11:21 AM

随着科技的不断发展,机器视觉技术在各个领域得到了广泛应用,如工业自动化、医疗诊断、安防监控等。Java作为一种流行的编程语言,其在机器视觉领域也有着重要的应用。本文将介绍基于Java的机器视觉实践和相关方法。一、Java在机器视觉中的应用Java作为一种跨平台的编程语言,具有跨操作系统、易于维护、高度可扩展等优点,对于机器视觉的应用具有一定的优越性。Java

win7怎么调屏幕亮度的两种简单方法win7怎么调屏幕亮度的两种简单方法Jul 08, 2023 pm 06:33 PM

目前有很多屏幕亮度调整软件,我们可以通过使用软件进行快速调整或者通过显示器上自带的亮度功能进行调整。以下是详细的Win7屏幕亮度调整方式,您可以通过教程中的方法进行快速调整即可。Win7系统电脑怎么调节屏幕亮度教程:1、依次点击“计算机—右键—控制面板”,如果没有也可以在搜索框中进行搜索。2、点击控制面板下的“硬件和声音”,或者点击“外观和个性化”都可以。3、点击“NVIDIA控制面板”,有些显卡可能是AMD或者Intel的,请根据实际情况选择。4、调节图示中亮度滑块即可。5、还有一种方法,就是

Go 语言中的方法是怎样定义和使用的?Go 语言中的方法是怎样定义和使用的?Jun 10, 2023 am 08:16 AM

Go语言是近年来备受青睐的编程语言,因其简洁、高效、并发等特点而备受开发者喜爱。其中,方法(Method)也是Go语言中非常重要的概念。接下来,本文就将详细介绍Go语言中方法的定义和使用。一、方法的定义Go语言中的方法是带有接收器(Receiver)的函数,它是一个与某个类型绑定的函数。接收器可以是值类型或者指针类型。用于接收者的参数可以在方法名

图文详解如何下载win10系统方法图文详解如何下载win10系统方法Jul 16, 2023 pm 01:25 PM

如今微软的Windows系统已经更新换代到了Windows10版本。很多以前还在使用Windows7系统的用户都想体验这个新版本Windows10系统。下面小编就来说说如何下载win10系统下载的方法,大家快来看看。1、首先下载一个小白重装系统软件,然后点击在线重装,下载win10系统。2、然后就开始系统镜像的下载了。3、系统镜像下载完成就是环境部署了。然后win10系统就下载完成啦。4、重启之后开始安装系统,安装完成就能进入桌面咯。以上就是如何下载win10系统的方法介绍啦,希望能帮助到大家。

PHP文件下载方法及常见问题解答PHP文件下载方法及常见问题解答Jun 09, 2023 pm 12:37 PM

PHP是一个广泛使用的服务器端编程语言,它的许多功能和特性可以将其用于各种任务,包括文件下载。在本文中,我们将了解如何使用PHP创建文件下载脚本,并解决文件下载过程中可能出现的常见问题。一、文件下载方法要在PHP中下载文件,我们需要创建一个PHP脚本。让我们看一下如何实现这一点。创建下载文件的链接通过HTML或PHP在页面上创建一个链接,让用户能够下载文件。

Vue 中的 createApp 方法是什么?Vue 中的 createApp 方法是什么?Jun 11, 2023 am 11:25 AM

随着前端开发的快速发展,越来越多的框架被用来构建复杂的Web应用程序。Vue.js是流行的前端框架之一,它提供了许多功能和工具来简化开发人员构建高质量的Web应用程序。createApp()方法是Vue.js中的一个核心方法之一,它提供了一种简单的方式来创建Vue实例和应用程序。本文将深入探讨Vue中createApp方法的作用,其如何使用以及使用时需要了解

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!