踩过的坑
- next.config.js中,开发阶段不能把热更新关闭掉,否则网站无法打开
- next/dynamic 动态加载 ---> 动态加载只对客户端才有意义
- DOMPurify库是用于浏览器环境中的,因为它依赖于浏览器的DOM API。在 Node.js环境中,由于没有浏览器的DOM API,因此无法直接使用DOMPurify。官网也写得很清楚,教你如何在服务端渲染中使用DOMPurify,我没有仔细看,结果程序一直在报错,浪费了很多时间
- 生产环境中,不可以使用组件名进行判断。因为webpack打包的时候会对组件名进行混淆,打包后组件名就是随机字符串了
//这段代码在development环境正常,在production环境就进不了if语句 export default function App({Component, pageProps}) { let body if (Component.name === 'BlurhashExample') { body = <Component {...pageProps}/> } else { body = <> <WMPageWrapper> <Component {...pageProps}/> </WMPageWrapper> </> } return <> <Head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/> </Head> <CssBaseline/> {body} </> }
项目结构
- 在 pages 目录中应该只包含 Next.js 页面组件,这些页面组件应该是应用程序的顶级路由组件,而不是嵌套在其他组件中的子组件。这是因为 pages 目录下的文件仅仅用于配置 Next.js 应用程序的路由,因此它们不应该包含业务逻辑或其他功能。不在pages文件夹下的组件,会被视为服务端(SSR)渲染组件
- _document.js(This file is only rendered on the server) 定义Html文档结构,修改标签的内容等。 添加第三方脚本和样式,例如Google Analytics、Facebook Pixel等 可以使用 _document 来设置语言、加载字体、在页面交互之前加载脚本 例如,将 CSS 类应用到页面主体,作为呈现逻辑的一部分,在 _app 中是不可能的。只有通过副作用才有可能
- _app.js 它对所有页面组件进行了包装 _app,更像是一个页面初始化程序,添加全局CS
- _document.js和_app.js在功能上略有重叠,但并不一定相互冲突
预渲染和数据获取
Essentially, getStaticProps
allows you to tell Next.js: “Hey, this page has some data dependencies — so when you pre-render this page at build time, make sure to resolve them first!”
export default function Home(props) { ... }
export async function getStaticProps() {
// Get external data from the file system, API, DB, etc.
const data = ...
// The value of the `props` key will be
// passed to the `Home` component
return {
props: ...
}
}
exportPathMap
exportPathMap allows you to specify a mapping of request paths to page destinations
module.exports = {
exportPathMap: async function (
defaultPathMap,
{ dev, dir, outDir, distDir, buildId }
) {
return {
'/': { page: '/' },
'/about': { page: '/about' },
'/p/hello-nextjs': { page: '/post', query: { title: 'hello-nextjs' } },
'/p/learn-nextjs': { page: '/post', query: { title: 'learn-nextjs' } },
'/p/deploy-nextjs': { page: '/post', query: { title: 'deploy-nextjs' } },
}
},
}
Note: thequery
field inexportPathMap
cannot be used withautomatically statically optimized pages
orgetStaticProps
pages as they are rendered to HTML files at build-time and additional query information cannot be provided during next export
参数
exportPathMap
is an async function that receives 2 arguments: the first one is defaultPathMap
, which is the default map used by Next.js. The second argument is an object with:
dev
true
when exportPathMap is being called in development.false
when running next export. In development exportPathMap is used to define routesdir
Absolute path to the project directoryoutdir
Absolute path to the out/ directory (configurable with -o). When dev is true the value of outDir will be null.# 指定输出文件夹 next export -o outdir
distdir
Absolute path to the .next/ directory (configurable with the distDir config)buildId
The generated build id
返回值
The returned object is a map of pages where the key is the pathname and the value is an object that accepts the following fields:
page:String
the page inside the pages directory to rendequery:Object
query的值取决于你的页面配置// 有个动态页面/a/b/c/[id],用户访问"/"时,你希望展示/a/b/c/index"页面,可以这样配置 return { "/":{page:"/a/b/c",query:{slug:"index"}} }
Nextjs中的webpack
- 在pages目录下的js文件,是运行在浏览器上的,webpack会把每个js文件打包成单独的页面。优化页面加载速度可以从这里分析
- 除此以外,其他代码都是运行在nodejs中
- 关于import导包,补充一些细节
import * from <npm-library>
- 如果这个库里面有很多的子模块(比如MUI库中有很多子模块,Button、Dialog...),那么会导入所有的模块,webpack打包时会增加包体积
- 如果这个库里面只有一个子模块,那么用*号导入和用名字导入其实差不多
webpack打包的最小单位是模块,如果你只是使用到了某个模块中的一个函数,webpack还是会打包整个模块,保证程序的完整性
举个例子
// time-util.js
function getFormatDate(){
//获取格式化时间
}
function getBeijingTime(){
//获取北京时间
}
......
在另外一个文件进行包的导入,以下三种写法
import time from 'time-util'
import * from 'time-util'
import {getFormatDate} from 'time-util'
效果都是一样的,webpack最终会把time-util.js打包,而不是只打包你使用到的某个函数