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 :

  1. How the server monitors file updates
  2. How the server notifies the browser
  3. How the browser updates the page
  4. How to get the latest Markdown Content
  5. 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 :

  1. Maintain a singleton pattern with WebSocekt Server The connection of
  2. After listening to the server message , Determine whether the current page route is related to the changed file , Ignore if irrelevant
  3. Server side messages may be sent intensively , You need to do anti shake processing when loading new version content
  4. load Markdown File and complete the update
  5. This component is only available in Development mode Work 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<Data>
) {
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} - Gauliang</title>
</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/

monitor Markdown File and hot update Next.js More related articles on the page

  1. ORACLE clear 、 Truncate listening log file (listener.log)

    stay ORACLE In the database , If you don't listen to log files (listener.log) Cut off , So listen to log files (listener.log) It's going to get bigger and bigger , Many people must have heard about "LISTENER.LOG Japan ...

  2. ORACLE The listening log file is too large. Stopping writing the listening log causes the database connection to fail

    The production library listening log file is too large ( achieve 4G many ), Find out oracle Stop writing listening logs , Inspection parameters log_file,log_directory,log_status All normal , The database is running normally . It is confirmed that the listening log is too large ...

  3. File download Controller, Folder content monitoring , Upload files , Run the program through url Realize file download

    File download Controller @RequestMapping("/fileDownLoad") public ResponseEntity<byte[]> fileDo ...

  4. Oracle Database operation and maintenance : Listen to the log file (listener.log) Do regular cleaning , If you don't clean up regularly , There are some problems

    Link to the original text : http://www.lookdaima.com/WebForms/WebPages/Blanks/Pm/Docs/DocItemDetail.aspx?EmPreviewTypeV=2& ...

  5. monitor Documents The files in the folder have changed

    // When Documents When the internal file changes , Start the timer , The size is calculated every second , When the size does not change, the transmission is completed , Start refreshing . @property (nonatomic, strong) NSTimer *t ...

  6. Xlua The file is called in the hot update

    Xlua The file is called in the hot update public class news : MonoBehaviour { LuaEnv luaEnv;// Definition Lua Initial variable void Awake() { luaEnv ...

  7. Vue Event monitoring to achieve the top effect of navigation bar ( Scroll the page and locate it )

    Vue Event monitoring to achieve the top effect of navigation bar ( Scroll the page and locate it ) Howie126313  Focus on 2017.11.19 15:05*  Number of words 100  read 3154 Comment on 0 like 0 The so-called ceiling effect is that there is no sliding on the page ...

  8. Webpack Multiple entry files 、 Hot update and other experiences

    Webpack Today's popular front-end packaging tools , Today, I'd like to share my learning experience . One .html-webpack-plugin Realization html Analysis and generation of template file stay plugins Join in HtmlWebpackPlug ...

  9. arcgis engine monitor element The addition of 、 Update and delete Events ( Use IGraphicsContainerEvents)

    IGraphicsContainerEvents Interface How to listen element event ? Such as , When we're in Mapcontrol Add . Delete . Updated a Element after , How to capture this event ?   ...

  10. apache host ( Website ) To configure ,port monitor , Folder access and distributed access

    Preface The two core messages of a website are : Host name (server name / The websites ):ServerName server name Site location ( Site folder path ):DocumentRoot " The actual physical path " ...

Random recommendation

  1. ORACLE How to view the progress of index reconstruction

    stay ORACLE In the database , If a large index takes a long time to rebuild , So how to check the time spent in index reconstruction , And how much has been done ( The proportion ) What about it , We can go through V$SESSION_LONGOPS View to see how the index is rebuilt ...

  2. pycharm Garbled

    1. 'gbk' codec can't encode character u'\xb8' terms of settlement import sys reload(sys)sys.setdefaultencoding('utf ...

  3. Express inquiry API Interface docking method

    All kinds of interfaces Express inquiry API There are instant query and subscription query , Data is returned on request , Subscription is to subscribe the express bill number to the interface , If the logistics track is updated, the data will be returned in full . At present, express birds are commonly used . Courier 100. Express network, etc . Express bird instant API You can query 3 ...

  4. Apache+Subversion+TortoiseSVN

    Key words: dav_svn, apache, subversion, tortoisesvn # install apache2 sudo apt-get install libapache ...

  5. Xeon Phi 《 Coprocessor high performance Programming Guide 》 With the book code arrangement part 3

    Chapter two , A few simple procedures ● Code , Single thread #include <stdio.h> #include <stdlib.h> #include <string.h> ...

  6. MVC Log4Net To configure

    1. quote log4net.dll 2. Add... In the project root directory log4.config file <?xml version="1.0"?> <configuration> ...

  7. [TF] Architecture - Computational Graphs

    Reading notes : I just hope to have some necessary perceptual knowledge of the bottom , Including some basic core concepts . Here Focus on the Graph relevant , Because it's good for programming . TF – Kernels For the module part, see :https://mp.weixin.qq.c ...

  8. spring cloud: zuul( 3、 ... and ): ribbon Load balancing configuration

    zuul Of routes Under configuration path/url The combination does not support load balancing Let's introduce zuul Of routes The configuration of the path/serviceId Load balancing configuration spring-boot-user Microservice is on :7901, ...

  9. cocos2d-x Way of learning ( One )—— install cocos2d-x

    These two days, I want to pygame and SDL Switch to cocos2d-x On ( Mainly for cross platform development ), So here's how to install cocos2d-x. First, go to the official website to download cocos2d-x: Portal Click... On the menu bar above Produc ...

  10. C++ Multithreading , Mutually exclusive , Sync

    Synchronization and mutual exclusion When there are multiple threads , It is often necessary to synchronize these threads to access the same data or resource . for example , Suppose there is a program , One of the threads is used to read files into memory , Another thread counts the number of characters in the file . Of course , Before transferring the entire file into memory , ...