如何使用Gatsby为WordPress生成静态网站

如何使用Gatsby为WordPress生成静态网站

典型的动态网站(例如基于 WordPress 的网站)如何工作?当访问者在浏览器上输入URL或通过链接访问您的网站时,会向您的Web服务器发送请求。

服务器通过必要的数据库查询收集所需的数据,并生成一个HTML文件供您的浏览器显示。另一方面,静态站点将这些响应存储到服务器上的平面文件中,这些文件会立即传递给访问者。

静态站点生成器已经存在了很长时间,但它们最近变得越来越流行。在本分步指南中,我们将了解如何将WordPress与静态网站生成器Gatsby集成。

  1. 什么是Gatsby?
  2. 第1步:设置Gatsby
  3. 第2步:如何将Gatsby连接到WordPress
  4. 第3步:创建基本页面模板
  5. 第4步:高级迁移任务

什么是Gatsby?

WordPress创建动态网站,需要在服务器上安装一堆PHP、MySQL和Apache或Nginx才能运行。可以通过为您网站上的所有内容生成HTML页面列表来创建WordPress的静态版本。

这个静态版本的WordPress称为无头WordPress或无服务器WordPress。此转换过程只需执行一次,以便可以多次向访问者提供同一页面。您如何将您的WordPress网站转换为静态版本?这就是Gatsby出现的地方。

Gatsby或GatsbyJS是一个使用ReactJS构建并由GraphQL提供支持的静态站点生成器。Gatsby允许任何人创建功能丰富、引人入胜的网站和应用程序。Gatsby通过GraphQL从各种来源(包括现有网站、API调用和平面文件)为您的站点获取数据,并根据您指定的配置设置构建静态站点。

Gatsby是一年前才开发出来的,但大量用户都在尝试Gatsby。Gatsby在各种环境中都得到了认可。Airbnb的数据科学与工程博客的主页由Gatsby提供支持,但实际的博客文章托管在Medium上。

Airbnb的工程与数据科学博客

Airbnb的工程与数据科学博客

BRAUN(博朗)是消费品公司宝洁的品牌。它的加拿大站点由Gatsby托管,而站点上的搜索功能由React提供支持。

博朗品牌的加拿大网站

博朗品牌的加拿大网站

此外,Gatsby还激发了自由职业者开发人员对其作品集的兴趣。诸如Jacob Castro的作品集主要包含静态内容,其中包含作品链接和电子邮件联系方式,因此静态网站非常适合他的需求。

Jacob D. Castro的作品展示站

Jacob D. Castro的作品展示站

为什么选择Gatsby?

快速网站: 使用Gatsby构建静态网站的主要好处是速度,自从Google宣布在网络搜索排名中使用网站速度以来,网站管理员一直在努力优化速度。加载时间也会影响页面浏览量和转化率。据估计,网站加载时间延迟一秒会导致转化次数减少7%。

安全性: 您还可以通过静态站点获得额外的安全性。由于提供的是一堆静态文件,因此没有什么可破解的。此外,如果静态文件丢失,您始终可以重新生成它们。

服务器成本:托管动态站点需要您的服务器与您的技术堆栈兼容。如果您使用的是静态站点,则几乎可以在任何服务器上托管它,这也降低了与托管相关的成本。

在每次更改时使用Gatsby生成静态站点确实需要JavaScript,这也可以在将静态文件传输到站点之前在本地计算机上完成。

为什么要避开Gatsby?

没有内置动态内容: 如果你想使用Gatsby,你需要重新考虑如何控制和提供动态内容,即你需要创建静态/动态的混合来实现这一点(更多关于这个以下)。

例如,评论需要通过像Disqus这样的服务在外部托管。

联系表格还需要通过Google表格等外部合作伙伴重新发送。简而言之,您将失去对此类动态内容的直接控制,因为它们的响应未存储在您的服务器上。

频繁构建不方便: 静态站点也存在频繁重新转换的问题。只有在重新生成页面并将其重新上传到服务器后,您在网站上所做的任何更改才会反映出来。

技术专长:  Gatsby建立在ReactJS和GraphQL之上。因此,需要一些JavaScript知识和GraphQL的基本概念来处理网站并将其移植到Gatsby。

静态网站非常适合那些正在寻找具有高安全性的低成本解决方案的人。一些用例是自由职业者的投资组合网站和产品演示网站。

如果您认为好处大于缺点,那就太好了!我们现在将尝试设置Gatsby以与我们的WordPress站点集成。

我们在本教程中构建的Gatsby站点的最新版本在GitHub上可供您使用。

第1步:设置Gatsby

