利用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
來源:劉偉波博客
本文原創版權屬於劉偉波 ,轉載請註明出處,謝謝合做