Next.js实现react服务器端渲染的方法示例


Posted in Javascript onJanuary 06, 2019

说明

实现 路由跳转、redux

文件版本

  • “next”: “^4.2.3”,
  • “react”: “^16.2.0”,
  • “react-dom”: “^16.2.0”

Next.js GitHub 文档

项目源码

使用

Next.js 使用文件体统作为API,可以自动进行服务器端渲染和代码分割

1. 安装

yarn add next react react-dom

2. package.json 中添加 npm script

"scripts": {
  "dev": "next",
  "build": "next build",
  "start": "next start"
 },

3. 创建 /pages 文件夹,其中文件会映射为路由

/pages 文件夹是顶级组件文件夹 其中 /pages/index.js 文件会映射文 / 路由,其他文件根据文件名映射

目录结构 映射路由
/pages/index.js /
/pages/about.js /about
/pages/home/index.js /home
/pages/home/about.js /home/about

每一个路由js文件都会 export 一个 React 组件,这个组件可以是函数式的也可以是通过集成 React.Component 得到的类

export default () => <div>this is index page </div>;

4. 创建 /static 文件夹,存放静态资源

静态资源文件夹文件会映射到 /static/ 路由下,直接通过 http://localhost:3000/static/test.png 访问

5. 使用内置组件 <head> 定制每个页面的 head 部分

import Head from 'next/head'; // 引入内置组件

  export default () => (
    <div>
     <Head>
       <title>index page</title>
       <meta name="viewport" content="initial-scale=1.0, width=device-width"/>
     </Head>
     <div>this is index page</div>
    </div>
  );

6. 使用内置组件 <Link> 进行路由跳转

import Link from 'next/link';

  export default () => (
    <div>
     <p>this is home index page</p>
     <Link href="/about" rel="external nofollow" rel="external nofollow" >
       <a> to about page</a>
     </Link>
    </div>
  );

更多 Link 使用方式

import React, {Component} from 'react';
import Link from 'next/link';

export default class About extends Component {
  constructor(props) {
   super(props);
  }
  render() {
   // href 值可以是一个对象
   const href = {
     pathname: '/home',
     query: {name: 'test'}
   };

   return (
    <div>
      <p>this is about page </p>
      <img src="/static/test.png" alt="test"/>
      {/* replace 覆盖历史跳转 */}
      <Link href={href} replace>
      <a>click to home index page</a>
      </Link>
    </div> 
   );
  }
}

7. 使用内置 router 方法,手动触发路由跳转

next/router 提供一套方法和属性,帮助确认当前页面路由参数,和手动触发路由跳转

import router from 'next/router';
  /*
    router.pathname ==> /home
    router.query ==> {}
    router.route - 当前路由
    asPath - 显示在浏览器地址栏的实际的路由
    push(url, as=url) - 跳转页面的方法
    replace(url, as=url) - 跳转页面
  */

更好的方式使用路由 ? router 的 withRouter 方法

import Link from 'next/link';
import {withRouter} from 'next/router';

const Home = (props) => {
  // 这里的 props 会得到 {router, url} 两个属性
  // router: {push: ƒ, replace: ƒ, reload: ƒ, back: ƒ, prefetch: ƒ, …}
  // url: {query: {…}, pathname: "/home", asPath: "/home?name=test", back: ƒ, push: ƒ, …}
  console.log(props);
  return (
   <div>
     <p>this is home index page </p>
     {/* <Link href="/about" rel="external nofollow" rel="external nofollow" >
      <a> to about page</a>
     </Link> */}
   </div>
  );
}

export default withRouter(Home);

8. 使用 next-redux-wrapper 插件辅助实现 redux

1. 安装依赖

sudo yarn add next-redux-wrapper redux react-redux redux-devtools-extension redux-thunk

2. 创建 initializeStore.js 一个可以返回 store 实例的函数

在这个文件中会完成装载中间件、绑定reducer、链接浏览器的redux调试工具等操作

import { createStore, applyMiddleware } from 'redux';
  import { composeWithDevTools } from 'redux-devtools-extension'; 
  import thunk from 'redux-thunk';
  import reducer from '../modules/reducers';

  const middleware = [thunk];
  const initializeStore = initialState => {
    return createStore(
       reducer, 
       initialState, 
       composeWithDevTools(applyMiddleware(...middleware))
     );
  };

  export default initializeStore;

3. 创建 reducer , action

与普通 react-redux 项目创建 reducer, action 的方法一致,我把这部分代码都提取到一个名为 modules的文件夹中

// /modules/reducers.js
  import { combineReducers } from 'redux';
  import about from './about/reducer';

  // 合并到主reducer
  const reducers = {
    about
  };

  // combineReducers() 函数用于将分离的 reducer 合并为一个 reducer 
  export default combineReducers(reducers);
// /modules/about/reudcer.js 
  // /about 页面的 reducer
  import {
    CHANGE_COUNT
  } from '../types-constant';

  const initialState = {
    count: 0
  };

  const typesCommands = {
    [CHANGE_COUNT](state, action) {
     return Object.assign({}, state, { count: action.msg });
    },
  }

  export default function home(state = initialState, action) {
    const actionResponse = typesCommands[action.type];

    return actionResponse ? actionResponse(state, action) : state;
  }
