Статический генератор сайтов, базирующийся в next.js
nextein - это обертка вокруг next.js , которая позволяет вам писать статические сайты, используя markdown и react .
Nodejs V10.x + требуется для запуска команд nextein .
Если вы хотите перейти в стартовый проект, проверьте Nextein-Starter
Есть несколько шагов, которые вы должны выполнить, чтобы поднять свой сайт с nextein
Создайте проект:
mkdir my-sitecd my-sitenpm init -yУстановить зависимости
npm i nextein next react react-dom Добавить файл конфигурации next.config.js
const { withNextein } = require ( 'nextein/config' )
module . exports = withNextein ( {
} ) Создать pages/index.js
import React from 'react'
import { getPosts } from 'nextein/fetcher'
import Content from 'nextein/content'
export async function getStaticProps ( ) {
return {
props : {
posts : await getPosts ( )
}
}
}
export default function Index ( { posts } ) {
return (
< section >
{
posts . map ( post => < Content { ... post } /> )
}
</ section >
)
} ) markdown запись в папке posts ( posts/my-first-post.md )
---
title : First Post
category : post
---
This is the first paragraph and it will be used as an excerpt when loaded in a ` <Content excerpt /> ` tag.
This paragraph should * not * appear in that list.
Добавить сценарии NPM в режим запуска dev в свой package.json
"scripts" : {
"dev" : " next "
}Запустите сервер разработки
npm run dev Добавьте еще один сценарий NPM в свой package.json для экспорта сайта
"scripts" : {
"dev" : " next " ,
"export" : " next build && next export "
}fetcherИспользуйте Fetcher, чтобы получить посты и данные из ваших файлов разметки.
Методы getPostsFilterBy и getDataFilterBy в Fetcher позволяют выполнять функции фильтра. Например, мы можем использовать фильтр inCategory для извлечения постов в данной категории:
import { getPostsFilterBy } from 'nextein/fetcher'
import { inCategory } from 'nextein/filters'
//...
const blog = await getPostsFilterBy ( InCategory ( 'blog' ) ) getData и getDataFilterBy получат только метаданные, генерируемые для записей вместо всего поста.
Метод fetcher - это удобный способ определения фильтра, а затем использовать getPosts и getData с применением фильтра.
import fetcher from 'nextein/fetcher'
import { inCategory } from 'nextein/filters'
//...
const { getPosts } = fetcher ( InCategory ( 'blog' ) )
//...
const blog = await getPosts ( )Вы можете использовать динамические маршруты и функции статического генератора (GetStaticProps и GetStaticPaths) с помощью методов выбора.
Пример для динамического маршрута [name].js
import fetcher from 'nextein/fetcher'
const { getData , getPost } = fetcher ( /* filter */ )
export async function getStaticPaths ( ) {
const data = await getData ( )
return {
paths : data . map ( ( { name } ) => ( { params : { name } } ) ) ,
fallback : false
}
}
export async function getStaticProps ( { params } ) {
const post = await getPost ( params )
return { props : { post } }
}
export default function Post ( { post } ) {
//...
} Пример для [[...name]].js :
import fetcher from 'nextein/fetcher'
import { inCategory } from 'nextein/filters'
const { getData , getPosts , getPost } = fetcher ( inCategory ( 'guides' ) )
export async function getStaticPaths ( ) {
const data = await getData ( )
return {
paths : [ { params : { name : [ ] } } ,
... data . map ( ( { name } ) => ( { params : { name : [ name ] } } ) )
] ,
fallback : false
}
}
export async function getStaticProps ( { params } ) {
const posts = await getPosts ( )
const post = await getPost ( params ) // This can be null if not matching `...name`
return { props : { posts , post } }
}
export default function Guides ( { posts , post } ) {
//...
}inCategory(category, options)Функция фильтра, которая будет применена к сообщениям для получения сообщений в данной категории.
category : {String} Категория для фильтрации результатов.options : {Object} НеобязательноincludeSubCategories: Boolean True, чтобы включить посты в подкатегории. По умолчанию: false Категории разрешаются структурой папок по умолчанию. Это означает, что пост, расположенный по posts/categoryA/subOne будет иметь категорию categoryA/subOne если вы не указате имя категории в передней части.
import { getPosts } from 'nextein/fetcher'
import { inCategory } from 'nextein/filters'
//...
const posts = await getPosts ( )
const homePosts = posts . filter ( inCategory ( 'home' ) )
Если вы хотите получить все сообщения в определенной категории, скажем, categoryA которая будет включать в себя все, кто находится под subOne , используйте варианты, includeSubCategories: true .
import { inCategory } from 'nextein/filters'
const categoryAPosts = posts
. filter ( inCategory ( 'categoryA' , { includeSubCategories : true } ) )Content Компонент для визуализации объекта post . Этот компонент получает content от поста в качестве свойства. Используйте свойство excerpt , чтобы отобразить первый абзац (это полезно при составлении списка сообщений).
content : {Object} Содержимое разметки в формате HAST для рендеринга. Это предоставлено post.contentexcerpt : {Boolean} Верно только для того, чтобы представить только первый абзац. Необязательный. По умолчанию: falserenderers : {Object} Набор пользовательских визуализаторов для элементов разметки с формой [tagName]: renderer .component : {String|React.Component} Компонент, используемый для корневого узла. import Content from 'nextein/content'
//...
export default function PostPage ( { post } ) {
return < Content { ... post } />
} Использование renderers для изменения/стиля тега <p>
const Paragraph = ( { children } ) => ( < p style = { { padding : 10 , background : 'silver' } } > { children } </ p > )
// Then in your render method ...
< Content
{ ... post }
renderers = { {
p : Paragraph
} }
/ >post__id является уникальным идентификатором, сгенерированным Nextein.data являются объектом FrontMatter. Содержание Meta Meta Information (заголовок, страница, категория и т. Д.)data.category - это категория сообщения. Если не указано, если пост находится внутри папки, будет использоваться структура каталогов в соответствии с posts .data.date : дата JSON с даты или даты FrontMatter в имени файла или дате создания файлаcontent является представлением пост -контента (обычно в формате HAST), созданном плагином Build для данного MimeType. { data , content } = post В метаданных фронтальных метаданных есть только несколько определенных свойств, которые используются nextein
---
category : categoryOne
date : 2017-06-23
---
Post Content...
category : название категории (необязательно)date : строка даты в формате Yyyy-MM-DD. Используется для сортировки списка сообщений. (необязательный)published : установите на false , чтобы удалить этот пост из записей.name : Прочитайте только имя файла сообщения. Дата удалена с имени, если присутствует.withNextein Функция конфигурации обертки, которая будет применена в next.config.js . Он предоставляет способ добавить свою собственную конфигурацию next.js вместе с nextein Internal Next.js Config.
Next.config.js
const { withNextein } = require ( 'nextein/config' )
module . exports = withNextein ( {
// Your own next.js config here
} ) Вы также можете определить плагины Nextein, используя конфигурацию withNextein :
const { withNextein } = require ( 'nextein/config' )
module . exports = withNextein ( {
nextein : {
plugins : [
//your nextein plugins here
]
}
// Your own next.js config here
} ) Конфигурация nextein.plugins принимает массив плагинов со следующими форматами:
[name] : просто строка для определения плагина.[name, options] : Строка для определения плагина и объекта параметров плагинов.{ name, id, options } : объект плагина. Поле name требуется. Все предыдущие определения преобразуются в этот формат. id необязателен, когда предоставляется, позволяет несколько экземпляров одного и того же плагина. name плагина должно быть предварительно установленным плагином ( nextein-plugin-markdown ) или локальным файлом ( ./myplugins/my-awesome-plugin )
Конфигурация по умолчанию включает в себя:
plugins: [
[ 'nextein-plugin-source-fs' , { path : 'posts' , data : { page : 'post' } } ] ,
'nextein-plugin-markdown' ,
'nextein-plugin-filter-unpublished'
] Читать файлы из файловой системы.
Параметры:
path : Путь к чтению файлов из.data : данные по умолчанию будут переданы в качестве дополнительных для каждой записи. По умолчанию {}includes : по умолчанию **/*.* .ignore : набор игнорируемых файлов. Список по умолчанию включает в себя: '**/.DS_Store' ,
'**/.gitignore' ,
'**/.npmignore' ,
'**/.babelrc' ,
'**/node_modules' ,
'**/yarn.lock' ,
'**/package-lock.json' Рендеринг файлов разметки.
Параметры:
raw : по умолчанию в true . Сделайте это false , чтобы не добавлять raw контент в объект Post.position : по умолчанию в false . Сделайте это true , чтобы добавить информацию о позиции, чтобы публиковать контент hast.rehype : по умолчанию [] . Добавьте набор плагинов для rehyperemark : по умолчанию [] . Добавить набор плагинов для remark Фильтрующие сообщения, используя свойство для предотвращения отображения черновиков / неопубликованных записей.
Параметры:
field : по умолчанию 'published' . Проверяет, присутствует ли field в data Post и фильтру, если установлено на false .Вы можете написать свои собственные плагины. Есть в основном 2 разных типа (источник и преобразование). Плагины исходного производства будут вызваны для генерации записей сообщений, а затем плагины Transform будут получать эти записи и могут модифицировать, фильтровать, добавлять или преобразовать в любом случае в списке сообщений.
Смотрите документ Plugins & LifeCyle Design.