[WordPress] 外掛分享: Static Site Exporter

首頁外掛目錄 › Static Site Exporter
WordPress 外掛 Static Site Exporter 的封面圖片
500+
安裝啟用
★★★☆☆
3.5/5 分(12 則評價)
37 天前
最後更新
問題解決
WordPress 4.4+ PHP 7.2+ v3.1.1 上架:2014-12-11

內容簡介

nclude information relevant to the issue you are reporting.

功能

將所有文章、頁面和 WordPress 設定轉換為 Markdown 和 YAML 格式,可用於 Jekyll(或 Hugo 或任何其他基於 Markdown 和 YAML 的網站引擎)
輸出的內容為用戶查看的內容,而非資料庫中存儲的內容(在導出之前,通過 the_content 附加外掛運行文章內容,從而允許第三方插件修改輸出內容)
將所有 post_content 轉換為 Markdown
將所有 post_meta 和 wp_posts 表格中的欄位轉換為 YAML 前置資料以便 Jekyll 排序
生成包含 wp_options 表格中所有設定的 _config.yml
輸出單個 zip 檔,其中包含 _config.yml、頁面和 _posts 文件夾,其中包含符合 Jekyll 命名慣例的每篇文章的 .md 檔案
無需進行任何設置,只需一個單擊即可完成

使用方法

將插件放置在 /wp-content/plugins/ 文件夾中
在 WordPress 控制台中啟用插件
從 工具 菜單中選擇 導出到 Jekyll

更多信息

參閱完整文檔:

更新日誌
命令行用法
自定文章類型
本地開發
最低要求的 PHP 版本

安全政策

如需報告安全漏洞,請發送電子郵件至 [email protected]

獲得幫助或報告問題的位置

如需開始使用和一般文檔,請瀏覽並隨時貢獻該項目文檔
對於支援問題(例如“我該怎麼做”的問題),請搜索並如未有答案,請在支援論壇中開啟一個主題。
對於技術問題(例如提交錯誤或功能請求),請搜索並如未創建,請在 GitHub 上開啟問題。

報告問題前的檢查事項

您是否使用最新版本的 WordPress?
您是否使用最新版本的插件?
即使停用所有外掛並使用默認主題,問題是否仍然發生?
您是否嘗試過停用並重新啟用該插件?
是否已報告您的問題?

在問題中包括哪些內容

其他使用者可採取哪些步驟以重新生成問題?
該操作的預期結果是什麼?
實際結果是什麼?
是否有任何屏幕截圖或屏幕錄像可以添加?
僅包含與您報告的問題相關的信息。

外掛標籤

開發者團隊

⬇ 下載最新版 (v3.1.1) 或搜尋安裝

① 下載 ZIP → 後台「外掛 › 安裝外掛 › 上傳外掛」
② 後台搜尋「Static Site Exporter」→ 直接安裝(推薦)
📦 歷史版本下載

原文外掛簡介

Features

Converts all posts, pages, and settings from WordPress to Markdown and YAML for use in Jekyll (or Hugo or any other Markdown and YAML based site engine)
Export what your users see, not what the database stores (runs post content through the_content filter prior to export, allowing third-party plugins to modify the output)
Converts all post_content to Markdown
Converts all post_meta and fields within the wp_posts table to YAML front matter for parsing by Jekyll
Generates a _config.yml with all settings in the wp_options table
Outputs a single zip file with _config.yml, pages, and _posts folder containing .md files for each post in the proper Jekyll naming convention
Selective export: Export only specific categories, tags, or post types using WP-CLI
No settings. Just a single click.

Usage

Place plugin in /wp-content/plugins/ folder
Activate plugin in WordPress dashboard
Select Export to Jekyll from the Tools menu

More information
See the full documentation:

Changelog
Command-line-usage
Selective export by category or tag
Custom post types
Custom fields
Developing locally
Minimum required PHP version

Security Policy
To report a security vulnerability, please email [email protected].
Where to get help or report an issue

For getting started and general documentation, please browse, and feel free to contribute to the project documentation.
For support questions (“How do I”, “I can’t seem to”, etc.) please search and if not already answered, open a thread in the Support Forums.
For technical issues (e.g., to submit a bug or feature request) please search and if not already filed, open an issue on GitHub.

Things to check before reporting an issue

Are you using the latest version of WordPress?
Are you using the latest version of the plugin?
Does the problem occur even when you deactivate all plugins and use the default theme?
Have you tried deactivating and reactivating the plugin?
Has your issue already been reported?

What to include in an issue

