zoukankan      html  css  js  c++  java
  • [Next] 五.next自定义内容

    自定义 head

    这是默认的 head

    这样的 head 并不能满足我们的需求.next 公开了一个内置组件,用于将元素追加到<head>标签的.我们可以通过这个自定义 head

    新建 components/Head.js

    import { Fragment } from "react";
    import Head from "next/head";
    
    function MyHead() {
      return (
        <Fragment>
          <Head>
            <meta charset="utf-8"></meta>
            <meta name="referrer" content="origin"></meta>
            <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"></meta>
            <meta name="keywords" content="next.js,react.js"></meta>
            <meta content="next 简介 next.js作为一款轻量级的应用框架,主要用于构建静态网站和后端渲染网站。 next 特点 默认情况下由服务器呈现 自动代码拆分可加快页面加载速度 简单的客户端路由(基于页面) 基于"></meta>
            <title>蓝猫</title>
          </Head>
        </Fragment>
      );
    }
    
    export default MyHead;
    

    为了避免重复的标签,您<head>可以使用 key 属性,以确保标签仅呈现一次

    在 MyLayout.js 引入

    import Head from "./Head";
    
    ......
          <Fragment>
            <Head />
            <Header />
            <div className={"content"}>{children}</div>
            <Footer />
          </Fragment>
    ......
    

    添加完之后的 head 标签,但是在使用中<meta charset="utf-8"></meta>如果再添加的话就会出现两个,去掉 Head 组件中的 charset.

    自定义 app

    上面是 next 的渲染流程,next 使用 app 组件来进行初始化页面. 可以覆盖 next 自带的 app 来进行初始化

    • 在页面更改是保持持久布局
    • 当页面切换时保持状态
    • 使用自定义错误处理 componentDidCatch
    • 页面的数据注入

    新建 pages/_app.js

    import React from "react";
    import App from "next/app";
    
    class MyApp extends App {
      render() {
        const { Component, pageProps } = this.props;
        return (
          <div className="my-app">
            <Component {...pageProps} />
          </div>
        );
      }
    }
    
    export default MyApp;
    

    getInitialProps 在 App 中添加自定义设置会影响自动静态优化

    自定义 document

    • 自定义<Document>通常用于扩充<html><body>标签
    • 在服务端呈现
    • 初始化服务端时添加文档标记元素
    • 通常实现服务端渲染会使用一些 css-in-js 库,如 styled-components, glamorous 或 emotion。styled-jsx 是 Next.js 自带默认使用的 css-in-js 库

    新建 pages/_document.js

    import Document, { Html, Head, Main, NextScript } from "next/document";
    
    class MyDocument extends Document {
      static async getInitialProps(ctx) {
        const initialProps = await Document.getInitialProps(ctx);
        return { ...initialProps };
      }
    
      render() {
        return (
          <Html>
            <Head />
            <body>
              <div className="document">
                <Main />
                <div className="inner-document"></div>
                <NextScript />
              </div>
            </body>
          </Html>
        );
      }
    }
    
    export default MyDocument;
    

    钩子 getInitialProps 接收到的参数 ctx 对象都是一样的

    • 回调函数 renderPage 是会执行 React 渲染逻辑的函数(同步),这种做法有助于此函数支持一些类似于 Aphrodite 的 renderStatic 等一些服务器端渲染容器。

    注意:<Main />外的 React 组件将不会渲染到浏览器中,所以那添加应用逻辑代码。如果你页面需要公共组件(菜单或工具栏),可以参照上面说的 App 组件代替。

    自定义 renderPage

    使用 renderPage 的唯一原因是 css-in-js 库需要包裹当前应用并且在服务端渲染下也能正常工作

    static async getInitialProps(ctx) {
      const originalRenderPage = ctx.renderPage
    
      ctx.renderPage = () =>
        originalRenderPage({
          // useful for wrapping the whole react tree
          enhanceApp: App => App,
          // useful for wrapping in a per-page basis
          enhanceComponent: Component => Component,
        })
    
      // Run the parent `getInitialProps` using `ctx` that now includes our custom `renderPage`
      const initialProps = await Document.getInitialProps(ctx)
    
      return initialProps
    }
    

    自定义错误页面

    客户端和服务器端的 404 或 500 错误默认由 error.js 组件处理。

    新建 pages/_error.js 覆盖

    import React from 'react'
    
    function Error({ statusCode }) {
      return (
        <p>
          {statusCode
            ? `An error ${statusCode} occurred on server`
            : 'An error occurred on client'}
        </p>
      )
    }
    
    Error.getInitialProps = ({ res, err }) => {
      const statusCode = res ? res.statusCode : err ? err.statusCode : 404
      return { statusCode }
    }
    

    自定义配置 / 自定义 Webpack 配置 / 自定义 babel 配置

    当前的配置./next.config.js

    const fetch = require("isomorphic-unfetch");
    const withBundleAnalyzer = require("@zeit/next-bundle-analyzer");
    const withLess = require("@zeit/next-less");
    const FilterWarningsPlugin = require("webpack-filter-warnings-plugin");
    
    if (typeof require !== "undefined") {
      require.extensions[".less"] = file => {};
    }
    
    function HACK_removeMinimizeOptionFromCssLoaders(config) {
      config.module.rules.forEach(rule => {
        if (Array.isArray(rule.use)) {
          rule.use.forEach(u => {
            if (u.loader === "css-loader" && u.options) {
              delete u.options.minimize;
            }
          });
        }
      });
    }
    
    module.exports = withBundleAnalyzer(
      withLess({
        poweredByHeader: false,
        analyzeServer: ["server", "both"].includes(process.env.BUNDLE_ANALYZE),
        analyzeBrowser: ["browser", "both"].includes(process.env.BUNDLE_ANALYZE),
        bundleAnalyzerConfig: {
          server: {
            analyzerMode: "static",
            reportFilename: "../bundles/server.html"
          },
          browser: {
            analyzerMode: "static",
            reportFilename: "../bundles/client.html"
          }
        },
        exportPathMap: async function() {
          const paths = {
            "/": { page: "/" },
            "/books": { page: "/books" },
            "/article": { page: "/article" },
            "/write": { page: "/write" }
          };
    
          const res = await fetch("https://api.tvmaze.com/search/shows?q=batman");
          const data = await res.json();
          const shows = data.map(entry => entry.show);
    
          shows.forEach(show => {
            paths[`/book/${show.id}`] = {
              page: "/book/[id]",
              query: { id: show.id }
            };
          });
    
          return paths;
        },
        lessLoaderOptions: {
          javascriptEnabled: true
        },
        webpack(config) {
          config.plugins.push(
            new FilterWarningsPlugin({
              exclude: /mini-css-extract-plugin[^]*Conflicting order between:/
            })
          );
          HACK_removeMinimizeOptionFromCssLoaders(config);
          return config;
        }
      })
    );
    
    

    当前的.babelrc

    {
      "presets": ["next/babel"],
      "plugins": [
        [
          "import",
          {
            "libraryName": "antd",
            "style": "less"
          }
        ]
      ]
    }
    
    

    Doc

  • 相关阅读:
    【NOIP 2003】 加分二叉树
    【POJ 1655】 Balancing Act
    【HDU 3613】Best Reward
    【POJ 3461】 Oulipo
    【POJ 2752】 Seek the Name, Seek the Fame
    【POJ 1961】 Period
    【POJ 2406】 Power Strings
    BZOJ3028 食物(生成函数)
    BZOJ5372 PKUSC2018神仙的游戏(NTT)
    BZOJ4836 二元运算(分治FFT)
  • 原文地址:https://www.cnblogs.com/mybilibili/p/11778065.html
Copyright © 2011-2022 走看看