Saya menggunakan blog React Server Framework Next.js, jika Anda suka, berikan dukungan bintang. https://github.com/weibozzz/next-blog Alamat online: http://www.liuweibo.cn Proyek ini menggunakan Berbagi pengalaman selanjutnya: http://www.liuweibo.cn/p/206 Ada juga Warehouse untuk membangun front-end-end-end-nya sendiri. https://github.com/weibozz/weibozz.github.io
Deskripsi Arsitektur Perangkat Lunak react.js next.js antd mysql node koa2 fetch
Masukkan isshow dari env.js di bawah folder konfigurasi dan atur ke true . Di sini saya hanya memanggil antarmuka online saya sendiri. Tentu saja, Anda hanya dapat menontonnya dan tidak memodifikasi antarmuka. Jika salah, antarmuka tidak dapat disesuaikan dan Anda perlu menulis antarmuka sendiri.
cnpm i
npm run devcnpm i
npm run build
npm startKami akan menggunakan situs web pribadi yang dikembangkan sepenuhnya dengan bantuan Next.js, dan alamat online http://www.liuweibo.cn untuk meringkas pengalaman dan pengalaman menggunakan pengembangan setelah selesai. Kode sumber gtihub https://github.com/weibozzz/next-blog. Jika Anda menyukainya, berikan dukungan bintang.
Mari kita bicarakan poin -poin penting di sini
server.js Gunakan express Resmi di sini, dan aktifkan kompresi gzip secara bersamaan
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 )
} ) Digunakan untuk meneruskan data redux, menyimpan sama dengan penggunaan reaksi biasa, dan header dan footer dapat ditempatkan di sini, dan _err.js digunakan untuk memproses 404 halaman
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 digunakan untuk melompat ke halaman, dan menggunakan untuk mengubah http: //***.com asli? Id = 1 menjadi indah/id/1head dapat bersarang meta tag untuk SEO import 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 ) Buat folder static di direktori root. Ini adalah persyaratan wajib, jika tidak sumber daya statis tidak akan dimuat.
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" ; Akhirnya, konfigurasi disatukan di head publik
< 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 > file .babelrc
{
"presets" : [ " next/babel " ],
"plugins" : [
" transform-decorators-legacy " ,
[
" import " ,
{
"libraryName" : " antd " ,
"style" : " less "
}
]
]
}
Konfigurasi File next.config.js
const withLess = require ( '@zeit/next-less' )
module . exports = withLess (
{
lessLoaderOptions : {
javascriptEnabled : true ,
cssModules : true ,
}
}
) Rasanya seperti scope vue , style jsx , tambahkan global sebagai global, jika tidak, ia hanya akan berlaku di sini.
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 ( ) Gunakan hanya perlu 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
} ) ; Konfigurasi File next.config.js
module . exports = {
webpack ( config , ... args ) {
return config ;
}
} config.resolve.alias = {
...config.resolve.alias,
'@': path.resolve(__dirname, './'),
}
config.plugins.push(
new webpack.DefinePlugin({
'process.env.NODE_ENV': process.env.NODE_ENV
})
)
config.module.rules.push(
{
test: /.svg(?v=d+.d+.d+)?$/,
use: [
{
loader: 'babel-loader'
},
{
loader: '@svgr/webpack',
options: {
babel: false,
icon: true
}
}
]
}
)
config = withCSS()
.webpack(config, ...args)
config = withLess()
.webpack(config, ...args)
const loaderUtils = require('loader-utils')
const fs = require('fs')
const path = require('path')
const cssModuleRegex = /.module.less$/
config = withLess(
// 开启 css module 自定义
{
cssModules: true,
cssLoaderOptions: {
importLoaders: 1,
minimize: !args[0].dev,
getLocalIdent: (loaderContext, _, localName, options) => {
const fileName = path.basename(loaderContext.resourcePath)
if (cssModuleRegex.test(fileName)) {
const content = fs.readFileSync(loaderContext.resourcePath)
.toString()
const name = fileName.replace(/.[^/.]+$/, '')
const hash = args[0].dev ? `${name}___[hash:base64:5]` : '[hash:base64:5]'
const fileNameHash = loaderUtils.interpolateName(
loaderContext,
hash,
{ content }
)
return fileNameHash
}
return localName
}
}
}
)
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true'
})
config = withBundleAnalyzer({})
.webpack(config, ...args)
)
Saat ada kunjungan besar, Anda perlu mensembakan data
node cdn melihat tanggal gambar
Deskripsi dan Perubahan Gambar Konfigurasi
Mengunggah gambar berkualitas tinggi belum mendukung pengunggahan, mengunggah perbaikan kode
Diunggah sebagai bug 1m persis
Setelah masuk, mendukung artikel favorit dan memodifikasi komentar
Jika artikel sebelumnya dihapus, ID penangkapan diri tidak menabrak diri sendiri 1, dan Anda perlu menanyakan database
Isi Kode Markdown untuk menyorotnya, mirip dengan Nuggets
Versi untuk bergabung pada hari itu
contentEditableGitHub: https: //github.com/weibozzz
Blog Pribadi: http://www.liuweibo.cn
SegmentFault: https: //segmentfault.com/u/weibozzz
Platform Publik: Weibo Frontend
Penulis: Liu Weibo
Tautan: http://www.liuweibo.cn/p/206
Sumber: Blog Liu Weibo
Hak cipta asli dari artikel ini adalah milik Liu Weibo. Harap tunjukkan sumber saat mencetak ulang. Terima kasih atas kerja sama Anda.