J'utilise le blog React Server Framework.js, si vous l'aimez, donnez la prise en charge de Star. https://github.com/weibozzz/next-log Adresse en ligne: http://www.liuweibo.cn Ce projet utilise le partage d'expérience Next.js: http://www.liuweibo.cn/p/206 Il existe également un entrepôt pour établir son propre système de connaissances frontal: https://github.com/weibozz/weibozz.github.io
Description de l'architecture logicielle react.js next.js antd mysql node koa2 fetch
Entrez l'iSShow de Env.js sous le dossier Config et définissez-le sur true . Ici, j'appelle juste ma propre interface en ligne. Bien sûr, vous ne pouvez le regarder et ne pas modifier l'interface. S'il est faux, l'interface ne peut pas être ajustée et vous devez écrire l'interface vous-même.
cnpm i
npm run devcnpm i
npm run build
npm startNous utiliserons le site Web personnel entièrement développé avec l'aide de next.js, et l'adresse en ligne http://www.liuweibo.cn pour résumer l'expérience et l'expérience de l'utilisation du développement après la fin. GTIHUB Code source https://github.com/weibozzz/next-log. Si vous l'aimez, apportez un support Star.
Parlons simplement des points clés ici
server.js Utilisez l' express officiel ici et activez la compression gzip en même temps
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 )
} ) Utilisé pour passer les données Redux, le magasin est le même que l'utilisation de la réaction ordinaire, et l'en-tête et le pied de page peuvent être placés ici, et _err.js est utilisé pour traiter 404 pages
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 est utilisé pour passer aux pages et utiliser comme pour modifier le http: //***.com? ID = 1 en un beau / id / 1head peut nidifier les étiquettes de méta pour le référencement 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 ) Créez un dossier static dans le répertoire racine. Il s'agit d'une exigence obligatoire, sinon la ressource statique ne sera pas chargée.
antd-custust
@primary-color : # 722ED0;
@layout-header-height : 40px;
@border-radius-base : 0px;styles sans
@import "~antd/dist/antd.less" ;
@import "./antd-custom.less" ; Enfin, la configuration est unifiée sur la head publique
< 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 > Fichier .babelrc
{
"presets" : [ " next/babel " ],
"plugins" : [
" transform-decorators-legacy " ,
[
" import " ,
{
"libraryName" : " antd " ,
"style" : " less "
}
]
]
}
Configuration du fichier next.config.js
const withLess = require ( '@zeit/next-less' )
module . exports = withLess (
{
lessLoaderOptions : {
javascriptEnabled : true ,
cssModules : true ,
}
}
) On dirait que scope de vue , style jsx , Ajouter global comme Global, sinon cela ne prendra effet ici.
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 ( ) Utiliser a juste besoin pour 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
} ) ; Configuration du fichier 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)
)
Lorsqu'il y a de grandes visites, vous devez mettre en cache des données
Date d'image d'affichage du nœud CDN
Description de l'image de configuration et modifications
Le téléchargement des images de haute qualité ne prend pas encore en charge le téléchargement, téléchargement des améliorations de code
Téléchargé comme un bug exactement 1m
Après vous être connecté, soutenir les articles préférés et modifier les commentaires
Si l'article précédent est supprimé, l'ID d'auto-augmentation n'est pas auto-augmentation 1 et vous devez interroger la base de données
Remplissez le code Markdown pour le mettre en surbrillance, similaire à Nuggets
Versions à fusionner ce jour-là
contentEditablegithub: https: //github.com/weibozzz
Blog personnel: http://www.liuweibo.cn
segmentfault: https: //segmentfault.com/u/weibozzz
Plateforme publique: Weibo Frontend
Auteur: Liu Weibo
Lien: http://www.liuweibo.cn/p/206
Source: le blog de Liu Weibo
Le droit d'auteur original de cet article appartient à Liu Weibo. Veuillez indiquer la source lors de la réimpression. Merci pour votre coopération.