在本节中,我们将了解如何安装Gatsby并使用Gatsby创建一个基本的静态站点。

先决条件

开始使用Gatsby的第一步是检查其先决条件。Gatsby通过npm(NodeJS包安装程序)提供服务。因此,在安装Gatsby之前,您的环境中需要NodeJS和npm。此外,Gatsby要求您安装源代码管理系统Git。

如果您运行的是Windows,您可以通过下载页面上的安装程序安装NodeJS和Git。在Mac上,您可以下载他们的安装程序或使用自制软件。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
brew install nodejs
brew install git
brew install nodejs brew install git
brew install nodejs
brew install git

如果您运行的是Linux操作系统,则可以通过apt之类的包安装程序安装NodeJS。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo apt update
sudo apt install nodejs git
sudo apt update sudo apt install nodejs git
sudo apt update
sudo apt install nodejs git

安装Gatsby

成功安装NodeJS和Git后,就可以安装Gatsby了!最简单的方法是在终端上运行以下命令(在Windows上使用命令行npm):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install -g gatsby-cli
npm install -g gatsby-cli
npm install -g gatsby-cli

安装程序首先安装依赖项,然后安装Gatsby。您现在已准备好创建您的第一个Gatsby站点。

构建和部署您的Gatsby站点

运行以下命令以创建Gatsby站点。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
gatsby new gatsby-wordpress
gatsby new gatsby-wordpress
gatsby new gatsby-wordpress

Gatsby通过克隆Gatsby入门模板在目录/gatsby-wordpress中创建一个站点。您可以提供不同的入门模板进行克隆。克隆完成并安装依赖项后,您可以使用以下命令运行站点的开发版本。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cd gatsby-wordpress
gatsby develop
cd gatsby-wordpress gatsby develop
cd gatsby-wordpress
gatsby develop

然后,您可以在http://localhost:8000访问该站点的开发版本。

Gatsby入门网站

Gatsby入门网站

最后一步是构建您的静态站点。以下命令在公共目录中创建静态文件。要将其上传到服务器,您只需将该目录的内容上传到服务器的根目录即可。您可能希望添加像www.example.com/blog/这样的路径前缀作为构建的根URL。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
gatsby build
gatsby build
gatsby build

要在本地启动HTML服务器以显示您网站的这种静态形式,您需要使用serve 命令。请注意,它仅在运行build命令后才有效。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
gatsby serve
gatsby serve
gatsby serve

现在您已经从Gatsby成功创建了一个基本的静态站点,让我们尝试将其与WordPress集成。

第2步:如何将Gatsby连接到WordPress

在本节中,您将把您的WordPress网站与Gatsby集成。您可以将Gatsby指向您的WordPress博客的地址,以使其在您运行开发服务器或生成静态页面时能够提取最新数据。

将Gatsby连接到WordPress的过程是获取由构建触发的WordPress数据。Gatsby获取WordPress数据后,它会根据当前模板创建静态站点。

该过程使用WordPress站点,该站点具有Gatsby上的文章的来源。为了方便这种交流,您需要通过以下命令安装Gatsby的WordPress插件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install gatsby-source-wordpress
npm install gatsby-source-wordpress
npm install gatsby-source-wordpress

配置Gatsby

接下来,将此插件添加到Gatsby的配置文件gatsby-config.js中。