What steps can another user take to recreate the issue?
What is the expected outcome of that action?
What is the actual outcome of that action?
Are there any screenshots or screencasts that may be helpful to include?
Only include one bug per issue. If you have discovered two bugs, please file two issues.

Command-line Usage
If you’re having trouble with your web server timing out before the export is complete, or if you just like terminal better, you may enjoy the command-line tool.
It works just like the plugin, but produces the zipfile on STDOUT:
`

php jekyll-export-cli.php > jekyll-export.zip
`
If using this method, you must run first cd into the wordpress-to-jekyll-exporter directory.
Alternatively, if you have WP-CLI installed, you can run:
`

wp jekyll-export > export.zip
`
The WP-CLI version will provide greater compatibility for alternate WordPress environments, such as when wp-content isn’t in the usual location.
Filtering by Category or Tag
You can export only specific categories or tags using the WP-CLI command. This is useful when you want to convert just one section of your WordPress site instead of the entire corpus.
Export posts from a specific category:
`bash

wp jekyll-export –category=technology > export.zip
`
Export posts from multiple categories:
`bash

wp jekyll-export –category=tech,news,updates > export.zip
`
Export posts with a specific tag:
`bash

wp jekyll-export –tag=featured > export.zip
`
Export only pages (or specific post types):
`bash

wp jekyll-export –post_type=page > export.zip
`
Combine filters:
`bash

wp jekyll-export –category=technology –tag=featured –post_type=post > export.zip

Using Filters in PHP

If you're using the plugin via PHP code or want more control, you can use thejekyll_export_taxonomy_filters` filter:
`php

add_filter( ‘jekyll_export_taxonomy_filters’, function() {
return array(
‘category’ => array( ‘technology’, ‘science’ ),
‘post_tag’ => array( ‘featured’ ),
);
} );
// Then trigger the export
global $jekyll_export;
$jekyll_export->export();
`
Custom fields
When using custom fields (e.g. with the Advanced Custom fields plugin) you might have to register a filter to convert array style configs to plain values.
Available Filters
The plugin provides two filters for customizing post metadata:

jekyll_export_meta: Filters the metadata for a single post before it’s merged with taxonomy terms. Receives $meta array as the only parameter.
jekyll_export_post_meta: Filters the complete metadata array (including taxonomy terms) just before it’s written to the YAML frontmatter. Receives $meta array and $post object as parameters. This is the recommended filter for most use cases.

Note: As of the latest version, the plugin no longer automatically removes empty or falsy values from the frontmatter. All metadata is preserved by default. If you want to remove certain fields, you can use the jekyll_export_post_meta filter to customize this behavior.
By default, the plugin saves custom fields in an array structure that is exported as:
`php

[“my-bool”]=>
array(1) {
[0] => string(1) “1”
}
[“location”]=>
array(1) {
[0] => string(88) “My address”
}
`
And this leads to a YAML structure like:
`yaml

my-bool:
– “1”
location:
– ‘My address’
`
This is likely not the structure you expect or want to work with. You can convert it using a filter:
`php

add_filter( ‘jekyll_export_meta’, function($meta) {
foreach ($meta as $key => $value) {
if (is_array($value) && count($value) === 1 && array_key_exists(0, $value)) {
$meta[$key] = $value[0];
}
}
return $meta;

});
`
A more complete solution could look like that:
`php

add_filter( ‘jekyll_export_meta’, function($meta) {
foreach ($meta as $key => $value) {
// Advanced Custom Fields
if (is_array($value) && count($value) === 1 && array_key_exists(0, $value)) {
$value = maybe_unserialize($value[0]);
// Advanced Custom Fields: NextGEN Gallery Field add-on
if (is_array($value) && count($value) === 1 && array_key_exists(0, $value)) {
$value = $value[0];
}
}
// convert types
$value = match ($key) {
// Advanced Custom Fields: “true_false” type
‘my-bool’ => (bool) $value,
default => $value
};
$meta[$key] = $value;
}
return $meta;

});
`
Removing Empty or Falsy Values
If you want to remove empty or falsy values from the frontmatter (similar to the pre-3.0.3 behavior), you can use the jekyll_export_post_meta filter:
`php

add_filter( ‘jekyll_export_post_meta’, function( $meta, $post ) {
foreach ( $meta as $key => $value ) {
// Remove falsy values except numeric 0
if ( ! is_numeric( $value ) && ! $value ) {
unset( $meta[ $key ] );
}
}
return $meta;
}, 10, 2 );
`
Custom post types
To export custom post types, you’ll need to add a filter (w.g. to your themes config file) to do the following:
`php

add_filter( ‘jekyll_export_post_types’, function() {
return array(‘post’, ‘page’, ‘you-custom-post-type’);
});
`
The custom post type will be exported as a Jekyll collection. You’ll need to initialize it in the resulting Jekyll site’s _config.yml.
Developing locally
Option 1: Using Dev Containers (Recommended)
The easiest way to get started is using VS Code Dev Containers or GitHub Codespaces:

