next.js的从零到百入门配置
接触了react很长一段时间,终于有时间给我接触到实际的项目当中,虽然只是个entry task
,我希望能够将在vue所学到的优化点都运用到react上。首先选型肯定是next.js,它是一个轻量级的服务端渲染框架。在现在node服务端横行的年代,首屏直出的效果是非常重要的,除了seo的要求外,用户体验的提升是非常明显的。
这里直出分为:
- 静态直出(静态化)
- 动态直出(服务端渲染)
- 预渲染(prerender-spa-plugin)
其中,静态直出和动态直出是利用react的renderToNodeStream或者vue的renderToString的api实现了将dom监控直出到node端,可以动态实时渲染数据(其中会有秒级cache)或者静态化渲染。预渲染则是采用puppeteer
]在构建时将首屏的dom结构提前抓取下来构造成为html。其中静态化渲染效果应该和预渲染效果是接近的,都是html的内容是死的,而非数据真实动态数据。静态化广泛运用在vuepress和gatsby,这种技术更多是服务于博客或者网站官网。
相比之下,动态直出在列表渲染等因为用户数据动态变化的页面有着它天然的优势。
为什么说next.js是轻量级框架?它的出现有着渐进式的感觉。阿里出了umijs企业级插件化前端框架,但是太过于繁琐,不适合新手上手。next.js的插件化目的性更加明确。以下是next.js的官方插件,可以很轻易的接入css modules
、typescript
等。在ssr的框架里面算是非常友善,可以有非常丰富的examples。
- @zeit/next-mdx
- @zeit/next-css
- @zeit/next-sass
- @zeit/next-less
- @zeit/next-stylus
- @zeit/next-preact
- @zeit/next-typescript
- @zeit/next-bundle-analyzer
- @zeit/next-source-maps
- @zeit/next-workers
如何快速从零构建构建next.js
首先初始化项目,安装三个依赖,配置npm script
,框架已经搭建完成。其中,next
用于开发环境的调试。next build
用于构建服务端资源。将资源移交到服务器后,next start
命令启动node服务。next export
是用于静态化资源,静态化的资源可以用于降级。
yarn add next react react-dom
{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"export": "next export"
}
}
这时需要建个\pages
的文件夹,里面新建文件index.js
,写入react组件,组件会自动注入到SPA当中。其中pages是一个目录,所有的页面都会根据文件的存放格式自动生成路由,这也免去了react-router的干扰。
export default () => <div>Welcome to next.js!</div>
项目的从一到十
掘金有一篇文章Next.js踩坑入门系列。我读完这个系列后,发现这些文章果然有坑。我在这里帮忙填坑。项目的页面Layout配置,并非生成组件去完成,而是可以通过自定义重写pages目录当中的_app.js
和_document.js
。这些都属于next.js走向高阶的必经之路。例如,_app.js的重写就由以下几个优点,额外next提供了getInitialProps
的生命周期,完成服务端数据的获取工作,这部分代码是跑在服务端,而且每个页面组件一样存在getInitialProps
的生命周期(这里不用担心像vue一样created的生命周期是走在服务端)。
- 保持页面间跳转的功能,不同页面会走一样的生命周期
- 页面间跳转时候保持state
- 全局错误处理
- 额外的插件处理(例如mobx的引入)
//_app.js
import React from 'react';
import App, { Container } from 'next/app';
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
}
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<Component {...pageProps} />
</Container>
);
}
}
export default MyApp;
这时候,有人会问,如果要内联一些脚本,自定义引用外部css或js,seo要加入meta标签要怎么办?
这时_document.js
需要被重写,next
还提供了Head
组件方便你自定义<head>,并且可以把<html>, <body>等重写。
// ./pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html>
<Head>
<style>{`body { margin: 0 } /* custom! */`}</style>
</Head>
<body className="custom_class">
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
有了这两个自定义方案,很多场景都可以被自定义,项目也可以灵活起来。
项目的从十到百
需要各位同学的实战和研究,next.js/examples有大量值得学习的栗子,可供借鉴模仿,我相信很多代码模仿能力好的同学绝对不会错过。
也可以通过执行create-next-app
的命令来了解例子。
npx create-next-app --example with-typescript with-typescript-app
# or
yarn create next-app --example with-typescript with-typescript-app