cn-font-split User Guide
cn-font-split is a crucial component of the Chinese Web Font Project, enabling the deployment of Chinese fonts over the web. It divides the large Chinese font packages into smaller, easily deployable, on-demand loading chunks, creating a highly available web font solution.
cn-font-split boasts exceptional cross-platform capabilities. It can run in Node.js environments, Bun environments, Deno environments, the command line, and even in browser environments, with a unified and simple usage approach!
Since the syntax of JavaScript runtimes is quite similar, the following examples will use the Node.js environment.
Simple Usage in Node.js
- Install cn-font-split
npm i cn-font-split
npm i cn-font-split # or
- Write a JS script
// index.mjs
import fs from 'fs-extra';
import { fontSplit } from '../dist/index.js';
fontSplit({
    // This is the directory for the packaged output
    destFold: '../zh-cn/temp/node',
    // This is the original font package
    FontPath: '../demo/public/SmileySans-Oblique.ttf',
});
- Run the script
node index.mjs
Introduction to Generated Font Artifacts
- result.css
- The entry CSS file that the front-end code can directly reference.
 
- woff2 Font
- The core artifact, a font subpackage optimized by cn-font-split.
 
- index.html
- The test HTML file that is generated by default.
- An early test webpage file that allows you to see the effects of the packaging in detail through a port.
 
- preview.svg
- An image of the test font that is generated by default.
- You can use this image to get a simple idea of what the font looks like.
 
- reporter.json
- The report file from cn-font-split.
- It contains analysis and reference data on woff2.
 
Custom Configuration Properties
Key operations for generating artifacts can be achieved through corresponding configuration properties. Below are some examples based on specific needs.
- Force sub-packaging of certain characters
The default behavior of cn-font-split is to automatically sub-package all characters within the font. However, in special cases, you may want to sub-package only specific characters.
{
    // Disable automatic sub-packaging, so only the characters specified in subsets will be packaged.
    autoChunk: false,
    // Force sub-packaging, which takes precedence over automatic sub-packaging.
    subsets: [
        // This is a single package containing characters with unicode 31105 and 8413.
        [31105, 8413]
    ],
}
Typically, we operate with strings rather than unicode characters, so the following method is more appropriate.
{
    subsets: [
        '中文网字计划'
            .split('')
            .filter(Boolean)
            .map((i) => i.charCodeAt(0))
    ],
}
- Control the generated CSS file
{
    css: {
        // Change the font name referenced in the CSS
        fontFamily: '823746343',
        // FontWeight may not be required in some cases.
        fontWeight: false,
        // Do not declare local characters.
        localFamily: false,
        // Do not generate comments
        comment: false,
        // Uncomment for specific customization
        // comment: {
        //     base: false,
        //     nameTable: false,
        //     unicodes: true
        // }
    },
}
- Change the naming of packaged artifacts
Thanks to richex-cn for their assistance.
{
    renameOutputFont: '[hash:10][ext]', // Automatically truncates the hash length.
    renameOutputFont: '[index][ext]', // Uses an index instead of a hash.
    // Custom naming implementation
    renameOutputFont({ transferred, ext, index }) {
        const algorithm = 'sha256'
        const hash = crypto.createHash(algorithm).update(transferred).digest('hex');
        // return index.toString() + ext // Named by index.
        return hash.slice(0, 6) + ext; // Short hash naming.
    }
}
- Customize the test image for packaging
{
    previewImage: {
        /** Text to display in the image */
        text: 'Excellent Chinese Font',
        /** Filename for the preview image, no extension needed */
        name: 'Example'
    },
    // Do not generate
    // previewImage: false
}