Install VS Code and the Dev Containers extension
git clone https://github.com/benbalter/wordpress-to-jekyll-exporter
Open the folder in VS Code
Click “Reopen in Container” when prompted
Wait for the container to build and dependencies to install
Access WordPress at http://localhost:8088

The devcontainer includes:
– Pre-configured WordPress and MySQL
– All PHP extensions and Composer dependencies
– VS Code extensions for PHP development, debugging, and testing
– WordPress coding standards configured
See .devcontainer/README.md for more details.
Option 2: Manual Setup
Prerequisites

sudo apt-get update
sudo apt-get install composer
sudo apt-get install php7.3-xml
sudo apt-get install php7.3-mysql
sudo apt-get install php7.3-zip
sudo apt-get install php-mbstring
sudo apt-get install subversion
sudo apt-get install mysql-server
sudo apt-get install php-pear
sudo pear install PHP_CodeSniffer

Bootstrap & Setup

git clone https://github.com/benbalter/wordpress-to-jekyll-exporter
cd wordpress-to-jekyll-exporter
script/bootstrap
script/setup

Option 3: Docker Compose Only

git clone https://github.com/benbalter/wordpress-to-jekyll-exporter
docker-compose up
open localhost:8088

Running tests
script/cibuild

Performance Optimizations

This document describes the performance optimizations implemented in Static Site Exporter to improve export speed and reduce resource usage, especially for large WordPress sites.
Overview
The following optimizations have been implemented to address performance bottlenecks identified in the export process:
1. Optimized Database Queries
Problem: The original get_posts() method executed a separate SQL query for each post type, then merged the results using array_merge().
`php

// Before (inefficient)
foreach ( $post_types as $post_type ) {
$ids = $wpdb->get_col( $wpdb->prepare( “SELECT ID FROM {$wpdb->posts} WHERE post_type = %s”, $post_type ) );
$posts = array_merge( $posts, $ids );
}
`
Solution: Changed to a single SQL query using an IN clause.
`php

// After (optimized)
$placeholders = implode( ‘, ‘, array_fill( 0, count( $post_types ), ‘%s’ ) );
$query = “SELECT ID FROM {$wpdb->posts} WHERE post_type IN ($placeholders)”;
$posts = $wpdb->get_col( $wpdb->prepare( $query, $post_types ) );
`
Impact: Reduces database round trips from N (number of post types, typically 3) to 1, significantly improving performance on sites with many posts.
2. User Data Caching
Problem: The convert_meta() method called get_userdata() for every post, resulting in redundant database queries for posts by the same author (N+1 query problem).
`php

// Before (inefficient)
‘author’ => get_userdata( $post->post_author )->display_name,
`
Solution: Implemented a static cache to store user data across post conversions.
`php

// After (optimized)
static $user_cache = array();
if ( ! isset( $user_cache[ $post->post_author ] ) ) {
$user_data = get_userdata( $post->post_author );
$user_cache[ $post->post_author ] = $user_data ? $user_data->display_name : ”;
}
‘author’ => $user_cache[ $post->post_author ],
`
Impact: Eliminates redundant database queries for author information. On a site with 1000 posts by 10 authors, this reduces queries from 1000 to 10.
3. HTML to Markdown Converter Reuse
Problem: A new HtmlConverter instance was created for every post, wasting memory and CPU cycles on object initialization.
`php

// Before (inefficient)
$converter = new HtmlConverter( $converter_options );
$converter->getEnvironment()->addConverter( new TableConverter() );
`
Solution: Reuse a single static instance across all post conversions.
`php

// After (optimized)
static $converter = null;
if ( null === $converter ) {
$converter_options = apply_filters( ‘jekyll_export_markdown_converter_options’, array( ‘header_style’ => ‘atx’ ) );
$converter = new HtmlConverter( $converter_options );
$converter->getEnvironment()->addConverter( new TableConverter() );
}
`
Impact: Reduces object creation overhead. On a site with 1000 posts, this eliminates 999 unnecessary object instantiations.
4. Improved File Operations
Problem: The copy_recursive() method used the legacy dir() API which is slower than modern alternatives.
`php

// Before (inefficient)
$dir = dir( $source );
while ( $entry = $dir->read() ) {
// process files
}
$dir->close();
`
Solution: Replaced with scandir() which is faster and more memory-efficient.
`php

// After (optimized)
$entries = @scandir( $source );
if ( false === $entries ) {
return false;
}
foreach ( $entries as $entry ) {
// process files
}
`
Impact: Improves directory traversal speed, particularly noticeable when copying large upload directories.
5. Upload Directory Filtering
New Feature: Added filters to allow skipping or excluding directories during the upload copy process.
Skip Entire Uploads:
php
add_filter( 'jekyll_export_skip_uploads', '__return_true' );
Exclude Specific Directories (e.g., cache or temporary files):
php
add_filter( 'jekyll_export_excluded_upload_dirs', function( $excluded ) {
return array_merge( $excluded, array( '/cache/', '/tmp/', '/backup/' ) );
} );
Impact: Allows large sites to:
– Skip uploads entirely if they’re served from a CDN
– Exclude cache directories that aren’t needed in the export
– Reduce export time and file size for very large installations
Performance Benchmarks
Estimated Improvements
Based on the optimizations, expected performance improvements for a typical WordPress site:
Site Size
Before
After
Improvement
Small (100 posts, 5 authors)
~5s
~3s
40% faster
Medium (1000 posts, 20 authors)
~45s
~20s
55% faster
Large (10000 posts, 50 authors)
~8min
~3min
63% faster
Note: Actual performance depends on server hardware, database configuration, and content complexity.
Database Query Reduction
Operation
Queries Before
Queries After
Reduction
Get posts (3 post types)
3
1
67%
User data (100 posts, 5 authors)
100
5
95%
Total for 100 posts
103
6
94%
Backward Compatibility
All optimizations maintain backward compatibility:
– All existing WordPress hooks and filters continue to work
– No changes to the exported file format
– No changes to the public API
– New filters are opt-in and don’t affect default behavior
Additional Optimization Tips
For even better performance on large sites:

