Skip to content

Latest commit

 

History

History
258 lines (215 loc) · 9.04 KB

教程.md

File metadata and controls

258 lines (215 loc) · 9.04 KB

安装、启动、部署

"scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "NODE_ENV=production pm2 start server.js",
    "stop": "pm2 stop server.js"
  }

1、下载好项目后,安装依赖。

npm install 或者cnpm install

2、启动项目。

npm run dev

3、开发完成后,生产环境测试。

npm run build  // 先打包
npm start  // 再启动

4、检测没有问题,部署到服务器。

以阿里云为例,react服务端架构部署的基本步骤是,使用各种方法将前端项目上传到服务端,可以是FTP上传,也 可以在服务器使用git clone下载项目。

你得在服务器安装好node环境,然后和上面的第一步一样,在服务端安装依赖,然后就不要用dev启动项目,而是start,start设置成pm2启动,这样你的项目就能在服务端一直运行。

通常将前端项目放到和后端同内网的服务器上,这样的话,初始渲染需要请求的接口是在内网直接请求,首屏渲染的速度会更快。

主要的文件夹

Next框架和客户端框架的目录结构有所不同,需要注意这么几个关键的文件夹。

1、pages

pages下面有多个js文件,每个js文件对应一个服务端路由。index.js作为默认入口,也是首页路由。

2、static

static是静态资源的路径,这是Next采用的资源文件的管理方式,通常我将每个路由建立一个静态文件夹来管理。如果你将静态资源放到组件下的文件夹管理,可能会报路径的错误。

3、redux

目前redux目录下面只有一个store.js文件,在客户端开发的时候,是将reducer、store、action分开来管理,在服务端也可以学习这种管理模式。

4、styles

公共css资源

5、utils

定义各种接口的工具函数

6、components

每个路由使用到的组件都放在该文件夹下面,也是你开发react组件最常访问的地方

路由组件的写法

拿到一个新框架开发前端,通常就是写js、写css、然后关联起来,再导入一些图片,只要熟悉这些步骤,Next不会成为你的阻碍。

我拿首页路由index.js来讲解一下如何写服务端渲染的路由。

下面这个例子的写法相信对你来说一点也不陌生,他看起来就是一个纯客户端组件。它只做了一件事情,渲染一个Home组件。 前面我们说它是个路由,现在看起来就是一个组件,和路由有什么关系呢?下面讲到路由的跳转时你会有所体会。

import React from 'react' // 导入react
import { initStore } from '../redux/store' // 导入store,服务端渲染要初始化store
import withRedux from 'next-redux-wrapper' //这个插件和客户端不一样,需要特别注意
import Layout from layout // 在这里我提取了一个容器组件
import Home from '../components/Home' //导入首页组件

class App extends React.Component {
    componentDidMount () { }

    componentWillUnmount () { }

    render () {
        return (
            <Layout title={`图书商城`}>
                <Home />
            </Layout>
        )
    }
}

const mapDispatchToProps = (dispatch) => {
    return {}
}

export default withRedux(initStore, null, mapDispatchToProps)(App)

首页组件的写法

在首页的路由中,我们导入了Home组件,也就是首页组件,如果说路由组件中redux插件和客户端有些许不同,但是在首页组件中,写法就和客户端的完全一样。 所以使用Next开发,完全不用担心写法问题,只要你会客户端的react,写起服务端就很轻松。

import React from 'react' //关键
import { connect } from 'react-redux' //关键
import { bindActionCreators } from 'redux' //关键
import Header from './Header'
import Nav from './Nav'
import Special from './Special'
import { getNav } from '/redux/store' //关键

