使用next.js13 进行了相应的开发,总结日记
简要总结:根据项目选择合适的框架,很多情况下Create React App(CRA)已经满足绝大的需求。
简单介绍一下项目,需要构建一个展示界面(单界面)demo,所以next.js 强大的路由功能用不到,ssr渲染等优秀功能也用不到,但为了后续扩展需求,我还是决定使用next.js框架(提前学习布局)
本人使用的next.js 13 踩了不少坑 总结一下:
一。文件目录解析:
page.tsx 代码如下,注意的以下几点:
1、app下面的是路由界面,在app里面的文件夹就是指向路由,里面代表。所以我把组件代码放在外部 compentent中。里面page.tsx是 就是界面主要入口
2、 使用了类似单界面的风格,把服务端和客户端文件组合在一起, 此界面是server端
3.css方面使用了tailwind,使用官网路径:Tailwind CSS - 只需书写 HTML 代码
4.切记服务端代码不会执行 react的钩子,父子传参也是不执行的哦
import Main from './Main';
import React from 'react'
export default function page() {
return (
<div className="flex flex-col h-screen justify-between flex-nowrap">
<header className='basis-1/20 bg-[#3e4a62] text-white flex items-center '>
<div className='ml-5 '>阵列监测</div>
</header>
<Main/>
</div>
)
}
二 客户端文件解析:
Main.tsx代码如下:
注意的以下几点:
1.use client 代表客户端文件,意思就是在网页端进行渲染,react的钩子或者antd这些都要加此定义 ,注意antd结合next.js 官网有相关教程 指路;antd在next.js相关配置
2.由于项目都是由客户端渲染,查询文档发现 推荐使用useSWR 组件进行 fetch的数据获取。 官方文档只推荐用这种,其余都是server的获取数据
'use client'
import React, { useEffect, useState } from 'react'
import './Main.css'
import FooterComponent from '@/Compentent/FooterComponent'
import ScatterEchart from '@/Compentent/Scatter_Echart'
import SignalEchart from '@/Compentent/Signal_Echart'
import PowerEchart from '@/Compentent/Power_Echart'
import LineEchart from './Line_Echart'
import LineEchartNew from '@/Compentent/Line_EchartNew'
import FlvVideoPlayer from '../Compentent/FlvVideoPlayer'
import dynamic from 'next/dynamic'
import FetchClient from '@/commonPackage/FetchModel/newFetchPackage';
import useSWR from 'swr'
//const DynamicHeader = dynamic(() => import('../Compentent/FlvVideoPlayer'), {
// loading: () => <p>Loading...</p>,
//})
export interface IPageConfig extends ISaveConfig,IDynamicConfig{
}
export interface ISaveConfig{
dynamic_range: number,
ema: number,
freq_lower: number,
freq_upper: number,
spl_threshold:number,
zoom:number,
prpd_hnr:number,
prpd_peak_critical:number,
prpd_peak_warning:number,
}
export interface IDynamicConfig{
dynamic_range_big:number
dynamic_range_large: number
dynamic_range_media: number
dynamic_range_small:number
}
// // //静态props加载 预加载
// async function fetchNote() {
// console.log("开始预加载。。。",process.env.NODE_ENV,process.env.DB_HOST);
// let data:any;
// try {
// data=await fetchClient.get<any>('config')
// } catch (error) {
// data={
// dynamic_range: 1,
// ema: 0.5,
// freq_lower: 5000,
// freq_upper: 20000,
// spl_threshold: 0,
// zoom: 1,
// dynamic_range_big: 3,
// prpd_hnr:10,
// prpd_peak_critical:10,
// prpd_peak_warning:10,
// dynamic_range_large: 15,
// dynamic_range_media: 1,
// dynamic_range_small: 0.1
// }
// }
// return data;
// }
// interface IMain{
// uri:string,
// flvVideoUrl:string
// }
//获取当前网页ip,作为host
const hostname = typeof window !== 'undefined' && window.location.hostname ? window.location.hostname : '';
let flvVideoUrl= `http://${hostname}:5000/live`;
let uri = `http://${hostname}`;
if (process.env.NODE_ENV === "development") {
flvVideoUrl = `http://192.168.4.203:5000/live`;
uri = `http://192.168.4.203`;
}
export default function Main() {
//const {uri,flvVideoUrl}= props
const fetcher = (uri: RequestInfo | URL) => fetch(uri).then((res) => res.json());
const { data, error, isLoading }=useSWR(uri+"/config",fetcher)
const fetchClient=new FetchClient(uri)
let data1:IPageConfig=data
let saveConfig:ISaveConfig={
dynamic_range: data1?.dynamic_range,
ema: data1?.ema,
freq_lower: data1?.freq_lower,
freq_upper: data1?.freq_upper,
spl_threshold: data1?.spl_threshold,
zoom: data1?.zoom,
prpd_hnr: data1?.prpd_hnr,
prpd_peak_critical: data1?.prpd_peak_critical,
prpd_peak_warning: data1?.prpd_peak_warning
}
let dynamicConfig:IDynamicConfig={
dynamic_range_big: data1?.dynamic_range_big,
dynamic_range_large: data1?.dynamic_range_large,
dynamic_range_media: data1?.dynamic_range_media,
dynamic_range_small: data1?.dynamic_range_small
}
let upload=(e:any)=>{
//console.log("子组件上传的值",e,saveConfig);
saveConfig.dynamic_range=e.dynamic_range
saveConfig.ema=e.ema
saveConfig.zoom=e.zoom
saveConfig.prpd_peak_critical=e.prpd_peak_critical
saveConfig.prpd_peak_warning=e.prpd_peak_warning
saveConfig.prpd_hnr=e.prpd_hnr
//let uploadJson=JSON.stringify(saveConfig)
console.log("子组件上传的值",saveConfig);
fetchClient.post<any>('config',saveConfig).then((res)=>{
console.log("保存成功!",res);
}).catch((e)=>{
console.log("保存失败!",e);
})
}
return (
<>
<div className=' MainContent'>
<div className='flex w-98/100 h-98/100 flex-col justify-between'>
<div className='h-66.5/100 flex justify-between'>
<div className='basis-49.5/100 bg-[#ffffff] flex justify-center '>
<FlvVideoPlayer url={flvVideoUrl} />
</div>
<div className='basis-49.5/100 flex flex-col justify-between '>
<div className='basis-48.5/100 bg-[#ffffff]' >
<LineEchartNew uri={uri} spl_threshold={saveConfig.spl_threshold} getSpl={(e:number)=>{return saveConfig.spl_threshold=e}}/>
</div>
<div className='basis-48.5/100 bg-[#ffffff]' >
<ScatterEchart uri={uri}/>
</div>
</div>
</div>
<div className='h-32/100 flex justify-between'>
<div className='basis-49.5/100 bg-[#ffffff]'>
<PowerEchart uri={uri} freq_lower={saveConfig.freq_lower as number} freq_upper={saveConfig?.freq_upper as number}
getFreq_upper={(e:any)=>{return saveConfig.freq_upper=e}}
getFreq_lower={(e:any)=>{return saveConfig.freq_lower=e}}/>
{/* <AxisPointerMakelineExample/> */}
</div>
<div className='basis-49.5/100 bg-[#ffffff]'>
<SignalEchart uri={uri}/>
</div>
</div>
</div>
</div>
<footer className='basis-1/20 bg-[#3e4a62] text-white flex items-center '>
<div className='ml-5 w-full'><FooterComponent SaveConfig={saveConfig as ISaveConfig}
dynamicConfig={dynamicConfig as IDynamicConfig}
funcUpload={upload}
uri={uri}
/></div>
</footer>
</>
)
}
三 总结:
在使用next build的时候,报错原因 no self这种 请从渲染的顺序进行问题的寻找。
举个项目遇到的真实问题例子,要渲染flv.js 报错,不能build 如何进行规避呢?
这种组件没有考虑到server的渲染,在build的环境检查下就容易报错,我是这规避的 if (typeof window !== “undefined” && <></>) const flvjs = require(‘flv.js’);
if (typeof window !== "undefined" && <></>) {
const flvjs = require('flv.js');
const flvPlayer = flvjs.createPlayer({
type: 'flv',
url: url,
isLive:true,
},{
enableStashBuffer: false, // 取消缓存
});
flvPlayerRef.current = flvPlayer;
// 将播放器与video元素关联
if (videoRef.current) {
flvPlayer.attachMediaElement(videoRef.current);
flvPlayer.load();
}
flvPlayer.on('error', ()=>handlePlayerError(flvPlayerRef));
}
项目demo的展示