如何在Next.js静态站点中添加网站图标?

111

我正在尝试为一个Next.js静态网站添加favicon,但没有太大的成功。

我已经尝试使用来自'next/document'组件自定义文档。 https://nextjs.org/docs/#custom-document

直接链接到favicon.ico文件无法正常工作,因为该文件未包含在构建中,并且href不会更新为/_next/static/...

导入图像并将其添加到链接的href也无效(请参见已注释掉的行)。

import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';

// import favicon from '../data/imageExports';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <Html>
        <Head>
          {/* <link rel="shortcut icon" href={favicon} /> */}
          <link rel="shortcut icon" href="../images/icons/favicon.ico" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

网站图标的链接已经添加,但是没有显示。我本来期望引入文件后它可以正常工作,但实际上只是添加了一个<link rel="shortcut icon" href="[object Object]">的链接。

有人已经解决过这个问题了吗?

17个回答

175
  1. 在项目根目录中创建一个/static文件夹。这将被添加到静态导出文件夹中。
  2. /static文件夹中添加网站图标文件。
  3. 按照文档 (nextjs.org)文档 (github.com)_document.js添加到/pages/文件夹中。
  4. 在中添加<link rel="shortcut icon" href="/static/favicon.ico" />
  5. npm run build && npm run export

P.S. 感谢之前已删除的回答,它有效!


编辑:另一种方法是将Head引入您的根布局并在那里添加链接。添加到Head的任何内容都会插入到文档标记中。

import Head from 'next/head';

const Page = (props) => (
  <div>
    <Head>
      <link rel="shortcut icon" href="/static/favicon.ico" />
    </Head>
    // Other layout/components
  </div>
);

export default Page;

更新:

静态目录已被弃用,建议改为使用public目录。文档

因此,代码现在应该是这样的:

import Head from 'next/head';

const Page = (props) => (
  <div>
    <Head>
      <link rel="shortcut icon" href="/favicon.ico" />
    </Head>
    // Other layout/components
  </div>
);

3
文档链接现在在这里:https://nextjs.org/docs/advanced-features/custom-document 或 https://github.com/zeit/next.js/#custom-document。 - Denis
10
尽管这个方法可行,但现在Next.js更倾向于使用/public文件夹而不是/static。具体信息可以参考此链接:https://github.com/zeit/next.js/blob/master/errors/static-dir-deprecated.md - Gonzalo.-
2
@S.S.Anne 那是Tesseracter编辑的误操作,实际上那个编辑是好的 - 对此我深表歉意,所以我撤回了它。关于被删除的答案,我不知道为什么那个人删除了它,因为那个解决方案当时是有效的。 - Advait Junnarkar
1
它对我不起作用,显示React Favicon Logo并持续加载。 我所做的就是添加'..',因此它应该是:<link rel="shortcut icon" href="../static/favicon.ico" />。 P.S:我正在使用版本早于9.0.6,这就是为什么我仍然使用static公共目录的原因。感谢@AdvaitJunnarkar! - Elharony
1
当使用basePath时,它是否应该与public文件夹一起工作?我有一个basePath,我的favicon.ico在public文件夹中,并且我像这样定义它<link rel='shortcut icon' href='/favicon.ico' />,但链接在浏览器中保持没有我的basePath,就像这样:<link rel="shortcut icon" href="/favicon.ico"> - R. Boutte
显示剩余6条评论

70

2
谢谢!我所需要的只是在公共文件夹中替换当前的favicon.ico。使用下一个v10.0.2版本。 - Hanif
2
最佳答案! - Hanane
1
然而,这个问题在于格式不正确,因为至少需要24个网站图标资产。 - Oliver Dixon
这对我非常有效,只需将ico文件添加到/public中,就完成了! - Michiel J Otto
1
公共文件夹中的资源可以被浏览器访问。您的浏览器将查找 favicon.ico 文件,而不是 Next。但是,如果您没有提供链接,则在移动设备和平板电脑上可能会出现问题。特别是当有人尝试将链接保存到他们的应用程序启动器时,图标将不使用 favicon。 - Advait Junnarkar
需要在 Next.js 18 中位于 "public/images" 文件夹内。 - Emre

