ฉันใช้ Framework React Server Next.js บล็อกถ้าคุณชอบให้การสนับสนุน Star https://github.com/weibozzz/next-blog ที่อยู่ออนไลน์: http://www.liuweibo.cn โครงการนี้ใช้การแบ่งปันประสบการณ์ต่อไป: http://www.liuweibo.cn/p/206 นอกจากนี้ https://github.com/weibozz/weibozz.github.io
คำอธิบายสถาปัตยกรรมซอฟต์แวร์ react.js next.js antd mysql node koa2 fetch
ป้อน iSshow ของ env.js ภายใต้โฟลเดอร์ config และตั้งค่าเป็นจริง ที่นี่ฉันเพิ่งเรียกอินเทอร์เฟซออนไลน์ของตัวเอง แน่นอนคุณสามารถดูได้เท่านั้นและไม่แก้ไขอินเทอร์เฟซ หากเป็นเท็จไม่สามารถปรับอินเทอร์เฟซและคุณต้องเขียนอินเทอร์เฟซด้วยตัวเอง
cnpm i
npm run devcnpm i
npm run build
npm startเราจะใช้เว็บไซต์ส่วนบุคคลที่พัฒนาขึ้นด้วยความช่วยเหลือของ Next.js และที่อยู่ออนไลน์ http://www.liuweibo.cn เพื่อสรุปประสบการณ์และประสบการณ์ในการใช้การพัฒนาหลังจากเสร็จสิ้น ซอร์สโค้ด gtihub https://github.com/weibozzz/next-blog ถ้าคุณชอบให้การสนับสนุน Star
มาพูดถึงประเด็นสำคัญที่นี่
server.js ใช้ express อย่างเป็นทางการที่นี่และเปิดใช้งานการบีบอัด gzip ในเวลาเดียวกัน
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 การจัดเก็บจะเหมือนกับการใช้งานปฏิกิริยาทั่วไปและส่วนหัวและส่วนท้ายสามารถวางไว้ที่นี่และ _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 ใช้เพื่อข้ามไปยังหน้าและใช้เพื่อเปลี่ยน http: //***.com? id = 1 เป็นสวย/id/1head สามารถทำรังเมตาแท็กสำหรับ 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 ) สร้างโฟลเดอร์ 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 ,
}
}
) มันให้ความรู้สึกเหมือน scope ของ vue 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
} ) ; 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)
-
เมื่อมีการเยี่ยมชมครั้งใหญ่คุณต้องแคชข้อมูล
CDN โหนดดูวันที่ภาพ
คำอธิบายภาพการกำหนดค่าและการเปลี่ยนแปลง
การอัปโหลดรูปภาพคุณภาพสูงยังไม่รองรับการอัปโหลดการอัปโหลดการปรับปรุงรหัส
อัปโหลดเป็นข้อผิดพลาด 1m ที่แน่นอน
หลังจากเข้าสู่ระบบสนับสนุนบทความที่ชื่นชอบและแก้ไขความคิดเห็น
หากบทความก่อนหน้านี้ถูกลบ ID การเพิ่มขึ้นของตัวเองจะไม่เพิ่มขึ้นตัวเอง 1 และคุณต้องสอบถามฐานข้อมูล
กรอกรหัส Markdown เพื่อเน้นคล้ายกับนักเก็ต
รุ่นที่จะรวมในวันนั้น
contentEditableGitHub: https: //github.com/weibozzz
บล็อกส่วนตัว: http://www.liuweibo.cn
segmentfault: https: //segmentfault.com/u/weibozzz
แพลตฟอร์มสาธารณะ: Weibo Frontend
ผู้แต่ง: Liu Weibo
ลิงค์: http://www.liuweibo.cn/p/206
ที่มา: บล็อกของ Liu Weibo
ลิขสิทธิ์ดั้งเดิมของบทความนี้เป็นของ Liu Weibo โปรดระบุแหล่งที่มาเมื่อพิมพ์ซ้ำ ขอบคุณสำหรับความร่วมมือ