bundlerrollupbundling-and-minification

How can I modify font path with rollup?


I'm currently configuring rollup for my project.

While dealing with assets,(font : .woff) I'm having issue cause, I can't resolve path correctly when bundling my project.

my project dir looks as below.



src -
    |_...other dirs..
    |_styles
       |_fonts
          |_notosans.scss (!! where font import happens!!)
          |_woff
             |_....my font assets..      
         

/// notosans.scss


@font-face {
  font-family: 'NotoSansKR';
  font-weight: 900;
  font-display: swap;
  src: local('NotoSansKR Black'),
    url('./woff/NotoSansKR-Black.woff') format('woff');
}


so, I configured my rollup as below.


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: [
            // Need to copy the files over for usage
            { 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)$/]
  }
]

what I want is dist folder looks as below

dist
  |_assets - woff - my fonts..
  |_cjs 
  |_esm
  ...

when I build my project, bundled stuff looks as expected what I wanted.

but import path for font(notosans.scss) didn't changed to fit the dist directory structure.

below is code fragment of my build



var css_248z$1 = "@font-face {\n  font-family: \"NotoSansKR\";\n  font-weight: 900;\n  font-display: swap;\n  src: local(\"NotoSansKR Black\"), 

as you can see, path didn't changed.

ofcourse this is because I didn't set anything for this, but I don't know what should I google for this...

btw, there are other solutions for this, such as using CDN , link tag, modifing src path to fit the builds,, but this isn't the thing I want.

By solving this, I think I could acheive better bundling skills.

pls give me any advise or solution, It will help me a lot.


Solution

  • This is what helped me to get this working

    TLDR; you can pass a callback to postcss-url's url parameter. When CSS url() is encountered by postcss-url, this call back will be invoked and it can be used to copy fonts to dist/assets + change the url in compiled css

    const FONT_RX = /\.(woff|woff2|ttf)$/;
    const OUT_DIR = "./dist";
    
    const config = {
     // ...
      plugins: [
        postcss({
          extract: false,
          modules: true,
          plugins: [
            url({
              // Copy fonts to dist/assets + change the url in css
              url: (asset) => {
                if (!FONT_RX.test(asset.url)) {
                  return asset.url;
                }
                const file = fs.readFileSync(asset.absolutePath);
                const fileName = path.basename(asset.absolutePath);
                fs.ensureDirSync(path.join(OUT_DIR, "assets"));
                const filePath = path.join("assets", fileName);
                fs.writeFileSync(path.join(OUT_DIR, filePath), file);
                return filePath;
              },
            })
          ],
        }),
      ],
    };