I am writing a react component library with typescript, sass and rollup, and I want it to be as standalone as possible.
Does anyone have a suggestion on how to best include assets (images and fonts) referenced in scss files?
One solution could be some sort of loader (for instance a postcss processor) replacing all image and font assets referenced in scss files with the base64 version.
Does anyone have an example where this has been done in an effective manner? Any solutions or suggestions would be highly appreciated
My rollup config looks like this:
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import resolve from "rollup-plugin-node-resolve";
import typescript from "rollup-plugin-typescript2";
import scss from 'rollup-plugin-scss'
import sass from "rollup-plugin-sass";
import commonjs from "rollup-plugin-commonjs";
import copy from "rollup-plugin-copy";
import url from '@rollup/plugin-url';
import packageJson from "./package.json";
export default {
input: "src/index.tsx",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true
},
{
file: packageJson.module,
format: "esm",
sourcemap: true
}
],
plugins: [
peerDepsExternal(),
resolve({
browser: true
}),
typescript({ objectHashIgnoreUnknownHack: true }),
commonjs({
include: ["node_modules/**"],
exclude: ["**/*.stories.js"],
namedExports: {
"node_modules/react/react.js": [
"Children",
"Component",
"PropTypes",
"createElement"
],
"node_modules/react-dom/index.js": ["render"]
}
}),
scss({
}),
sass({
insert: true
}),
copy({
targets: [
{
src: "src/variables.scss",
dest: "build",
rename: "variables.scss"
},
{
src: "src/typography.scss",
dest: "build",
rename: "typography.scss"
},
{
src: "src/assets",
dest: "build/",
},
]
})
]
};
UPDATE:
So what I did might be hacky, but it solved my problem.
I added a postcss-plugin in the plugins array in rollup.config.js, after a commonjs plugin.
postcss({
inject: true,
plugins: [
postcssInlineBase64({
baseDir: 'src/assets/',
}),
postcssUrl({
url: 'inline',
}),
atImport({
path: path.resolve(__dirname, '../'),
}),
],
}),
I also use storybook, which internally uses webpack, so I had to recreate the same in .storybook/webpack.config.js:
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
inject: true,
ident: 'postcss',
plugins: [
postcssInlineBase64({
baseDir: 'src/assets/',
}),
postCssUrl({ url: 'inline' }),
atImport({
path: path.resolve(__dirname, '../'),
}),
],
},
},
'sass-loader',
],
include: path.resolve(__dirname, '../'),
});
Now, when using the url directive in scss (or elsewhere probably), I can surroud any path with:
b64---<SOME_PATH>---
For instance:
@font-face {
font-family: 'Open Sans';
font-display: swap;
font-style: normal;
font-weight: 300;
src: url('b64---./fonts/open-sans/open-sans-v15-latin-ext_latin-300.woff2---') format('woff2'),
url('b64---./fonts/open-sans/open-sans-v15-latin-ext_latin-300.woff---') format('woff');
}
which makes post css bundle the asset as base64.
To anyone who might come across this post. Good luck! Hope this helps!