然后,将以下代码添加到文件中以将Gatsby连接到您的WordPress源。在此示例中,我们在MAMP上使用本地托管的WordPress站点。在旁注中,您可能希望在siteMetadata中编辑站点的标题和描述。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>module.exports = {
siteMetadata: {
...
},
plugins: [
...
{
resolve: `gatsby-source-wordpress`,
options: {
// Specify the URL of the WordPress source
baseUrl: `localhost:8888/wordpress`,
protocol: `http`,
// Indicates if a site is hosted on WordPress.com
hostingWPCOM: false,
// Specify which URL structures to fetch
includedRoutes: [
'**/posts',
'**/tags',
'**/categories'
]
}
}
</code>
<code>module.exports = { siteMetadata: { ... }, plugins: [ ... { resolve: `gatsby-source-wordpress`, options: { // Specify the URL of the WordPress source baseUrl: `localhost:8888/wordpress`, protocol: `http`, // Indicates if a site is hosted on WordPress.com hostingWPCOM: false, // Specify which URL structures to fetch includedRoutes: [ '**/posts', '**/tags', '**/categories' ] } } </code>
module.exports = {
siteMetadata: {
...
},
plugins: [
...
{
resolve: `gatsby-source-wordpress`,
options: {
// Specify the URL of the WordPress source
baseUrl: `localhost:8888/wordpress`,
protocol: `http`,
// Indicates if a site is hosted on WordPress.com
hostingWPCOM: false,
// Specify which URL structures to fetch
includedRoutes: [
'**/posts',
'**/tags',
'**/categories'
]
}
}

使用GraphQL获取文章

在配置文件中指定WordPress站点的来源后,您需要指定需要从WordPress站点提取哪些数据。Gatsby使用GraphQL(一种用于API的开源查询语言)来批量获取WordPress文章。

在最终确定要选择的查询之前,您可以交互地选择需要从WordPress获取的内容。运行开发服务器并转到URL:http://localhost:8000/___graphql以打开GraphQL编辑器。

使用GraphQL查询数据

使用GraphQL查询数据

完成要拉取的内容后,可以将GraphQL查询添加到文件index.js。

现在让我们只从每个文章中提取标题和摘录。我们可以稍后添加更多字段。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
export default ({ data }) => {
return (
<Layout>
<SEO title="home" />
<h4>Posts</h4>
{data.allWordpressPost.edges.map(({ node }) => (
<div>
<p>{node.title}</p>
<div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
</div>
))}
</Layout>
)
}
export const pageQuery = graphql`
query {
allWordpressPost(sort: { fields: [date] }) {
edges {
node {
title
excerpt
}
}
}
}
import React from "react" import { graphql } from "gatsby" import Layout from "../components/layout" import SEO from "../components/seo" export default ({ data }) => { return ( <Layout> <SEO title="home" /> <h4>Posts</h4> {data.allWordpressPost.edges.map(({ node }) => ( <div> <p>{node.title}</p> <div dangerouslySetInnerHTML={{ __html: node.excerpt }} /> </div> ))} </Layout> ) } export const pageQuery = graphql` query { allWordpressPost(sort: { fields: [date] }) { edges { node { title excerpt } } } }
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
export default ({ data }) => {
return (
<Layout>
<SEO title="home" />
<h4>Posts</h4>
{data.allWordpressPost.edges.map(({ node }) => (
<div>
<p>{node.title}</p>
<div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
</div>
))}
</Layout>
)
}
export const pageQuery = graphql`
query {
allWordpressPost(sort: { fields: [date] }) {
edges {
node {
title
excerpt
}
}
}
}

当您检查开发站点时,您会注意到所有来自WordPress的文章都已被拉取,并显示了它们的标题和摘录:

带有WordPress文章的Gatsby主页

带有WordPress文章的Gatsby主页

虽然这看起来不太漂亮,但您已经成功地从WordPress中提取了相关数据。下一步是为每个文章创建一个新页面。

第3步:创建基本页面模板

在本节中,您将触发Gatsby为您的WordPress站点的每个页面创建一个文章,并通过slug包含指向这些文章的链接。

为每个文章创建一个页面

从WordPress源中提取所有文章后的第一步是指示Gatsby为每个文章创建一个页面。这是使用动作完成的createPage 动作。

将以下代码添加到gatsby-node.js。请注意,我们还获取了每个文章的内容、作者、日期和slug:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const path = require(`path`)
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return graphql(`
{
allWordpressPost(sort: {fields: [date]}) {
edges {
node {
title
excerpt
slug
date(formatString: "MM-DD-YYYY")
author {
name
}
}
}
}
}
`).then(result => {
result.data.allWordpressPost.edges.forEach(({ node }) => {
createPage({
// Decide URL structure
path: node.slug,
// path to template
component: path.resolve(`./src/templates/blog-post.js`),
context: {
// This is the $slug variable
// passed to blog-post.js
slug: node.slug,
},
})
})
})
const path = require(`path`) exports.createPages = ({ graphql, actions }) => { const { createPage } = actions return graphql(` { allWordpressPost(sort: {fields: [date]}) { edges { node { title excerpt slug date(formatString: "MM-DD-YYYY") author { name } } } } } `).then(result => { result.data.allWordpressPost.edges.forEach(({ node }) => { createPage({ // Decide URL structure path: node.slug, // path to template component: path.resolve(`./src/templates/blog-post.js`), context: { // This is the $slug variable // passed to blog-post.js slug: node.slug, }, }) }) })
const path = require(`path`)
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return graphql(`
{
allWordpressPost(sort: {fields: [date]}) {
edges {
node {
title
excerpt
slug
date(formatString: "MM-DD-YYYY")
author {
name
}
}
}
}
}
`).then(result => {
result.data.allWordpressPost.edges.forEach(({ node }) => {
createPage({
// Decide URL structure
path: node.slug,
// path to template
component: path.resolve(`./src/templates/blog-post.js`),
context: {
// This is the $slug variable
// passed to blog-post.js
slug: node.slug,
},
})
})
})

从GraphQL提取数据后,代码为每个文章创建一个页面。在文章中,您可以使用路径基于slug指定页面的URL结构。

或者,您可以获取文章的ID并在URL中指定。组件变量指向需要渲染文章的模板。最后,我们将slug作为模板的上下文传递。这是模板从获取的文章列表中查询正确文章所必需的。

理想情况下,您需要传递一个将文章唯一标识为上下文的变量。

更改gatsby-node.js文件后重新启动开发服务器以使更改生效。

创建模板以显示文章

在src目录中创建目录模板。在模板目录中创建一个新文件blog-post.js并输入以下代码:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import React from "react"
import Layout from "../components/layout"
import { graphql } from "gatsby"
export default ({ data }) => {
const post = data.allWordpressPost.edges[0].node
console.log(post)
return (
<Layout>
<div>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
<p> By: {post.author.name} </p>
<p> On: {post.date} </p>
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
allWordpressPost(filter: { slug: { eq: $slug } }) {
edges {
node {
title
content
slug
date(formatString: "MM-DD-YYYY")
author {
name
}
}
}
}
}
import React from "react" import Layout from "../components/layout" import { graphql } from "gatsby" export default ({ data }) => { const post = data.allWordpressPost.edges[0].node console.log(post) return ( <Layout> <div> <h1>{post.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.content }} /> <p> By: {post.author.name} </p> <p> On: {post.date} </p> </div> </Layout> ) } export const query = graphql` query($slug: String!) { allWordpressPost(filter: { slug: { eq: $slug } }) { edges { node { title content slug date(formatString: "MM-DD-YYYY") author { name } } } } }
import React from "react"
import Layout from "../components/layout"
import { graphql } from "gatsby"
export default ({ data }) => {
const post = data.allWordpressPost.edges[0].node
console.log(post)
return (
<Layout>
<div>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
<p> By: {post.author.name} </p>
<p> On: {post.date} </p>
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
allWordpressPost(filter: { slug: { eq: $slug } }) {
edges {
node {
title
content
slug
date(formatString: "MM-DD-YYYY")
author {
name
}
}
}
}
}

GraphQL查询获取日期和作者姓名,它们显示在文章的末尾。您可以使用GraphQL编辑器获取其他字段并将它们显示在文章页面上。

您为每个文章创建了一个新页面。但是,您需要从索引页面添加指向这些文章的链接。前往index.js并修改代码以将链接添加到每个文章:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
export default ({ data }) => {
return (
<Layout>
<SEO title="home" />
<h1>My WordPress Blog</h1>
<h4>Posts</h4>
{data.allWordpressPost.edges.map(({ node }) => (
<div>
<Link to={node.slug}>
<p>{node.title}</p>
</Link>
<div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
</div>
))}
</Layout>
)
}
export const pageQuery = graphql`
query {
allWordpressPost(sort: { fields: [date] }) {
edges {
node {
title
excerpt
slug
}
}
}
}
import React from "react" import { Link, graphql } from "gatsby" import Layout from "../components/layout" import SEO from "../components/seo" export default ({ data }) => { return ( <Layout> <SEO title="home" /> <h1>My WordPress Blog</h1> <h4>Posts</h4> {data.allWordpressPost.edges.map(({ node }) => ( <div> <Link to={node.slug}> <p>{node.title}</p> </Link> <div dangerouslySetInnerHTML={{ __html: node.excerpt }} /> </div> ))} </Layout> ) } export const pageQuery = graphql` query { allWordpressPost(sort: { fields: [date] }) { edges { node { title excerpt slug } } } }
import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
export default ({ data }) => {
return (
<Layout>
<SEO title="home" />
<h1>My WordPress Blog</h1>
<h4>Posts</h4>
{data.allWordpressPost.edges.map(({ node }) => (
<div>
<Link to={node.slug}>
<p>{node.title}</p>
</Link>
<div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
</div>
))}
</Layout>
)
}
export const pageQuery = graphql`
query {
allWordpressPost(sort: { fields: [date] }) {
edges {
node {
title
excerpt
slug
}
}
}
}

以下是索引页面的状态:

添加文章链接后的索引页面

添加文章链接后的索引页面

单击文章链接时,这里是博客文章页面,由blog-post.js呈现:

带有标题、内容、创建日期和作者的博客文章

带有标题、内容、创建日期和作者的博客文章

第4步:高级迁移任务

虽然您可能已成功导入每个WordPress文章,但让我们执行一些高级任务以确保您将来不会遇到问题。在本节中,您可以有效地处理图像并将上次修改日期时间戳添加到您的数据中。

图像路径转换

我们的原始文章之一,“Post with Image!” 里面有一张图片。如果你在Gatsby上移动到相应的页面,你会注意到图片显示出来了,但是图片的来源和WordPress的一样。在此示例中,它指向本地托管的WordPress图像。

Gatsby发布图片及其来源

Gatsby发布图片及其来源

如果您在外部托管图像,这不会造成问题,因为您将继续指向您的图像服务器。但是,如果您将图像存储在WordPress安装中,您也需要获取带有文章的图像!

这是由inline images插件解决的。首先,安装插件gatsby-image,然后安装。gatsby-wordpress-inline-images

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install gatsby-image
npm install gatsby-wordpress-inline-images
npm install gatsby-image npm install gatsby-wordpress-inline-images
npm install gatsby-image
npm install gatsby-wordpress-inline-images

接下来,将以下行添加到您的gatsby-config.js 文件中。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
module.exports = {
siteMetadata: {
...
},
plugins: [
...
{
resolve: `gatsby-source-wordpress`,
options: {
...
// If useACF is true, then the source plugin will try to import the WordPress ACF Plugin contents.
// This feature is untested for sites hosted on WordPress.com
useACF: true,
plugins: [
{
resolve: `gatsby-wordpress-inline-images`,
options:
{
baseUrl: `localhost:8888/wordpress`,
protocol: `http`
}
}
]
}
}
],
}
module.exports = { siteMetadata: { ... }, plugins: [ ... { resolve: `gatsby-source-wordpress`, options: { ... // If useACF is true, then the source plugin will try to import the WordPress ACF Plugin contents. // This feature is untested for sites hosted on WordPress.com useACF: true, plugins: [ { resolve: `gatsby-wordpress-inline-images`, options: { baseUrl: `localhost:8888/wordpress`, protocol: `http` } } ] } } ], }
module.exports = {
siteMetadata: {
...
},
plugins: [
...
{
resolve: `gatsby-source-wordpress`,
options: {
...
// If useACF is true, then the source plugin will try to import the WordPress ACF Plugin contents.
// This feature is untested for sites hosted on WordPress.com
useACF: true,
plugins: [
{
resolve: `gatsby-wordpress-inline-images`,
options:
{
baseUrl: `localhost:8888/wordpress`,
protocol: `http`
}
}
]
}
}
],
}

进行这些更改后重新启动开发服务器将从WordPress站点下载图像并将其存储在本地。您可以从同一图像的路径中验证这一点。

显示上次修改日期

如果您管理一个定期更新文章的博客,您可能希望在最后一次更新文章时通知读者。虽然您之前在GraphQL查询中提取了“created date”,但本节也将告诉您如何提取“last modified”时间戳。

要将WordPress的最后修改时间戳添加到您的Gatsby文章中,您需要将修改后的字段添加到GraphQL查询中的项目列表中。它是一个时间戳date,所以你还需要添加参数formatString。这是修改后的blog-post.js文件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
...
<Layout>
<div>
...
<p> On: {post.date} </p>
<p> Last modified: {post.modified} </p>
</div>
</Layout>
...
export const query = graphql`
query($slug: String!) {
{
allWordpressPost {
edges {
node {
...
modified(formatString: "MM-DD-YYYY")
}
}
}
}
... <Layout> <div> ... <p> On: {post.date} </p> <p> Last modified: {post.modified} </p> </div> </Layout> ... export const query = graphql` query($slug: String!) { { allWordpressPost { edges { node { ... modified(formatString: "MM-DD-YYYY") } } } }
...
<Layout>
<div>
...
<p> On: {post.date} </p>
<p> Last modified: {post.modified} </p>
</div>
</Layout>
...
export const query = graphql`
query($slug: String!) {
{
allWordpressPost {
edges {
node {
...
modified(formatString: "MM-DD-YYYY")
}
}
}
}

添加后,您将能够在Gatsby的博客文章页面上看到上次修改的时间戳:

使用最后修改的时间戳发布

使用最后修改的时间戳发布

小结

决定利用Gatsby将您的WordPress网站转换为静态网站可能是一项具有挑战性的任务。为此,您应该执行以下步骤:

  • 安装Gatsby以构建起始站点
  • 通过GraphQL将Gatsby连接到WordPress源
  • 为博客文章创建模板
  • 从WordPress导入所有图像
  • 显示来自WordPress的最后修改时间戳

评论留言