// /modules/about/actions.js
  // /about 页面的 action
  import {
    CHANGE_COUNT
  } from '../types-constant';

  export function changeCount(newCount) {
    return {
     type: CHANGE_COUNT,
     msg: newCount
    };
  }

4. 页面中使用

需要用到 next-redux-wrapper 提供的 withRedux 高阶函数,以及 react-redux 提供的 connect 高阶函数

import React, { Component } from 'react';
  import withRedux from 'next-redux-wrapper';
  import { connect } from 'react-redux';
  import { bindActionCreators } from 'redux';
  import AboutCom from '../components/About/index';
  import initializeStore from '../store/initializeStore';
  import { changeCount } from '../modules/about/actions';

  class About extends Component {
    constructor(props) {
     super(props);
    }
    render() {
     const { about: { count }, changeCount } = this.props;
     return <AboutCom count={count} changeCount={changeCount} />;
    }
  }

  const connectedPage = connect(
    state => ({ about: state.about }),
    dispatch => ({
     changeCount: bindActionCreators(changeCount, dispatch)
    })
  )(About);

  export default withRedux(initializeStore)(connectedPage);

 更多

查看 github官网

react-next github上一个next架构为主实现React服务端渲染的模板

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery当鼠标悬停时放大图片的效果实例
Jul 03 Javascript
JavaScript中的style.cssText使用教程
Nov 06 Javascript
判断访客终端类型集锦
Jun 05 Javascript
JavaScript中用于生成随机数的Math.random()方法
Jun 15 Javascript
jQuery除指定区域外点击任何地方隐藏DIV功能
Nov 13 jQuery
JS计算两个时间相差分钟数的方法示例
Jan 10 Javascript
详解如何在vue项目中使用eslint+prettier格式化代码
Nov 10 Javascript
JQuery animate动画应用示例
May 14 jQuery
微信小程序数据统计和错误统计的实现方法
Jun 26 Javascript
JavaScript 继承 封装 多态实现及原理详解
Jul 29 Javascript
vue中使用element组件时事件想要传递其他参数的问题
Sep 18 Javascript
JS前后端实现身份证号验证代码解析
Jul 23 Javascript
vue.js引入外部CSS样式和外部JS文件的方法
Jan 06 #Javascript
Bootstrap4 gulp 配置详解
Jan 06 #Javascript
jQuery实现获取当前鼠标位置并输出功能示例
Jan 05 #jQuery
node.js连接mysql与基本用法示例
Jan 05 #Javascript
Node.js Buffer模块功能及常用方法实例分析
Jan 05 #Javascript
Node.js net模块功能及事件监听用法分析
Jan 05 #Javascript
JS无限级导航菜单实现方法
Jan 05 #Javascript
You might like
php adodb连接不同数据库
2009/03/19 PHP
排序算法之PHP版快速排序、冒泡排序
2014/04/09 PHP
ThinkPHP框架实现FTP图片上传功能示例
2019/04/08 PHP
解决 FireFox 下[使用event很麻烦] 的问题.
2006/08/22 Javascript
jQuery的实现原理的模拟代码 -2 数据部分
2010/08/01 Javascript
return false,对阻止事件默认动作的一些测试代码
2010/11/17 Javascript
ajax 同步请求和异步请求的差异分析
2011/07/04 Javascript
formValidator3.3的ajaxValidator一些异常分析
2011/07/12 Javascript
你必须知道的Javascript知识点之&quot;单线程事件驱动&quot;的使用
2013/04/23 Javascript
使用jquery自定义鼠标样式满足个性需求
2013/11/05 Javascript
jQuery实现点击文本框弹出热门标签的提示效果
2013/11/17 Javascript
jquery form表单序列化为对象的示例代码
2014/03/05 Javascript
JS使用ajax方法获取指定url的head信息中指定字段值的方法
2015/03/24 Javascript
教你如何终止JQUERY的$.AJAX请求
2016/02/23 Javascript
jquery使用Cookie和JSON记录用户最近浏览历史
2016/04/19 Javascript
微信小程序实战之顶部导航栏(选项卡)(1)
2020/06/19 Javascript
原生js封装运动框架的示例讲解
2017/10/01 Javascript
详解最新vue-cli 2.9.1的webpack存在问题
2017/12/16 Javascript
Vue.js 表单控件操作小结
2018/03/29 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
2019/03/07 Javascript
React+Antd+Redux实现待办事件的方法
2019/03/14 Javascript
微信小程序判断页面是否从其他页面返回的实例代码
2019/07/03 Javascript
react MPA 多页配置详解
2019/10/18 Javascript
Python设计模式之单例模式实例
2014/04/26 Python
Python中使用logging模块代替print(logging简明指南)
2014/07/09 Python
Python实现统计英文单词个数及字符串分割代码
2015/05/28 Python
Python正确重载运算符的方法示例详解
2017/08/27 Python
利用django+wechat-python-sdk 创建微信服务器接入的方法
2019/02/20 Python
canvas 绘图时位置偏离的问题解决
2020/09/16 HTML / CSS
便利店投资创业计划书
2014/02/08 职场文书
致铅球运动员加油稿
2014/02/13 职场文书
医学生就业推荐表自我鉴定
2014/03/26 职场文书
2014年学校财务工作总结
2014/12/06 职场文书
文明单位创建材料
2014/12/24 职场文书
个人委托书范文
2015/01/28 职场文书
就业推荐表自我评价范文
2015/03/02 职场文书