45

接受的答案很好,但值得指出的是,您不必修改 _document.js 来添加网站图标(也不必添加任何标签到 head)。

我自己发现将网站图标放置在 _app.js 中更有意义。这个文件很可能已经存在于为页面设置布局或类似内容的过程中。而且您可以在任何地方添加 Head 标签(请参见文档

所以我最终选择了 _app.js

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;

    return (
      <Layout>
        <Head>
          <link rel="shortcut icon" href="/favicon.ico" />
        </Head>
        <Component {...pageProps} />
      </Layout>
    );
  }
}

它对我不起作用,唯一有效的方法是将faricon放入静态文件夹中。 - Sallwa
1
你可以将你的网站图标存储在任何地方,这个问题是关于如何将它添加到网站上,而不是文件的位置。所以很可能你只是指定了错误的路径到你的网站图标。 - user3272018

23
截至2020年6月,您无需添加/编辑document.js_head.js文件。您只需要将favicon.ico文件放置在public目录中即可。

我已经将 "favicon.ico" 添加到公共文件夹中,但是当我运行构建时,我没有看到 favicon 被编译到 .next 文件夹中。你有例子吗?谢谢。 - nart
它不会被放进任何其他文件夹,你只需要将它留在公共文件夹中。如果它在那里,nextjs 会捡起它并使用它。我正在使用 next@9.4.4 版本。 - Andres Zapata
我也使用了next@9.4.4版本,但仍然遇到了相同的问题 :( - nart
我正在使用Next 9.5.0,我将favicon.ico文件放置在public目录中,然后它就起作用了!谢谢@AndresZapata - Sumit

20

仅仅添加.ico文件是不够的。

因为默认的.ico文件只会被桌面浏览器使用,这样是不够的。你需要支持不同的设备,如平板电脑、智能手机等。通过添加不同尺寸的图标,应用程序可以在智能手机的桌面上存储。

_document.jsx_document.tsx文件的<Head>部分添加链接标签。问题只涉及.ico文件,但我建议添加不同的尺寸和格式以获得更好的支持。

import React from 'react';
import Document, { Html, Head, Main, NextScript, DocumentContext, DocumentInitialProps } from 'next/document';

class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render(): React.ReactElement {
    return (
      <Html>
        <Head>
          <link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png" />
          <link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png" />
          <link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png" />
          <link rel="manifest" href="/favicons/site.webmanifest" />
          <link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5" />
          <meta name="msapplication-TileColor" content="#ffc40d" />
          <meta name="theme-color" content="#ffffff" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

你可以使用RealFaviconGenerator生成不同的图标,并将结果上传到/public/favicons/文件夹中。由于公共目录的特性,可以通过/favicons/来引用该文件夹。

2
非常感谢。我认为这太多代码了,只是为了一个站标,但你的解决方案还是有帮助的。 - Gorr1995
3
唯一正确的答案是,您至少需要24个收藏夹图标才能在各种设备上保持兼容性。 - Oliver Dixon
这在下一个 12 版本中不会起作用,他们取消了 PNG 和 SVG 加载器。 - serraosays
@serraosays,您能分享一下提到这个的文档链接吗?我正在使用Next 12.1版本,对于这个配置没有任何问题。 - Black
@Black - 新的Next编译器文档:https://nextjs.org/docs/advanced-features/compiler。现在他们有点强制要求你使用next/image。我还没有找到一种不需要自定义webpack 5加载器(这意味着他们从默认设置中删除了这些加载器)就能加载jpg、png等文件的方法。希望我错了,因为现在很麻烦。 - serraosays
值得一提的是 - https://github.com/vercel/next.js/discussions/26167 - serraosays

6

我必须执行favicon.src才能使其工作。

不起作用:

import favicon from '...'
...

<link rel="shortcut icon" href={favicon} />

工作:

import favicon from '...'
...

<link rel="shortcut icon" href={favicon.src} />

为了搞清楚这个问题,我运行了 console.log(favicon) 命令,结果发现它是一个长得像这样的对象:
{
  height: 16,
  src: "path/to/favicon.603d046c.ico"
  width: 16,
}

5

在我的情况下,如果没有导入,它是无法工作的:

文件:_app.tsx


    import { AppContext, AppProps } from "next/app";
    import "../styles/common.scss";
    import Head from 'next/head';
    //For me it didn't work without the following import...
    import favico from "../static/favicon.ico";
    
    
    function MyApp({ Component, pageProps }: AppProps) {
      const csrfToken = pageProps["anti-csrftoken-a2z"];
      return (
        <div>
          <Head>
            <link rel="shortcut icon" href={favico} type="image/x-icon" />
          </Head>
          <Component {...pageProps} />
        </div>
      );
    }
    
    MyApp.getInitialProps = async ({ Component, ctx }: AppContext) => {
      let pageProps = {};
      if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx);
      }
      return { pageProps };
    };
    
    export default MyApp;


4

3

Next.js can serve static files, like images, under a folder called public in the root directory. Files inside public can then be referenced by your code starting from the base URL (/).

For example, if you add an image to public/me.png, the following code will access the image:

import Image from 'next/image'

function Avatar() {   
    return <Image src="/me.png" alt="me" width="64" height="64" />
}

export default Avatar 

Note: next/image requires Next.js 10 or later.

This folder is also useful for robots.txt, favicon.ico, Google Site Verification, and any other static files (including .html)!

如果您只是替换 favicon.ico ,它将会相应地更新。

更多详情请访问官方文档


2

我认为这对某人会很有用

<Head>
    <link rel="apple-touch-icon" sizes="57x57" href="/favicons/apple-touch-icon-57x57.png" />
    <link rel="apple-touch-icon" sizes="60x60" href="/favicons/apple-touch-icon-60x60.png" />
    <link rel="apple-touch-icon" sizes="72x72" href="/favicons/apple-touch-icon-72x72.png" />
    <link rel="apple-touch-icon" sizes="76x76" href="/favicons/apple-touch-icon-76x76.png" />

    <link rel="apple-touch-icon" sizes="114x114" href="/favicons/apple-touch-icon-114x114.png" />
    <link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-touch-icon-120x120.png" />
    <link rel="apple-touch-icon" sizes="144x144" href="/favicons/apple-touch-icon-144x144.png" />
    <link rel="apple-touch-icon" sizes="152x152" href="/favicons/apple-touch-icon-152x152.png" />
    <link rel="apple-touch-icon" sizes="167x167" href="/favicons/apple-touch-icon-167x167.png" />
    <link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon-180x180.png" />

    <link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png" />
    <link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="96x96" href="/favicons/favicon-96x96.png" />
    <link rel="icon" type="image/png" sizes="128x128" href="/favicons/favicon-128x128.png" />
    <link rel="icon" type="image/png" sizes="196x196" href="/favicons/favicon-196x196.png" />
    <link rel="icon" type="image/png" sizes="192x192" href="/favicons/android-chrome-192x192.png" />
    <link rel="icon" type="image/png" sizes="512x512" href="/favicons/android-chrome-512x512.png" />

    <link rel="shortcut icon" href="/favicons/favicon.ico" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="mobile-web-app-capable" content="yes" />

    <meta name="msapplication-TileImage" content="/favicons/mstile-144x144.png"/>
    <meta name="msapplication-square70x70logo" content="/favicons/mstile-70x70.png"/>
    <meta name="msapplication-square150x150logo" content="/favicons/mstile-150x150.png"/>
    <meta name="msapplication-square144x144logo" content="/favicons/mstile-144x144.png"/>
    <meta name="msapplication-square310x310logo" content="/favicons/mstile-310x310.png"/>
</Head>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接