Next.js我爱编程

十二、Next.js,延迟加载组件

2017-09-05  本文已影响105人  小纠结在简书

Next.js是一个新的通用JavaScript框架,它为基于React和服务器的Web应用提供了一个新的可选方案。

Next.js目前已经开源,https://zeit.co/blog/next

我们在应用程序使用了很多的React组件。这里将包括在我们主的 JavaScript 包 (app.js) 或页面的 JavaScript 包之一。有时这些组件都相当大。

例如,这是一个非常简单的博客站点,我们用Next.js构建基于markdown。

Paste_Image.png

它还支持语法高亮。对于这个,我们使用的是 react-highlight,,它是一个相当大的模块。

实际上,react-highlight 模块本身很小,但最highlight.js模块在里面是很笨重的。

下面是我们如何使用它。

import Highlight from 'react-highlight'

// some other code

<div>
  <Highlight innerHTML>
    {marked(blogPostMarkdown)}
  </Highlight>
</div>

// some other code

由于几乎所有页面都使用了它,所以在我们的主JavaScript包中包含了所有的内容。

但我们不需要在每个页面上使用高亮显示的语法。只有在博客文章中有一个代码样例时才需要它。

因此,如果我们能够在我们需要的时候加载 react-highlight,这将大大减少初始应用程序包,这将帮助我们的应用加载更快。

这是我们接下来要做的事情用Next.js(适用3.0版本以后)。
让我们开始吧。

安装

让我们下载我们将在本课程中使用的示例博客应用程序:

git clone https://github.com/arunoda/learnnextjs-demo.git
cd learnnextjs-demo
git checkout markdown-blog

然后你就可以运行这个应用了:

npm install
npm run dev

现在访问http://localhost:3000并尝试应用程序。

让我们来分析

在我们做其他事情之前,让我们分析一下我们的应用程序的JavaScript包。
为此,只需运行以下命令:

npm run analyze

在命令完成之后,您可以在web浏览器中看到结果。
highlight.js的包在哪里呢?

分析结果

正如你所见,它被包含在公共包 commons.js中。这是因为在我们的博客应用中几乎每一页都使用它。

Paste_Image.png

在这个结果页面中,我们甚至看不到react-highlight模块。这是因为它很小。该模块里面使用的highlight.js,它是一个重的模块。

Hello 动态组件

在这个应用程序中,我们将markdown独立渲染时一个React高阶组件(HOC)。
这是位于 lib/with-post.js。以下是该文件的内容:

import React from 'react'
import MyLayout from '../components/MyLayout'
import marked from 'marked'
import Highlight from 'react-highlight'

marked.setOptions({
  gfm: true,
  tables: true,
  breaks: true
})

export default function WithPost (options) {
  return class PostPage extends React.Component {
    render () {
      return (
        <MyLayout>
          <h1>{options.title}</h1>
          <div>
            <Highlight innerHTML>
              {marked(options.content)}
            </Highlight>
          </div>
        </MyLayout>
      )
    }
  }
}

你可以访问 pages/p/hello-nextjs.js然后看它是怎样使用这个HOC的。


现在,我们正在尝试将上面的Highlight 组件转换为动态组件。动态组件由Next.js dynamic imports 提供能力。

最重要的是,这些组件只有在应用程序即将呈现时才会加载。

创建动态组件很简单。您可以使用next/dynamic实用工具。下面是如何将Highlight 转换为动态组件的方法。

//import Highlight from 'react-highlight'
import dynamic from 'next/dynamic'

const Highlight = dynamic(import('react-highlight'))

这就是你要做的。
在lib/with-post.js中应用上述代码更改。

然后试着重新开始你的应用程序并访问http://localhost:3000/p/hello-nextjs。你将能够看到被加载的作为一个单独的捆绑包。

Paste_Image.png

现在尝试访问http://localhost:3000/p/learn-nextjs看看是否加载react-highlight包?

它总是加载

如您所见,甚至react-highlight包加载页面http://localhost:3000/p/learn-nextjs没有任何代码样本。

Paste_Image.png

它加载了react-highlight,因为我们要求它每次都加载。
你可以通过查看lib/with-post.js来了解这一点。以下是相关代码块:

export default function WithPost (options) {
  return class PostPage extends React.Component {
    render () {
      return (
        <MyLayout>
          <h1>{options.title}</h1>
          <div>
            <Highlight innerHTML>
              {marked(options.content)}
            </Highlight>
          </div>
        </MyLayout>
      )
    }
  }
}

我们经常使用Highlight 组件 options.content 有否任何代码或不。

仅在需要时加载

现在,我们只在需要的时候才使用Highlight 组件。

这是修改后的 WithPost HOC ,它只在需要时使用Highlight 组件。

export default function WithPost (options) {
  return class PostPage extends React.Component {
    renderMarkdown () {
      // If a code snippet contains in the markdown content
      // then use Highlight component
      if (/~~~/.test(options.content)) {
        return (
          <div>
            <Highlight innerHTML>
              {marked(options.content)}
            </Highlight>
          </div>
        )
      }

      // If not, simply render the generated HTML from markdown
      return (
        <div
          dangerouslySetInnerHTML={{__html: marked(options.content)}}
        />
      )
    }

    render () {
      return (
        <MyLayout>
          <h1>{options.title}</h1>
          { this.renderMarkdown() }
        </MyLayout>
      )
    }
  }
}

尝试将上述更改应用到lib/with-post.js并重新启动你的应用。

然后访问http://localhost:3000/p/learn-next.js。这款应用不会下载“react-highlight”。
但是如果你访问http://localhost:3000/p/hello-nextjs时,它将下载包。


现在我们有一个简单的任务。在生产模式下运行你的应用:

npm run build
npm run start

在Chrome中打开一个空白页面,并在dev控制台中选择“Network Inspect”。

然后访问http://localhost:3000 /。
页面加载后,单击“Hello Next.js”标题。

正如你已经看到的,这款应用会在需要的时候,在客户端上下载“react-highlight”功能。这就是动态组件的全部目的。当它加载时,它将显示一个加载组件。

如果需要,还可以设置一个自定义加载组件。custom loading component

直接访问

如果您直接访问包含代码片段的页面(比如http://localhost:3000/p/hello-nextjs)这是一个特例。然后,该应用程序将在服务器端加载组件,并包含初始HTML的包。

您可以通过查看上述页面的HTML内容来验证这一点。

Paste_Image.png
最后

惰性加载动态组件对于高性能应用程序来说非常重要,它允许您在需要的时候加载组件。如果你做的很明智,你可以减少需要下载的JavaScript的数量,让你的应用加载更快。

Next.js在默认情况下支持这些动态组件的服务器端呈现(SSR)。因此,使用动态组件不会丢失任何东西。

我们只使用了动态组件的基本功能。您可以通过参考文档了解更多关于它们的信息。 documentation.

本文翻译自:https://learnnextjs.com/excel/lazy-loading-components

上一篇 下一篇

猜你喜欢

热点阅读