react ssr 框架next.js开发个人网站心得

前言

完全借助于 next.js 开发的个人网站,线上地址 http://www.liuweibo.cn 总结一下开发完成后的心得和使用体会。gtihub源码https://github.com/Weibozzz/next-blog

为什么使用服务器端渲染(SSR)?

  • 网站是要推广的,所以需要更好的 SEO,搜索引擎可以抓取完整页面
  • 访问速度,更快的加载静态页面

网站使用技术

  • 前端:React(16.x) Next.js antd-design fetch Less
  • 后端:node框架koa和mysql (目前前后端分离,这里只负责写接口,和平常的ajax获取接口一样,这里就不开放源码了)
  • 网站目的:业余学习,记录技术文章,学以致用
  • 网站功能
    • 发布文章
    • 修改文章(增删改查)
    • 用户评论

源码剖析

这里就只讲重点了

入口文件server.js

这里用的官方提供的express,同时开启gzip压缩

const express = require(@apos;express@apos;)
const next = require(@apos;next@apos;)

const compression = require(@apos;compression@apos;)
const dev = process.env.NODE_ENV !== @apos;production@apos;
const app = next({ dev })
const handle = app.getRequestHandler()
let port= dev?4322:80

app.prepare()
  .then(() => {
    const server = express()

    if (!dev) {
      server.use(compression()) //gzip
    }
    //文章二级页面
    server.get(@apos;/p/:id@apos;, (req, res) => {
      const actualPage = @apos;/detail@apos;
      const queryParams = { id: req.params.id }
      app.render(req, res, actualPage, queryParams)
    })

    server.get(@apos;*@apos;, (req, res) => {
      return handle(req, res)
    })

    server.listen(port, (err) => {
      if (err) throw err
      console.log(@apos;> Ready on http://localhost @apos;+port)
    })
  })
  .catch((ex) => {
    process.exit(1)
  })

page根组件_app.js

用于传递redux数据,store就和普通react用法一样了,还有header和footer可以放在这里,同理还有_err.js用于处理404页面


import App, {Container} from @apos;next/app@apos;
import React from @apos;react@apos;
import {withRouter} from @apos;next/router@apos; // 接入next的router
import withReduxStore from @apos;../lib/with-redux-store@apos; // 接入next的redux
import {Provider} from @apos;react-redux@apos;


class MyApp extends App {
  render() {

    const {Component, pageProps, reduxStore, router: {pathname}} = this.props;
    return (
      <Container>
        <Provider store={reduxStore}>
         <Component {...myPageProps}  />
        Provider>

      Container>
    )
  }
}

export default withReduxStore(withRouter(MyApp))

网站的服务端渲染页面Blog页面

  • link用于跳转页面,利用as把原本的http://*.com?id=1变为漂亮的 /id/1
  • head可以嵌套meta标签进行seo
  • 配置不需要seo的组件
import dynamic from @apos;next/dynamic@apos;;

//不需要seo
const DynasicTopTipsNoSsr = dynamic(import(@apos;../../components/TopTips@apos;),{
  ssr:false
})

import React, {Component} from @apos;react@apos;
import {connect} from @apos;react-redux@apos;
import Router from @apos;next/router@apos;
import @apos;whatwg-fetch@apos; // 用于fetch请求数据
import Link from @apos;next/link@apos;; // next的跳转link
import Head from @apos;next/head@apos;  // next的跳转head可用于seo

class Blog extends Component {

  render() {
    return (
      <div className="Blog">
        <Head>
          <title>{BLOG_TXT}»{COMMON_TITLE}title>
        Head>
        <MyLayout>
          <Link   as={`/Blog/${current}`} href={`/Blog?id=${current}`}>
            <a onClick={this.onClickPageChange.bind(this)}>{current}a>
          Link>
        MyLayout>
      div>
    )
  }
}
//这里才是重点,getInitialProps方法来请求数据进行渲染,达到服务端渲染的目的
Blog.getInitialProps = async function (context) {
  const {id = 1} = context.query
  let queryStringObj = {
    type: ALL,
    num: id,
    pageNum
  }
  let queryTotalString = {type: ALL};
  const pageBlog = await fetch(getBlogUrl(queryStringObj))
  const pageBlogData = await pageBlog.json()


  return {pageBlogData}
}
// 这里根据需要传入redux
const mapStateToProps = state => {
  const {res, searchData, searchTotalData} = state
  return {res, searchData, searchTotalData};
}
export default connect(mapStateToProps)(Blog)

静态资源

根目录创建static文件夹,这里是强制要求,否则加载不到静态资源

配置antd和主题并且按需加载

主题配置

antd-custom.less

@primary-color: #722ED0;

@layout-header-height: 40px;
@border-radius-base: 0px;

styles.less

@import "~antd/dist/antd.less";
@import "./antd-custom.less";

最后统一配置在公共head

<Head>
    <meta charSet="utf-8"/>
    <meta httpEquiv="X-UA-Compatible" content="IE=edge, chrome=1"/>
    <meta name="viewport"
          content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
    <meta name="renderer" content="webkit"/>
    <meta httpEquiv="description" content="刘伟波-天天向上"/>
    <meta name="author" content="刘伟波,liuweibo"/>
    <link rel=@apos;stylesheet@apos; href=@apos;/_next/static/style.css@apos;/>
    <link rel=@apos;stylesheet@apos; type=@apos;text/css@apos; href=@apos;/static/nprogress.css@apos; />
    <link rel=@apos;shortcut icon@apos; type=@apos;image/x-icon@apos; href=@apos;/static/favicon.ico@apos; />
  Head>

按需加载配置

.babelrc文件

{
  "presets": ["next/babel"],
  "plugins": [
    "transform-decorators-legacy",
    [
      "import",
      {
        "libraryName": "antd",
        "style": "less"
      }
    ]
  ]
}

next.config.js文件配置

const withLess = require(@apos;@zeit/next-less@apos;)

module.exports =   withLess(
  {
    lessLoaderOptions: {
      javascriptEnabled: true,
      cssModules: true,

    }
  }
)

页面css

感觉和vuescope一样,stylejsx,加了global为全局,否则只在这里生效

render() {

    return (
      <Container>
        <Provider store={reduxStore}>
          <Component {...myPageProps}  />
        Provider>

        <style jsx global>{`

.fl{ float: left;
}
.fr{
    float: right;
}
        `}style>
      Container>
    )

页面顶部加载进度条

import Router from @apos;next/router@apos;
import NProgress from @apos;nprogress@apos;

Router.onRouteChangeStart = (url) => {
  NProgress.start()
}
Router.onRouteChangeComplete = () => NProgress.done()
Router.onRouteChangeError = () => NProgress.done()

markdown发表文章和代码高亮

使用只需要marked(@apos;放入markdown字符串@apos;);

import marked from @apos;marked@apos;
import hljs from @apos;highlight.js@apos;;

hljs.configure({
  tabReplace: @apos;  @apos;,
  classPrefix: @apos;hljs-@apos;,
  languages: [@apos;CSS@apos;, @apos;HTML, XML@apos;, @apos;JavaScript@apos;, @apos;PHP@apos;, @apos;Python@apos;, @apos;Stylus@apos;, @apos;TypeScript@apos;, @apos;Markdown@apos;]
})
marked.setOptions({
  highlight: (code) => hljs.highlightAuto(code).value,
  gfm: true,
  tables: true,
  breaks: false,
  pedantic: false,
  sanitize: true,
  smartLists: true,
  smartypants: false
});

作者:刘伟波

链接:http://www.liuweibo.cn/p/206

来源:刘伟波博客

本文原创版权属于刘伟波 ,转载请注明出处,谢谢合作

你可能感兴趣的:(react ssr 框架next.js开发个人网站心得)