Netlify-CMS是一个很好用的CMS系统,开源且免费,经常与Next.js、Hugo、Nuxt.js等静态网站生成工具一起使用。在Next.js项目中启用netlify-cms是比较简单的,但是如果要做一些自定义插件设置,就会稍微复杂一些。
先看官方的配置:
要在Next.js中启用netlify-cms,只需要在静态文件目录中添加一个admin目录,里面放一个index.html和config.yml即可。这部分可以直接看netlify-cms的官方文档:
admin
├ index.html
└ config.yml
对于Next.js来说,静态文件目录在public目录,所以只要在public目录中建立一个admin子目录,并按上面的方式添加index.html和config.yml即可。
index.html(复制即可):
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content Manager</title>
</head>
<body>
<!-- Include the script that builds the page and powers Netlify CMS -->
<script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
</body>
</html>
config.yml(按需调整):
backend:
name: git-gateway
branch: master # Branch to update (optional; defaults to master)
这种方式可以应对大部分场景,但是在注册自定义插件的时候不是很方便。
如果不使用静态文件的方式,而改成动态渲染。就会需要在Next.js项目的 src/pages/
目录中新建一个admin.tsx
或admin.jsx
文件,并完成相应的渲染。
官方文档中也有一部分示例:
npm install netlify-cms-app --save
import CMS from 'netlify-cms-app'
// Initialize the CMS object
CMS.init()
// Now the registry is available via the CMS object.
CMS.registerPreviewTemplate('my-template', MyTemplate)
但是在next.js中直接复制上述代码的话,会报一个错误:window is not defined.
,因为next.js有服务端渲染的部分,而netlify-cms-app
的内部有对window的处理,不兼容ssr,所以会报错。
Github上有一个开源项目jakeprins/nextjs-netlify-cms,提供了一个解决方案。
import dynamic from 'next/dynamic';
import config from '../cms/config';
const CMS = dynamic(
() =>
import('netlify-cms-app').then((cms) => {
cms.init({ config });
}),
{ ssr: false, loading: () => <p>Loading...</p> }
);
const AdminPage: React.FC = () => {
return <CMS />;
};
export default AdminPage;
实际操作过程中,我发现它会有一个白屏的问题,所以还需要微调一下:
import dynamic from 'next/dynamic';
import config from './config.json'
const CMS = dynamic(
() =>
import('netlify-cms-app').then(async (cms: any) => {
cms.init({ config });
}) as any,
{ ssr: false, loading: () => <p>Loading...</p> }
);
const AdminPage: React.FC = () => {
return <>
<div id='nc-root' />
<CMS />
</>
};
export default AdminPage;
在这里,就可以注册自定义插件了。注意如果你的自定义插件中引用了netlify-cms中的东西,则可能也需要使用dynamic import技术,取代文件头部引入的方式。
示例代码:
import dynamic from 'next/dynamic';
import config from './config.json'
const CMS = dynamic(
() =>
import('netlify-cms-app').then(async (cms: any) => {
const { HtmlControl, HtmlPreview } = await import('netlify-cms-widget-html')
cms.init({ config });
cms.registerWidget('html', HtmlControl, HtmlPreview)
}) as any,
{ ssr: false, loading: () => <p>Loading...</p> }
);
const AdminPage: React.FC = () => {
return <>
<div id='nc-root' />
<CMS />
</>
};
export default AdminPage;
以上。