Increase PHP memory limit: Add to wp-config.php:
php
define( 'WP_MEMORY_LIMIT', '512M' );

Use WP-CLI: The command-line interface bypasses web server timeouts:
bash
wp jekyll-export > export.zip

Skip uploads if using CDN: If your uploads are served from a CDN, you can skip copying them:
php
add_filter( 'jekyll_export_skip_uploads', '__return_true' );

Enable object caching: Use Redis or Memcached to speed up WordPress core queries.

Technical Notes
Why Static Variables?
Static variables in PHP persist across function calls within the same request. This makes them ideal for caching data during a batch export process where the same function is called many times (once per post).
Thread Safety
These optimizations are safe for:
– Single-threaded PHP execution (standard)
– WordPress multisite installations
– WP-CLI execution
They are NOT designed for:
– Multi-threaded or async PHP environments (not common in WordPress)
– Long-running daemon processes (not the intended use case)
Future Optimization Opportunities
Potential areas for future improvement:

Bulk metadata loading: Pre-load all post meta in a single query
Taxonomy term caching: Pre-load all terms to avoid per-post queries
Streaming ZIP creation: Write directly to ZIP instead of creating temp directory
Parallel processing: Use multiple processes for very large exports (WP-CLI only)

Questions?
For questions about these optimizations or to report performance issues:
– Open an issue
– View the documentation
Performance Tips for Large Sites
If you’re running a large WordPress site with thousands of posts or gigabytes of uploads, here are some tips to make the export process faster and more efficient.
Quick Wins
1. Use WP-CLI Instead of Browser Export
Browser-based exports are subject to PHP execution time limits (typically 30-300 seconds). Use WP-CLI for unlimited execution time:
`bash

wp jekyll-export > export.zip
`
2. Skip Uploads if You Don’t Need Them
If your images and files are served from a CDN or you plan to handle them separately, you can skip the uploads directory entirely:
`php

// Add to your theme’s functions.php or a custom plugin
add_filter( ‘jekyll_export_skip_uploads’, ‘__return_true’ );
`
This can save significant time and disk space, especially if you have gigabytes of media files.
3. Exclude Cache and Temporary Directories
Many sites accumulate cache files and temporary uploads that aren’t needed in the export:
`php

add_filter( ‘jekyll_export_excluded_upload_dirs’, function( $excluded ) {
return array_merge( $excluded, array(
‘/cache/’,
‘/tmp/’,
‘/backup/’,
‘/wc-logs/’, // WooCommerce logs
‘/wpml/’, // WPML cache
) );
} );
`
Performance Improvements in Version 2.4.3+
Recent optimizations …

延伸相關外掛

文章
Filter
Apply Filters
Mastodon