完全借助于 next.js 开发的个人网站,线上地址 http://www.liuweibo.cn 总结一下开发完成后的心得和使用体会。gtihub源码https://github.com/Weibozzz/next-blog
这里就只讲重点了
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)
})
用于传递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))
link
用于跳转页面,利用as把原本的http://*.com?id=1变为漂亮的 /id/1head
可以嵌套meta标签进行seoimport 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-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,
}
}
)
感觉和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 @apos;next/router@apos;
import NProgress from @apos;nprogress@apos;
Router.onRouteChangeStart = (url) => {
NProgress.start()
}
Router.onRouteChangeComplete = () => NProgress.done()
Router.onRouteChangeError = () => NProgress.done()
使用只需要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
来源:刘伟波博客
本文原创版权属于刘伟波 ,转载请注明出处,谢谢合作