当前位置:网站首页>Next. JS hot update markdown file change
Next. JS hot update markdown file change
2022-06-25 17:09:00 【qq_ forty-three million four hundred and seventy-nine thousand 】
High quality resource sharing
| Learning route guidance ( Click unlock ) | Knowledge orientation | Crowd positioning |
|---|---|---|
| 🧡 Python Actual wechat ordering applet 🧡 | Progressive class | This course is python flask+ Perfect combination of wechat applet , From the deployment of Tencent to the launch of the project , Create a full stack ordering system . |
| Python Quantitative trading practice | beginner | Take you hand in hand to create an easy to expand 、 More secure 、 More efficient quantitative trading system |
Next.js Provides Fast-Refresh Ability , It can help you to React The edits made by the component provide immediate feedback .
however , When you pass Markdown File provides website content , because Markdown No React Components , Hot update will fail .
How do you do it?
This problem can be solved from the following aspects :
- How the server monitors file updates
- How the server notifies the browser
- How the browser updates the page
- How to get the latest Markdown Content
- How to communicate with Next.js Start up with the development server
Monitoring file updates
Appointment : markdown The documents are stored in Next.js In the root directory of the project
_contents/in
adopt node:fs.watch Module recursive monitoring _contents Catalog , When the document changes , Trigger listener perform .
New file scripts/watch.js monitor _contents Catalog .
const { watch } = require('node:fs');
function main(){
watch(process.cwd() + '/\_contents', { recursive: true }, (eventType, filename) => {
console.log(eventType, filename)
});
}
Notification browser
Server through WebSocket Connect to the browser , When the development server finds that the file changes , adopt WS Notify the browser to update the page .
The browser needs to know whether the updated file is related to the route of the current page , therefore , The message sent by the server to the browser should at least contain the current
Update the page route corresponding to the file .
WebSocket
ws It's easy to use 、 Extremely fast and fully tested WebSocket Client and server implementation . adopt ws start-up WebSocket The server .
const { watch } = require('node:fs');
const { WebSocketServer } = require('ws')
function main() {
const wss = new WebSocketServer({ port: 80 })
wss.on('connection', (ws, req) => {
watch(process.cwd() + '/\_contents', { recursive: true }, (eventType, filename) => {
const path = filename.replace(/\.md/, '/')
ws.send(JSON.stringify({ event: 'markdown-changed', path }))
})
})
}
The browser connects to the server
Create a new one HotLoad Components , Be responsible for listening for messages from the server , And hot page updates . The components meet the following requirements :
- Maintain a singleton pattern with WebSocekt Server The connection of
- After listening to the server message , Determine whether the current page route is related to the changed file , Ignore if irrelevant
- Server side messages may be sent intensively , You need to do anti shake processing when loading new version content
- load Markdown File and complete the update
- This component is only available in
Development modeWork under the
import { useRouter } from "next/router"
import { useEffect } from "react"
interface Instance {
ws: WebSocket
timer: any
}
let instance: Instance = {
ws: null as any,
timer: null as any
}
function getInstance() {
if (instance.ws === null) {
instance.ws = new WebSocket('ws://localhost')
}
return instance
}
function \_HotLoad({ setPost, params }: any) {
const { asPath } = useRouter()
useEffect(() => {
const instance = getInstance()
instance.ws.onmessage = async (res: any) => {
const data = JSON.parse(res.data)
if (data.event === 'markdown-changed') {
if (data.path === asPath) {
const post = await getPreviewData(params)
setPost(post)
}
}
}
return () => {
instance.ws.CONNECTING && instance.ws.close(4001, asPath)
}
}, [])
return null
}
export function getPreviewData(params: {id:string[]}) {
if (instance.timer) {
clearTimeout(instance.timer)
}
return new Promise((resolve) => {
instance.timer = setTimeout(async () => {
const res = await fetch('http://localhost:3000/api/preview/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
})
resolve(res.json())
}, 200)
})
}
let core = ({ setPost, params }: any)=>null
if(process.env.NODE\_ENV === 'development'){
console.log('development hot load');
core = _HotLoad
}
export const HotLoad = core
Data preview API
Create data preview API, Read Markdown The contents of the document , And compile it into the format used for page rendering . The results here
Should and [...id].tsx On the page getStaticProps() Method returns a page with exactly the same data structure , relevant
Logic can be reused directly .
newly build API file pages/api/preview.ts,
import type { NextApiRequest, NextApiResponse } from 'next'
import { getPostData } from '../../lib/posts'
type Data = {
name: string
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (process.env.NODE\_ENV === 'development') {
const params = req.body
const post = await getPostData(['posts', ...params.id])
return res.status(200).json(post)
} else {
return res.status(200)
}
}
Update page
page pages/[...id].tsx Introduction in HotLoad Components , And transmission setPostData() And params to HotLoad Components .
...
import { HotLoad } from '../../components/hot-load'
const Post = ({ params, post, prev, next }: Params) => {
const [postData, setPostData] = useState(post)
useEffect(()=>{
setPostData(post)
},[post])
return (
<Layout>
<Head>
<title>{postData.title} - Gauliangtitle>
Head>
<PostContent post={postData} prev={prev} next={next} />
<BackToTop />
<HotLoad setPost={setPostData} params={params} />
Layout>
)
}
export async function getStaticProps({ params }: Params) {
return {
props: {
params,
post:await getPostData(['posts', ...params.id])
}
}
}
export async function getStaticPaths() {
const paths = getAllPostIdByType()
return {
paths,
fallback: false
}
}
export default Post
The startup script
to update package.json Of dev Script :
"scripts": {
"dev": "node scripts/watch.js & \n next dev"
},
summary
Above , Overall overview of the general implementation logic . When the specific project is implemented , There are some details to consider ,
Such as : When updating a file, you want to prompt for a different file name on the command line 、 Adjust the matching logic between file and route according to personalized route information .
Next.js Original blog version :https://gauliang.github.io/blogs/2022/watch-markdown-files-and-hot-load-the-nextjs-page/
边栏推荐
- 【黑苹果】联想拯救者Y70002019PG0
- 居家办公让我绩效拿了C | 社区征文
- Differences between et al and etc
- [Jianzhi offer II 091. painting the house]
- 剑指 Offer II 035. 最小时间差
- Kotlin
- Apijson simple to use
- 社交电商如何运营推广?
- "Podcast with relish" 386 Yuan Tang Hua Yuan Shi: who is not a "Mr. White character"?
- Notes: lbcf: a Large Scale budget Constrained causal Forest Algorithm
猜你喜欢

Optimization of lazyagg query rewriting in parsing data warehouse

学习太极创客 — MQTT(二)MQTT 基本原理

解析数仓lazyagg查询重写优化

Redis系列——概述day1-1

Sword finger offer 50 First character that appears only once

【剑指 Offer II 091. 粉刷房子】

XShell连接VMWare虚拟机

剑指 Offer 50. 第一个只出现一次的字符

剑指 Offer 39. 数组中出现次数超过一半的数字

Pytorch official document learning record
随机推荐
万卷书 - 大力娃的书单
剑指 Offer 39. 数组中出现次数超过一半的数字
千万级购物车系统缓存架构方案
Redis 的PSYNC命令
redis 分布式锁整理
[proficient in high concurrency] deeply understand the basics of assembly language
n-queens problem
How to talk about salary correctly in software testing interview
Home office earned me C | community essay
ES6知识点
Best practices for data relocation: using CDM to relocate offline Mysql to DWS
Wireshark网卡无法找到或没有显示的问题
js禁止浏览器默认事件
Tasklet API usage
心情
Differences between et al and etc
FreeRTOS内核时钟不对的问题解决
Sword finger offer 50 First character that appears only once
【黑苹果】联想拯救者Y70002019PG0
1-8file sharing in VMWare