利用react服务端框架next.js写的博客,喜欢就给个Star支持一下。
https://github.com/Weibozzz/next-blog
线上地址: http://www.liuweibo.cn
本项目使用next.js经验分享:http://www.liuweibo.cn/p/206javascript
软件架构说明react.js next.js antd mysql node koa2 fetch
css
网站功能html
1.快速开始
虽然是服务端渲染,可是也要调用接口,因此须要调用后端的接口前端
进入config文件夹下的env.js的isShow设置为true,这里只是调用了我本身线上的接口,固然你
只能看不能修改接口哦。若是为false则调不到接口,须要本身去写接口。vue
2.运行java
cnpm i npm run dev
3.部署node
cnpm i npm run build npm start
1.详情页
2.列表页
3.编辑页面和发布文章,上传图片到七牛云mysql
彻底借助于 next.js 开发的我的网站,线上地址 http://www.liuweibo.cn 总结一下开发完成后的心得和使用体会。gtihub源码 https://github.com/Weibozzz/next-blog。喜欢就给个Star支持一下。
网站功能react
这里就只讲重点了
server.js
这里用的官方提供的express
,同时开启gzip
压缩git
const express = require('express') const next = require('next') const compression = require('compression') const dev = process.env.NODE_ENV !== 'production' 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('/p/:id', (req, res) => { const actualPage = '/detail' const queryParams = { id: req.params.id } app.render(req, res, actualPage, queryParams) }) server.get('*', (req, res) => { return handle(req, res) }) server.listen(port, (err) => { if (err) throw err console.log('> Ready on http://localhost ' port) }) }) .catch((ex) => { process.exit(1) })
用于传递redux数据,store就和普通react用法同样了,还有header和footer能够放在这里,同理还有_err.js
用于处理404页面
import App, {Container} from 'next/app' import React from 'react' import {withRouter} from 'next/router' // 接入next的router import withReduxStore from '../lib/with-redux-store' // 接入next的redux import {Provider} from 'react-redux' 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))
link
用于跳转页面,利用as把本来的http://*.com?id=1变为漂亮的 /id/1head
能够嵌套meta标签进行seoimport dynamic from 'next/dynamic'; //不须要seo const DynasicTopTipsNoSsr = dynamic(import('../../components/TopTips'),{ ssr:false }) import React, {Component} from 'react' import {connect} from 'react-redux' import Router from 'next/router' import 'whatwg-fetch' // 用于fetch请求数据 import Link from 'next/link'; // next的跳转link import Head from 'next/head' // 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-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='stylesheet' href='/_next/static/style.css'/> <link rel='stylesheet' type='text/css' href='/static/nprogress.css' /> <link rel='shortcut icon' type='image/x-icon' href='/static/favicon.ico' /> </Head>
.babelrc
文件
{ "presets": ["next/babel"], "plugins": [ "transform-decorators-legacy", [ "import", { "libraryName": "antd", "style": "less" } ] ] }
next.config.js
文件配置
const withLess = require('@zeit/next-less') module.exports = withLess( { lessLoaderOptions: { javascriptEnabled: true, cssModules: true, } } )
感受和vue
的scope
同样,style
的jsx
,加了global
为全局,不然只在这里生效
render() { return ( <Container> <Provider store={reduxStore}> <Component {...myPageProps} /> </Provider> <style jsx global>{` .fl{ float: left; } .fr{ float: right; } `}</style> </Container> )
import Router from 'next/router' import NProgress from 'nprogress' Router.onRouteChangeStart = (url) => { NProgress.start() } Router.onRouteChangeComplete = () => NProgress.done() Router.onRouteChangeError = () => NProgress.done()
使用只须要marked('放入markdown字符串');
import marked from 'marked' import hljs from 'highlight.js'; hljs.configure({ tabReplace: ' ', classPrefix: 'hljs-', languages: ['CSS', 'HTML, XML', 'JavaScript', 'PHP', 'Python', 'Stylus', 'TypeScript', 'Markdown'] }) marked.setOptions({ highlight: (code) => hljs.highlightAuto(code).value, gfm: true, tables: true, breaks: false, pedantic: false, sanitize: true, smartLists: true, smartypants: false });
contentEditable
做者:刘伟波
连接:http://www.liuweibo.cn/p/206
来源:刘伟波博客
本文原创版权属于刘伟波 ,转载请注明出处,谢谢合做