当前位置:网站首页>Écoutez le fichier markdown et mettez à jour Hot next. Page JS

Écoutez le fichier markdown et mettez à jour Hot next. Page JS

2022-06-24 23:10:00 Jane Dow.

Original: ANGLAIS:https://gauliang.github.io/blogs/2022/watch-markdown-files-and-hot-load-the-nextjs-page/

Next.js Offre Fast-Refresh Capacité,Ça peut vous aider à React Les modifications apportées par le composant fournissent une rétroaction immédiate.
Mais,Quand tu passes Markdown Lorsque le document fournit le contenu du site,Parce que Markdown Non, pas du tout. React Components,La mise à jour à chaud échouera.

Comment?

La solution à ce problème peut être envisagée sous les aspects suivants:

  1. Comment le serveur surveille les mises à jour de fichiers
  2. Comment le serveur informe le navigateur
  3. Comment le navigateur met à jour la page
  4. Comment obtenir les dernières Markdown Contenu
  5. Comment Next.js Les serveurs de développement démarrent ensemble

Surveiller les mises à jour des fichiers

Accord: markdown Les documents sont conservés dans Next.js Sous la racine du projet _contents/ Moyenne

Adoption node:fs.watch Surveillance récursive des modules _contents Table des matières,Quand le document change,Déclencheur listener Mise en œuvre.
Nouveau fichier scripts/watch.js Surveillance _contents Table des matières.

const { watch } = require('node:fs');

function main(){
    watch(process.cwd() + '/_contents', { recursive: true }, (eventType, filename) => {
        console.log(eventType, filename)
    });
}

Le serveur passe WebSocket Connexion au navigateur , Lorsque le serveur de développement découvre un changement de fichier ,Adoption WS Aviser le navigateur de mettre à jour la page .
Le navigateur doit savoir si le fichier mis à jour est lié au routage de la page courante. ,Donc,, Le message envoyé par le serveur au navigateur doit contenir au moins le courant
Mettre à jour le routage de la page pour le fichier .

WebSocket

ws Est simple et facile à utiliser、 Très rapide et entièrement testé WebSocket Mise en œuvre du client et du serveur.Adoption ws Démarrage WebSocket Serveur.

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 }))
        })
    })
}

Créer un nouveau HotLoad Components, Responsable de l'écoute des messages du serveur , Mise à jour de la page . Le composant satisfait aux exigences suivantes: :

  1. Maintenir un lien avec WebSocekt Server Connexion à
  2. Après avoir écouté les messages du serveur , Déterminer si le routage actuel de la page est lié au changement de fichier , Non pertinent ignoré
  3. Les messages du serveur peuvent être envoyés intensivement , Nécessite un traitement anti - bavardage lors du chargement d'une nouvelle version du contenu
  4. Chargement Markdown Fichier et mise à jour complète
  5. Ce composant n'est disponible qu'en Modèle de développement Au travail.
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

Aperçu des données API

Créer un aperçu des données API,Lire Markdown Contenu du fichier, Et compilé dans le format utilisé pour le rendu de page .Les résultats ici
Doit être compatible avec [...id].tsx Dans la page getStaticProps() La méthode renvoie une structure de données de page entièrement cohérente ,Autres
La logique peut être directement réutilisée .

Nouveau API Documentation 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)
    }
}

Mise à jour de la page

Page pages/[...id].tsx Introduction de HotLoad Components,Et passer setPostData() Et params Voilà. 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

Démarrer le script

Mise à jour package.json De dev Script:

"scripts": {
    "dev": "node scripts/watch.js & \n next dev"
},

Résumé

Ce qui précède, Aperçu général de la logique de mise en oeuvre . Lors de l'atterrissage d'un projet spécifique , Quelques détails à considérer ,
Par exemple:: Vous souhaitez pouvoir demander un nom de fichier plus élevé sur la ligne de commande lors de la mise à jour du fichier 、 Ajuster la logique de correspondance entre le fichier et le routage en fonction de l'information de routage personnalisée .

Next.js Version originale du blog :https://gauliang.github.io/blogs/2022/watch-markdown-files-and-hot-load-the-nextjs-page/

原网站

版权声明
本文为[Jane Dow.]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206241941288699.html