中文版请见 README.zh_CN.md.
TL;DR: OptIFT minimizes CJK web font loading times by using clever font subsetting and partitioning based on page-wise character usage patterns. It reduces the total bytes loaded by over 50% compared to Google Fonts.
OptIFT applied to Vue docs:
OptIFT applied to React docs:
- Introduction
- Quick start
- Detailed usage
- Partitions explained
- Comparison with other solutions
- Building from source
- Legal considerations
- Contributing
- Acknowledgements
Web fonts are essential for creating a visually appealing web experience. However, for ideographic languages like Chinese, web fonts are significantly larger than those used for alphabetical languages, which can lead to long loading times.
While common alphabetical fonts like Latin cover their entire alphabet in a few dozen glyphs, CJK fonts require thousands of glyphs. A complete Chinese font can easily reach tens of megabytes in size, creating a major bottleneck for web performance.
OptIFT addresses this problem by:
- Subsetting fonts based on actual character usage in your content.
- Partitioning the subsetted fonts to balance performance for single-page and multi-page visits.
- Generating optimized WOFF2 font files and corresponding CSS for your static site.
If you have a static site with CJK content and want to improve font loading performance, OptIFT is designed for you.
Here’s how to get started with OptIFT in a few steps:
Make sure you have CMake, a C++ compiler, and Vcpkg installed. Then clone the OptIFT repository:
$ git clone https://github.com/ma-chengyuan/optift.git
$ cd optift
Make sure you have configured the VCPKG_ROOT
environment variable.
$ mkdir build && cd build
$ cmake .. --preset vcpkg
$ cmake --build .
You can also download prebuilt binaries from the Github Action artifacts in the repository. The Linux binaries are fully statically linked, so they should work out of the box on most distributions.
Prepare a simple input JSON file (see Input JSON Specification for details) and run the following command:
$ ./optift -i input.json -o output/ -n 10
This command will generate partitioned WOFF2 font files and a CSS file in the specified output directory.
OptIFT requires an input JSON file specifying the fonts and characters used on your website. Here’s a minimal example:
{
"fonts": {
"regular": {
"path": "path/to/SourceHanSansSC-Regular.otf",
"css": {
"font-family": "SourceHanSans",
"font-weight": "normal"
}
}
},
"posts": {
"post-1": {
"weight": 1,
"codepoints": {
"regular": "你好世界"
}
}
}
}
- fonts: Defines the fonts you want to subset. Each font entry contains:
path
: Path to the OTF or TTF font file.css
:@font-face
CSS properties to be added in the output CSS.
- posts: Lists pages or posts on your site and their character usage.
weight
: A relative importance weight for the page.codepoints
: Characters used in the page, grouped by font style.
You can define multiple fonts and posts as needed. For a more complex example, see the full input JSON example.
After running OptIFT, you will get:
- Subsetted WOFF2 fonts: Optimized web fonts partitioned into smaller chunks.
- CSS file: A stylesheet linking the generated fonts and defining their usage.
OptIFT balances two extremes when subsetting fonts:
- One subset per page: Minimal bytes loaded for single-page visits, but high total bytes if users visit multiple pages.
- One subset for the entire site: Reusable across pages but results in large initial loads.
By creating partitions, OptIFT finds a middle ground:
- Common characters are grouped into shared partitions.
- Rare characters are placed in smaller, page-specific partitions.
Empirical testing shows that 10-30 partitions typically provide the best trade-off.
Feature | OptIFT | Google Fonts | CNFS | Incremental Font Transfer (IFT) |
---|---|---|---|---|
Based on page-wise glyph usage | Yes | No | No | Yes |
Ease of use | Medium | High | High | High |
Dynamic site support | No | Yes | Yes | Yes |
OpenType feature support | Untested | Full | Full | Full |
Standardized browser support | No | No | No | Proposed |
Google Fonts offers a good out-of-the-box solution for CJK web fonts. It uses machine learning to subset and slice fonts efficiently, providing a substantial performance improvement over default solutions. OptIFT, however, often achieves an additional 50% reduction in bytes loaded by tailoring the fonts specifically to your site’s content.
cn-font-split (CNFS) is a mature tool for font partitioning. Unlike OptIFT, which relies on page-wise character usage, CNFS partitions fonts based on the font file alone, making it suitable for both static and dynamic sites. You can find more information about CNFS on its GitHub repository.
While CNFS is easier to use and supports more OpenType features, OptIFT can achieve better results for static sites by leveraging more specific information.
Incremental Font Transfer (IFT) is a proposed W3C standard designed to allow browsers to incrementally download only the portions of a font that are needed for rendering specific content. This approach would significantly improve font loading performance, particularly for large CJK fonts.
However, IFT is still in the proposal stage and has not yet been implemented in browsers. While it holds promise as the ideal future solution for web font optimization, it remains speculative until officially adopted and supported.
For now, OptIFT offers a practical and efficient alternative for static sites.
OptIFT is written in modern C++ and uses CMake + Vcpkg for dependency management. Follow the steps in Quick Start to build it on your platform.
OptIFT is built in C++ primarily because Harfbuzz, the font subsetting library, has a mature C API that integrates more naturally with C++ than with Rust. While Rust is an attractive option, working directly with Harfbuzz in Rust involves additional overhead due to the need for FFI bindings. Once Google Fonts completes a Rust rewrite of a subsetter with features comparable to hb-subset
, a full Rust rewrite of OptIFT may be considered.
OptIFT should only be used with fonts that permit subsetting or partitioning in their licenses. Common licenses that allow this include:
Always check the font’s license before using OptIFT to avoid potential legal issues.
Contributions are welcome! Feel free to open issues or submit pull requests.
I would like to thank Mingyang Deng (website) for proposing a heuristic approach to font partitioning, which served as the foundation for OptIFT's partitioning strategy.
OptIFT is licensed under the MIT License. See LICENSE for more details.