如何用JS生成特定Google Font的全样式有效加载URL?
优化Google Fonts CSS链接生成函数的问题
我正在开发一款图像编辑器,需要在用户选择字体时加载该字体家族的所有可用样式(italic、normal)和字重(如400–800)。目前通过fontsource API获取字体数据,尝试生成Google CSS链接,示例链接如下:
https://fonts.googleapis.com/css2?family=Open%20Sans:ital,wght@0,300..800;1,300..800
但编写的函数有时会生成无效链接,且不确定是否覆盖所有样式/字重。以下是API返回的示例数据:
{ "id": "open-sans", "family": "Open Sans", "subsets": [ "cyrillic", "cyrillic-ext", "greek", "greek-ext", "hebrew", "latin", "latin-ext", "vietnamese" ], "weights": [ 300, 400, 500, 600, 700, 800 ], "styles": [ "italic", "normal" ], "defSubset": "latin", "variable": true, "lastModified": "2022-09-22", "category": "sans-serif", "license": "OFL-1.1", "type": "google" }
我的当前代码如下,请问是否有更优解决方案?谢谢
function generateGoogleFontURL(font) { const formattedFontFamily = font.family.replace(/\s+/g, "+") if (font.weights.length == 0) { return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}`] } if (!font.variable) { if (font.styles.includes("italic")) { return font.weights.map(x => `https://fonts.googleapis.com/css2?family=${formattedFontFamily}:ital,wght@0,${x};1,${x}`) } return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:wght@${font.weights.join(';')}`] } if (font.weights.length > 1) { const minWeight = font.weights[0] const maxWeight = font.weights[font.weights.length - 1] if (font.styles.includes("italic")) { return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:ital,wght@0,${minWeight}..${maxWeight};1,${minWeight}..${maxWeight}`] } else { return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:wght@${minWeight}..${maxWeight}`] } } if (font.styles.includes("italic")) { return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:ital,wght@0,${font.weights[0]};1,${font.weights[0]}`] } return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}:wght@${font.weights[0]}`] }
优化方案
问题分析
原代码存在几个核心问题:
- 第一行
replace方法缺少闭合括号,存在语法错误 - 非可变字体场景下,为每个字重生成单独链接,会触发过多HTTP请求,影响加载性能
- 未处理
weights数组无序的情况,直接取首尾元素可能生成错误的权重范围 - 样式判断逻辑重复,边界场景覆盖不足
优化后的代码
function generateGoogleFontURL(font) { // 安全格式化字体名称,兼容特殊字符 const formattedFontFamily = encodeURIComponent(font.family); // 处理无权重数据的边界情况 if (!font.weights || font.weights.length === 0) { return [`https://fonts.googleapis.com/css2?family=${formattedFontFamily}`]; } // 对权重数组排序,确保范围计算准确 const sortedWeights = [...font.weights].sort((a, b) => a - b); const hasItalic = font.styles?.includes("italic"); const hasNormal = !font.styles || font.styles.includes("normal"); let paramSegments = []; if (font.variable) { // 可变字体使用范围语法 const weightRange = `${sortedWeights[0]}..${sortedWeights.at(-1)}`; if (hasNormal) paramSegments.push(`0,${weightRange}`); if (hasItalic) paramSegments.push(`1,${weightRange}`); } else { // 非可变字体合并权重,减少请求数量 const weightStr = sortedWeights.join(';'); if (hasNormal) paramSegments.push(`0,${weightStr}`); if (hasItalic) paramSegments.push(`1,${weightStr}`); } // 拼接最终URL let baseUrl = `https://fonts.googleapis.com/css2?family=${formattedFontFamily}`; if (paramSegments.length > 0) { baseUrl += `:ital,wght@${paramSegments.join(';')}`; } return [baseUrl]; }
优化点说明
- 用
encodeURIComponent替代简单的空格替换,更安全处理字体名称中的特殊字符(如符号、非英文字符) - 对权重数组排序,避免API返回无序数据导致的范围错误
- 合并非可变字体的样式请求,减少HTTP链接数量,提升加载性能
- 清晰拆分样式判断逻辑,覆盖仅含normal、仅含italic等边界场景
- 修复原代码的语法错误,增加对
styles字段可能不存在的兼容处理
内容的提问来源于stack exchange,提问作者StupidDoofus
相关产品推荐
相关产品推荐

