如何通过Rollup修改字体路径以适配打包后的目录结构?
Rollup字体资源路径解析问题
项目目录结构
src - |_...other dirs.. |_styles |_fonts |_notosans.scss (字体导入位置) |_woff |_....my font assets..
SCSS中的字体引用
@font-face { font-family: 'NotoSansKR'; font-weight: 900; font-display: swap; src: local('NotoSansKR Black'), url('./woff/NotoSansKR-Black.woff') format('woff'); }
当前Rollup配置
import commonjs from '@rollup/plugin-commonjs'; import typescript from '@rollup/plugin-typescript'; import dts from 'rollup-plugin-dts'; import json from '@rollup/plugin-json'; import postcss from 'rollup-plugin-postcss'; import copy from 'rollup-plugin-copy'; import peerDepsExternal from 'rollup-plugin-peer-deps-external'; import alias from '@rollup/plugin-alias' import pkg from './package.json'; export default [ { input : "src/index.ts", output: [ { file: pkg.main, format: 'cjs', sourcemap: true }, { file: pkg.module, format: 'esm', sourcemap: true } ], plugins: [ peerDepsExternal(['react', 'react-dom', 'styled-components' ,'lottie-web']), commonjs({ include: ['./src/index.ts', 'node_modules/**'] }), typescript({ tsconfig: './tsconfig.json' }), alias({ entries: [ { find : '@assets', replacement: './src/assets' } ] }), json(), copy({ targets: [ // 复制字体资源到目标目录 { src: "src/styles/fonts/woff", dest: "dist/assets" }, ], }), postcss(), ] }, { input: "dist/esm/types/index.d.ts", output: [{file : "dist/index.d.ts" , format: "esm"}], plugins: [dts()], external : [/\.(scss|css)$/] } ]
期望的dist结构
dist |_assets - woff - my fonts.. |_cjs |_esm ...
问题
字体资源已成功复制到dist/assets/woff,但SCSS编译后的字体引用路径未自动更新,导致路径错误。需要通过Rollup配置解决,不使用CDN或link标签方案。
解决方案
核心是通过配置rollup-plugin-postcss的路径重写能力,自动调整字体引用路径以匹配打包后的目录结构。
步骤1:安装postcss-url插件
该插件用于处理CSS中的资源路径转换:
npm install postcss-url --save-dev
步骤2:修改Rollup中的postcss配置
更新rollup-plugin-postcss的配置,添加postcss-url并设置路径转换规则:
// 导入postcss-url import postcssUrl from 'postcss-url'; // 在plugins数组中修改postcss配置 postcss({ plugins: [ postcssUrl({ url: (asset) => { // 匹配字体文件路径并转换 if (asset.url.includes('./woff/')) { // 转换为相对于打包后文件的路径:../assets/woff/[字体文件名] // 适配cjs/esm目录到assets目录的层级关系 return `../assets/woff/${asset.url.split('./woff/')[1]}`; } return asset.url; } }) ], // 可选:若需将CSS提取为单独文件,打开下方注释 // extract: true, }),
完整修改后的Rollup配置片段
// ...其他导入 import postcssUrl from 'postcss-url'; export default [ { input : "src/index.ts", output: [ { file: pkg.main, format: 'cjs', sourcemap: true }, { file: pkg.module, format: 'esm', sourcemap: true } ], plugins: [ peerDepsExternal(['react', 'react-dom', 'styled-components' ,'lottie-web']), commonjs({ include: ['./src/index.ts', 'node_modules/**'] }), typescript({ tsconfig: './tsconfig.json' }), alias({ entries: [ { find : '@assets', replacement: './src/assets' } ] }), json(), copy({ targets: [ { src: "src/styles/fonts/woff", dest: "dist/assets" }, ], }), postcss({ plugins: [ postcssUrl({ url: (asset) => { if (asset.url.includes('./woff/')) { return `../assets/woff/${asset.url.split('./woff/')[1]}`; } return asset.url; } }) ], // 若项目需提取独立CSS文件,打开此注释 // extract: true, }), ] }, // ...dts配置部分保持不变 ]
原理说明
postcss-url会遍历CSS中所有url()引用,将原路径./woff/xxx.woff转换为../assets/woff/xxx.woff,该路径相对于打包后cjs/esm目录下的样式文件(或注入到JS中的样式字符串),可正确指向dist/assets/woff中的字体资源。
内容的提问来源于stack exchange,提问作者Justin Seo
相关产品推荐
相关产品推荐

