Next.js是提供基于React的SSR框架。解决SPA的一些缺点。下文会对SPA应用进行一些简单的介绍,并且会通过拆分本Demo的实现,让大家学会如何从零搭建Next框架。
现今前端开发技术,spa(single page application)单页应用的普及度越来越高,react以及vue这类的前端UI框架为spa提供的很好的实现。单页应用的本质其实就是浏览器首先加载必须的HTML、CSS和Javascript,所有的操作都在这张页面上完成,都由JavaScript来控制。
优点:
- 分离前后端关注点,前端负责view,后端负责model,各司其职;
- 服务器只接口提供数据,不用展示逻辑和页面合成,提高性能;
- 同一套后端程序代码,不用修改兼容Web界面、手机;
- 用户体验好、快,内容的改变不需要重新加载整个页面;
- 可以缓存较多数据,减少服务器压力;
缺点:
- SEO问题没有html抓不到什么;
- 刚开始的时候加载可能慢很多;
- 用户操作需要写逻辑,前进、后退等;
- 页面复杂度提高很多,复杂逻辑难度成倍;
因此,当我们既要使用SPA的开发模式,又要去兼容此模式缺点的时候,Next就是一个优秀的方案。
- next 6.1.1
- react 16.4.2
- react-dom 16.4.2
- react-next-fast/ # 项目名称
- components/ # 组件目录
Hello.js
Layout.js
- pages/ # 本地静态页面入口
- about/ # 模块子目录,路由会相应匹配
index.js # /about
contact.js # /about/contact
index.js # 首页
test.js # /test
- static/ # 静态资源存放目录
- css/ # 样式表目录
index.less
+ img/ # 图片目录
next.config.js # next配置文件
package.json # 项目配置
README.md # 项目说明
Install Next以及React相关
npm install --save next react react-dom
并且在package.json添加script如下:
{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}
创建pages目录和index.js文件 根据Next的规范约定,所有的页面都需要放在pages文件夹,因此我们首先先创建一个pages文件夹并在该文件夹下创建第一个页面index。
mkdir pages
cd pages
touch index.js
编写/pages/index.js
export default () => (
<div className="example">
<h1>Hello Next.js</h1>
</div>
)
运行npm run dev,在浏览器中打开 localhost:3000,就可以看到 Hello Next.js
在pages文件夹内再创建一个test.js文件并进行编写
export default () => (
<h1>this is test page</h1>
)
在浏览器中打开 localhost:3000/test,就可以看到 this is test page
再次打开index.js并且修改为如下内容:
import Link from 'next/link'
export default () => (
<div className="example">
<h1>Hello Next.js</h1>
<p>Menu</p>
<ul className="menu">
<li><Link href="/test"><a>Test</a></Link></li>
</ul>
</div>
)
打开 localhost:3000,就可以看到页面中多了一个Test的a链接,点击页面就会跳转到 localhost:3000/test
接着我们在pages/下建立about文件夹,并且创建index.js和contact.js两个文件
index.js
export default () => (
<div>
<h1>This is the about page</h1>
</div>
)
contact.js
export default () => (
<div>
<h1>This is the contact page</h1>
</div>
)
分别打开 localhost:3000/about 和 localhost:3000/about/contact 我们会相应的看到两个页面,因此我们会发现,pages文件的目录结构即是页面url的路径,pages本身就是根目录。
首先可以在每一个模块中添加样式:
<style jsx>{`
.red {color:#f00;}
`}</style>
其次,如果要想使用'.css','.less','.sass'或者'.styl'文件,Next官网也同样给到了相应的方案:
本Demo使用的是less的方案,其他方案雷同。
在pages中添加_document.js文件并编辑:
import Document, { Head, Main, NextScript } from 'next/document'
export default class MyDocument extends Document {
render() {
return (
<html>
<Head>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no minimal-ui" />
<link rel="stylesheet" href="/_next/static/style.css" />
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}
同时创建static目录,并且添加index.less文件进行编辑,最后在pages/index.js中引用
import Link from 'next/link'
import '../static/index.less'
export default () => (
<div className="example">
<h1>Hello Next.js</h1>
<p>Menu</p>
<ul className="menu">
<li><Link href="/about"><a>About</a></Link></li>
<li><Link href="/about/contact"><a>Contact</a></Link></li>
<li><Link href="/test"><a>Test</a></Link></li>
</ul>
</div>
)
就可以看到,页面的样式会根据index.less的修改进行改变,这样我们就可以去使用less了。
我们将pages/index.js改造成react组件,index这个页面就有了react的生命周期。
import React, { Component } from 'react'
import Link from 'next/link'
import '../static/index.less'
export default class Index extends Component {
constructor(){
super();
console.log('---------constructor--------');
}
componentWillMount(){
console.log('---------componentWillMount--------')
}
componentDidMount(){
console.log('---------componentDidMount--------')
}
componentWillUpdate(){
console.log('---------componentWillUpdate--------')
}
componentDidUpdate(){
console.log('---------componentDidUpdate--------')
}
render (){
return (
<div className="example">
<h1>Hello Next.js</h1>
<p>Menu</p>
<ul className="menu">
<li><Link href="/about"><a>About</a></Link></li>
<li><Link href="/about/contact"><a>Contact</a></Link></li>
<li><Link href="/test"><a>Test</a></Link></li>
</ul>
</div>
)
}
}
打开 localhost:3000 的控制台可以看到在Next框架下pages/index.js文件已经变成了react的组件了。
在使用react的时候,我们会将页面模块化进而拆分成最小单元的component,接下去我们会在根目录创建一个和pages并行的文件夹components来放置一些组件。
mkdir components
cd components
touch Hello.js
编辑Hello.js的内容
import React, { Component } from 'react'
export default class Hello extends Component {
render (){
return (
<div>
Nice to meet you!
</div>
)
}
}
然后我们随便找一个页面进行引用
pages/about/contact.js
import Head from 'next/head'
import Hello from '../../components/Hello'
export default () => (
<div>
<h1>This is the contact page</h1>
<Hello />
</div>
)
我们打开 localhost:3000/about/contact 可以看到页面用已经引用了 Hello 组件,并显示'Nice to meet you!'
在常规的业务常见中,我们经常会碰到同一个结构在多个页面被使用,因此在Next中我们可以设计一个Layout模版进行统一的调用。
cd components
touch Layout.js
编辑Layout.js
import Link from 'next/link'
import Head from 'next/head'
export default ({ children, title = 'This is the default title' }) => (
<div>
<Head>
<title>{ title }</title>
<meta charSet='utf-8' />
<meta name='viewport' content='initial-scale=1.0, width=device-width' />
</Head>
<header>
<nav>
<Link href='/'><a>Home</a></Link>
<Link href='/about'><a>About</a></Link>
<Link href='/about/contact'><a>Contact</a></Link>
<Link href='/test'><a>Test</a></Link>
</nav>
</header>
{ children }
<footer>
{'I`m footer'}
</footer>
<style jsx>{`
nav {
width:100%;
border-bottom:1px solid #ccc;
line-height:40px;
}
nav a {
margin:0 10px;
color:#999;
}
nav a:hover {
color:#000;
}
footer {
position:fixed;
bottom:0;
width:100%;
border-top:1px solid #ccc;
line-height:40px;
}
`}</style>
</div>
)
在test.js,about/index.js,about/contact.js中进行调用
import React, { Component } from 'react'
import Layout from './../components/Layout'
export default class Test extends Component {
render (){
return (
<Layout title="test page">
<h1>this is test page</h1>
</Layout>
)
}
}
可以看到,localhost:3000/test,localhost:3000/about,localhost:3000/about/contact这个页面都使用了Layout的模版。
Next可以设置每一个页面独有的Head设置,只需要在相应的页面中单独配置。
pages/index.js
import React, { Component } from 'react'
import Link from 'next/link'
import Head from 'next/head' //引入头部配置
import '../static/index.less'
export default class Index extends Component {
constructor(){
super();
console.log('---------constructor--------');
}
componentWillMount(){
console.log('---------componentWillMount--------')
}
componentDidMount(){
console.log('---------componentDidMount--------')
}
componentWillUpdate(){
console.log('---------componentWillUpdate--------')
}
componentDidUpdate(){
console.log('---------componentDidUpdate--------')
}
render (){
return (
<div className="example">
<Head>
<title>首页</title> //设置首页title
</Head>
<h1>Hello Next.js</h1>
<p>Menu</p>
<ul className="menu">
<li><Link href="/about"><a>About</a></Link></li>
<li><Link href="/about/contact"><a>Contact</a></Link></li>
<li><Link href="/test"><a>Test</a></Link></li>
</ul>
</div>
)
}
}
打开首页,可以看到title已变为刚设置的'首页'。
至此,教程已经完结,通过该教程,可以帮助大家更加快速的上手Next.js,查看具体代码,可以将Demo clone到本地,安装并运行。
git clone [email protected]:xiqe/react-next-fast.git
npm install
npm run dev #访问本地localhost:3000
npm run build #创建静态页面