随着前端项目的复杂化,页面渲染出现白屏的情况也是越来越普遍。针对 Next.js 的项目来说,这种情况也时有发生。本文将介绍 Next.js 页面渲染白屏的原因分析、解决方法,并给出相应的示例代码。
问题的原因
在 Next.js 项目中,页面的渲染方式既有服务器端渲染(Server-side Rendering,SSR),还有客户端渲染(Client-side Rendering,CSR)。白屏的情况一般是由于客户端渲染时出现的问题所致。
常见的导致白屏的原因包括:
- JavaScript 报错。由于某些 JavaScript 异常,导致页面无法正常加载。
- 资源文件加载失败。某些 CSS 或 JavaScript 文件无法正常加载,导致页面无法正确渲染。
- 后端数据请求错误。如果页面中有公用组件,当其中某一个组件由于后端数据请求错误而不能正常渲染时,也可能导致整个页面白屏。
解决方法
调试工具
首先,要查找白屏的原因,我们可以使用调试工具。在 Next.js 项目中,我们可以使用 Chrome 浏览器的开发者工具(Developer Tools)来查看页面渲染情况。
通过开发者工具,我们可以查看很多有关页面加载的信息。包括控制台、网络、元素、应用等等。其中,「网络」选项卡中可以查看网页请求和响应的状态,如果发现有部分文件请求失败了,那么我们就可以初步判断是资源加载失败导致的问题。
另外,我们也可以在 Next.js 项目中使用 react-error-overlay
来展示 React 组件抛出的错误。这可以更直观地查看 JavaScript 报错的信息。
SSR 配置
由于 Next.js 项目支持 SSR 渲染,因此,我们可以进行 SSR 的配置,从而确保页面在首次渲染的时候能够正常显示。具体的配置方式如下:
将
getInitialProps()
从页面组件中提取,放到一个单独的文件中。配置
server.js
,在此文件中进行 SSR 渲染,并将生成的 HTML 保存到磁盘中。配置
next.config.js
,指定所需的环境变量、关键信息等等。集成自定义 ErrorBoundary 组件,防止静态资源请求出错时页面崩溃。
代码示例如下:
// javascriptcn.com 代码示例 // server.js const express = require('express') const next = require('next') const path = require('path') const App = require('./app').default const port = parseInt(process.env.PORT, 10) const env = process.env.NODE_ENV const nextApp = next({ dev: env !== 'production' }) const handle = nextApp.getRequestHandler() nextApp.prepare().then(() => { const server = express() server.get('/', async (req, res) => { try { const props = await App.getInitialProps(req, res) const html = await nextApp.renderToString(<App {...props} />) res.send(html) } catch (err) { console.error(err) res.status(500).end('Server error') } }) // 将生成的 HTML 保存到磁盘中 server.listen(port, err => { if (err) throw err console.log(`> Ready on http://localhost:${port}`) }) })
// javascriptcn.com 代码示例 // app.js import { Component } from 'react' import axios from 'axios' export default class App extends Component { static async getInitialProps(ctx) { try { const { data } = await axios.get('http://localhost:3000/api/articles') return { articles: data } } catch (err) { console.error(err) return { articles: [] } } } render() { const { articles } = this.props return ( <div> {articles && articles.map(article => <div key={article.id}>{article.title}</div>)} </div> ) } }
// javascriptcn.com 代码示例 // next.config.js module.exports = { env: { API_ENDPOINT: process.env.API_ENDPOINT, }, webpack: config => { // 定义别名 config.resolve.alias = { ...config.resolve.alias, '@': path.resolve(__dirname), } // 加载 SVG 图标 config.module.rules.push({ test: /\.svg$/, use: ['@svgr/webpack'], }) return config }, }
// javascriptcn.com 代码示例 // ErrorBoundary.js import React from 'react' export default class ErrorBoundary extends React.Component { constructor(props) { super(props) this.state = { hasError: false } } static getDerivedStateFromError(error) { return { hasError: true } } componentDidCatch(error, errorInfo) { console.error(error, errorInfo) } render() { if (this.state.hasError) { // 防止静态资源请求出错时页面崩溃 return <h1>Something went wrong.</h1> } return this.props.children } }
配置 Webpack
如果原因是 JavaScript 代码报错,可以尝试在 Webpack 中配置 devtool
来查看源码和对应的错误行号。具体的配置方式是 devtool: 'source-map'
。
如果加载 JavaScript 或 CSS 文件失败,可以尝试在 next.config.js
中指定所需的文件路径,并添加 file-loader
和 style-loader
。
代码示例如下:
// javascriptcn.com 代码示例 // next.config.js const withCSS = require('@zeit/next-css') const withSass = require('@zeit/next-sass') module.exports = withCSS( withSass({ cssModules: true, cssLoaderOptions: { importLoaders: 1, localIdentName: '[local]_[hash:base64:5]', }, webpack: (config, { isServer }) => { config.resolve.alias['@'] = __dirname config.module.rules.push({ test: /\.(png|jpg|gif|svg)$/, exclude: /node_modules/, use: [ { loader: 'file-loader', options: { outputPath: 'static/', publicPath: '/_next/static/', name: '[name].[ext]', }, }, ], }) if (!isServer) { config.node = { fs: 'empty', } config.module.rules.push({ test: /\.(css|scss)$/, exclude: /node_modules/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', options: { modules: true, importLoaders: 1, localIdentName: '[local]__[hash:base64:5]', }, }, { loader: 'sass-loader', options: { sourceMap: true, }, }, ], }) config.module.rules.push({ test: /\.(css|scss)$/, include: /node_modules/, use: ['style-loader', 'css-loader', 'sass-loader'], }) } return config }, }) )
总结
本文主要介绍了 Next.js 项目页面渲染出现白屏的原因分析和解决方法,并给出了针对 SSR 配置和 Webpack 配置的示例代码。当页面渲染出现白屏时,可以通过调试工具和上述的解决方法,逐一排查和解决问题,以确保页面能够正常加载和渲染。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654af0e47d4982a6eb4e6e87