logo

鱼肚的博客

Don't Repeat Yourself

Next.js中手动配置netlify-cms

Netlify-CMS是一个很好用的CMS系统,开源且免费,经常与Next.js、Hugo、Nuxt.js等静态网站生成工具一起使用。在Next.js项目中启用netlify-cms是比较简单的,但是如果要做一些自定义插件设置,就会稍微复杂一些。

先看官方的配置:

官方配置

要在Next.js中启用netlify-cms,只需要在静态文件目录中添加一个admin目录,里面放一个index.html和config.yml即可。这部分可以直接看netlify-cms的官方文档

1admin
2 ├ index.html
3 └ config.yml

对于Next.js来说,静态文件目录在public目录,所以只要在public目录中建立一个admin子目录,并按上面的方式添加index.html和config.yml即可。

index.html(复制即可):

1<!doctype html>
2<html>
3<head>
4  <meta charset="utf-8" />
5  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6  <title>Content Manager</title>
7</head>
8<body>
9  <!-- Include the script that builds the page and powers Netlify CMS -->
10  <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
11</body>
12</html>

config.yml(按需调整):

1backend:
2  name: git-gateway
3  branch: master # Branch to update (optional; defaults to master)

这种方式可以应对大部分场景,但是在注册自定义插件的时候不是很方便。

Next.js中动态渲染

如果不使用静态文件的方式,而改成动态渲染。就会需要在Next.js项目的 src/pages/目录中新建一个admin.tsxadmin.jsx文件,并完成相应的渲染。

官方文档中也有一部分示例:

1npm install netlify-cms-app --save
1import CMS from 'netlify-cms-app'
2// Initialize the CMS object
3CMS.init()
4// Now the registry is available via the CMS object.
5CMS.registerPreviewTemplate('my-template', MyTemplate)

但是在next.js中直接复制上述代码的话,会报一个错误:window is not defined.,因为next.js有服务端渲染的部分,而netlify-cms-app的内部有对window的处理,不兼容ssr,所以会报错。

Github上有一个开源项目jakeprins/nextjs-netlify-cms,提供了一个解决方案。

1
2import dynamic from 'next/dynamic';
3import config from '../cms/config';
4const CMS = dynamic(
5  () =>
6    import('netlify-cms-app').then((cms) => {
7      cms.init({ config });
8    }),
9  { ssr: false, loading: () => <p>Loading...</p> }
10);
11const AdminPage: React.FC = () => {
12  return <CMS />;
13};
14export default AdminPage;

实际操作过程中,我发现它会有一个白屏的问题,所以还需要微调一下:

1import dynamic from 'next/dynamic';
2import config from './config.json'
3
4const CMS = dynamic(
5  () =>
6    import('netlify-cms-app').then(async (cms: any) => {
7      cms.init({ config });
8    }) as any,
9  { ssr: false, loading: () => <p>Loading...</p> }
10);
11
12const AdminPage: React.FC = () => {
13  return <>
14    <div id='nc-root' />
15    <CMS />
16  </>
17};
18
19export default AdminPage;

在这里,就可以注册自定义插件了。注意如果你的自定义插件中引用了netlify-cms中的东西,则可能也需要使用dynamic import技术,取代文件头部引入的方式。

示例代码:

1import dynamic from 'next/dynamic';
2import config from './config.json'
3
4const CMS = dynamic(
5  () =>
6    import('netlify-cms-app').then(async (cms: any) => {
7      const { HtmlControl, HtmlPreview } = await import('netlify-cms-widget-html')
8      cms.init({ config });
9      cms.registerWidget('html', HtmlControl, HtmlPreview)
10    }) as any,
11  { ssr: false, loading: () => <p>Loading...</p> }
12);
13
14const AdminPage: React.FC = () => {
15  return <>
16    <div id='nc-root' />
17    <CMS />
18  </>
19};
20
21export default AdminPage;

以上。