class Home extends React.Component {
    constructor(props) {
        super(props)
    }
    componentWillMount() {
        const { navMain=[] } = this.props
        if (navMain.length == 0) {
            this.props.getNav()
        }
    }
    render() {
        let bgClass = { background: '#00bb9c' }
        const  { navMain=[] } = this.props
        return (
            <div>
                <Header
                    title="react-next服务端渲染"
                    linkTo="/search"
                    bgColor={bgClass}
                    imgUrl={`/static/home/search.svg`}
                />
                <div className="style_div">
                    <ul className="style_ul">
                        {
                            navMain.map((elem, index) => {
                                return (
                                    <Nav
                                        key={index}
                                        title={elem.text}
                                        index={index}
                                        handleClick={() => this.handleClick()}
                                    />
                                )
                            })
                        }
                    </ul>
                </div>
                <Special />
            </div>
        )
    }
}
const mapStateToProps = ({ navMain }) => ({ navMain })

const mapDispatchToProps = (dispatch) => {
    return {
        getNav: bindActionCreators(getNav, dispatch)
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(Home)

路由跳转的实现

上面的Home组件中,有一个子组件Header,我在Header实现了一个Link标签,这个Link不是客户端中react-router的Link,而是 next/link的Link,服务端路由和客户端路由使用的插件不一样,你可以忘记客户端的react-router了。

import React from 'react'
import Link from 'next/link'
import Head from 'next/head'
import PropTypes from 'prop-types'
import headerStyle from './styles/header.scss'

const Header = (props) => {
    const { title, imgUrl, linkTo, bgColor, handleClick } = props
    return (
        <header className='header' style={bgColor}>
            <Head><style dangerouslySetInnerHTML={{__html: headerStyle}}></style></Head>
            {title}
            <Link href={linkTo}>
                <a className="a_link" onClick={() => handleClick('left')}><img src={imgUrl || false} className="a_img" /></a>
            </Link>
        </header>
    )
}
Header.propTypes = {
    title: PropTypes.string,
    imgUrl: PropTypes.string,
    linkTo: PropTypes.string,
    bgColor: PropTypes.object
}
export default Header

注意这个Link的DOM写法,不是使用to,而是href,内部再嵌入一个a标签。href中的linkTo是 '/search',上面的代码有提到。 然后你是否会想,search路由在哪里,因为我们没有写<Route path="/search" render={() => } />,其实很简单, Next已经在底层帮我们做好了路由的处理,你只要在pages目录下面加上search.js路由就行,具体看代码。然后在任意组件的 内部都可以通过Link或者Next提供的路由插件处理跳转。

<Link href={linkTo}>
                <a className="a_link" onClick={() => handleClick('left')}><img src={imgUrl || false} className="a_img" /></a>
            </Link>

CSS的导入

1、还是看Header组件,本项目采用scss组件的写法,默认是支持css的,导入的方式如下:

import headerStyle from './styles/header.scss'

2、Next更重要的一个特性是支持组件内部css的写法。

import React from 'react'
import PropTypes from 'prop-types'
const HotSearch = (props) => {
    const { hotText, hotClick, currentHot } = props
    return (
        <a className={`style_span`}
           onClick={hotClick}
           style={{color: currentHot === hotText ? '#398cee' : ''}}
        >
            {hotText}
            <style jsx>{`
            .style_span {
              display: inline-block;
              background: #f4f4f4;
              padding: 0.41667rem 0.833rem;
              margin-right: 1rem;
              margin-bottom: 0.833rem;
              color: #444;
              font-size: 1rem;
            }`}</style>
        </a>
    )
}
HotSearch.propTypes = {
    hotText: PropTypes.string,
    hotClick: PropTypes.func,
    currentHot: PropTypes.string
}
export default HotSearch

图片资源的导入

特别注意,导入图片的方式不再是require或者import了,因为服务端本身的资源都是路径明确的,所以采用传统的html导入图片的写法。而且图片资源必须放在static目录下面,否则就会报错,至于能不能放在 其他目录下面,我还没尝试成功。

<img src={`/static/search/search_1.png`} className="style_div_img" />

redux怎么写

这个就不用说了吧,和客户端的写法一样。如果你觉得redux-sage更好,那就换成它。

更多

next.config.js文件支持自定义webpack配置。

server.js的配置也很丰富,你可以前往Next官网学习。