Add Background image in SCSS with rollup bundle? - sass

I can't able to use image path in scss file as background with rollup bundle.
My rollup config looks like this.
import typescript from 'rollup-plugin-typescript2';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import resolve from 'rollup-plugin-node-resolve';
import scss from 'rollup-plugin-scss';
import image from 'rollup-plugin-img'; // module solves image add in source
import pkg from './package.json';
export default {
input: 'src/index.tsx',
output: [
{
file: pkg.main,
format: 'cjs',
exports: 'named',
sourcemap: true,
},
{
file: pkg.module,
format: 'es',
exports: 'named',
sourcemap: true,
},
],
plugins: [
image({
extensions: /\.(png|jpg|jpeg|gif|svg)$/,
limit: 10000
}),
scss(),
external(),
resolve({
broswer: true
}),
typescript({
rollupCommonJSResolveHack: true,
exclude: '**/__tests__/**',
clean: true,
}),
commonjs({
include: ['node_modules/**'],
namedExports: {
'node_modules/react/react.js': ['Children', 'Component', 'PropTypes', 'createElement'],
'node_modules/react-dom/index.js': ['render'],
},
})
],
};
I am trying to add an image path in scss.
.chipsComponent > div:last-child {
background: url("/assets/images/Close_Circle.svg") no-repeat;
background-size: cover;
height: 16px;
width: 16px;
float: right;
cursor: pointer;
}
image path is adding in browser but rollup is not serving asset folder.Attached screesnhot
The image should show in circled chips(red).
Have I missed anything in rollup config or scss image usage is wrong?
Thanks in Advance

The scss line below is not actually importing the image:
background: url("/assets/images/Close_Circle.svg") no-repeat;
The rollup plugin rollup-plugin-img relies on resources being used via import declarations, like in a js file:
import logo from './rollup.png';
You have two options:
Write your own SCSS processor plugin that resolves url(...) references to copy over assets into your bundle directory.
Use a more manual rollup plugin like rollup-plugin-copy.
With rollup-plugin-copy you can use the following code in your rollup config:
plugins: [
copy({
targets: [
{ src: 'src/assets/images', dest: 'dist/assets/images' },
],
}),
This will copy over all of your images from your source folder to your bundle output.

Related

postcss-url not generating base64 url

I am building a library which is used as a package in a Next.js app.
I have a variable in my .scss file which uses an url('./some-file.png') and I want this to generate a base64 url in order to be used in my other app easily.
When I build the project, after adding postcss-url, the generated url has not changed...there is no base64 url generated.
rollup.config.js:
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import resolve from '#rollup/plugin-node-resolve'
import commonjs from '#rollup/plugin-commonjs'
import typescript from '#rollup/plugin-typescript'
import postcss from 'rollup-plugin-postcss'
import copy from 'rollup-plugin-copy'
import svgr from '#svgr/rollup'
import dts from 'rollup-plugin-dts'
import del from 'rollup-plugin-delete'
import analyze from 'rollup-plugin-analyzer'
import { terser } from 'rollup-plugin-terser'
import json from '#rollup/plugin-json'
import graphql from '#rollup/plugin-graphql'
import fs from 'fs'
import url from 'postcss-url'
import path from 'path'
import * as packageJson from './package.json'
const tsConfig = JSON.parse(fs.readFileSync(__dirname + '/tsconfig.json', 'utf8'))
export default [
{
input: 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true
}
],
plugins: [
peerDepsExternal(),
copy({
targets: [
{
src: [
'src/ui/styles/palette.scss',
'src/ui/styles/themes.scss',
'src/ui/styles/urls.scss',
'src/ui/styles/_exports.module.scss'
],
dest: 'lib/scss'
},
{ src: 'src/assets/images', dest: 'lib/assets' }
],
verbose: true
}),
svgr({ dimensions: false }),
resolve({ preferBuiltins: true, mainFields: ['browser'] }),
postcss({
plugins: [
url({
url: "inline"
}),
],
extract: path.resolve('lib/styles.scss'),
}),
commonjs(),
json(),
typescript({ tsconfig: './tsconfig.json' }),
graphql(),
terser(),
analyze({ summaryOnly: true })
]
},
{
input: 'lib/types/src/index.d.ts',
output: [{ file: 'lib/index.d.ts', format: 'esm' }],
external: [/\.scss$/],
plugins: [
dts({
compilerOptions: {
baseUrl: '.',
paths: tsConfig.compilerOptions.paths
}
}),
del({ hook: 'buildEnd', targets: './lib/types' })
]
}
]
button.scss
#import '../../styles/themes.scss';
.background-color-header {
background: themed('header-background');
}
themes.scss
#import './urls.scss';
header-background: url($light-url) no-repeat #{','} $gradient-light-background-header,
and finally : urls.scss
$light-url: '/assets/images/my-image.png';
styles.scss which is the result of the build:
.background-color-header {
background: url("/assets/images/my-image.png") no-repeat , transparent linear-gradient(180deg, #faf8f4 0%, white 100%) 0% 0% no-repeat padding-box;
}
So, you can see that the url is not base64 ...
Any advice?

Disable asset handling in Vite

I have a PHP project (WordPress theme) with Vite and PostCSS to bundle my JS and CSS files.
The output directory is build and everything worked, but as soon as I import fonts or images in my CSS, Vite copies them into the build folder and changes the paths in the source.
File structure:
styles
|- tailwind.css
|- fonts
|- fa-brands-400.eot
|- fa-brands-400.woff
|- fa-brands-400.woff2
|- fa-brands-400.svg
|- fa-brands-400.ttf
js
|- index.js
vite.config.js
...
In my tailwind.css, I'm importing the font:
#font-face{
font-family:"Font Awesome 5 Brands";
font-style:normal;
font-weight:400;
font-display:block;
src:url(../styles/fonts/font_awesome/fa-brands-400.eot);
src:url(../styles/fonts/font_awesome/fa-brands-400.eot?#iefix) format("embedded-opentype"),url( ../styles/fonts/font_awesome/fa-brands-400.woff2) format("woff2"),url(../styles/fonts/font_awesome/fa-brands-400.woff) format("woff"),url(../styles/fonts/font_awesome/fa-brands-400.ttf) format("truetype"),url(../styles/fonts/font_awesome/fa-brands-400 .svg#fontawesome) format("svg")
}
The problem, Vite copied the imported font files to my build folder and my font import now looks like this (in build/tailwind.css:
#font-face{
font-family:"Font Awesome 5 Brands";
font-style:normal;
font-weight:400;
font-display:block;
src:url(/fa-brands-400.eot);
src:url(/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(/fa-brands-400.woff2) format("woff2"),url(/fa-brands-400.woff) format("woff"),url(/fa-brands-400.ttf) format("truetype"),url(/fa-brands-400.svg#fontawesome) format("svg")
}
Is there a way to disable this? I just want Vite to bundle my JS and CSS, but don't include my assets.
My vite.config.js looks like this:
import postcssImport from "postcss-import"
import tailwindcssNesting from "tailwindcss/nesting"
import tailwindcss from "tailwindcss"
import autoprefixer from "autoprefixer"
import postcssScss from "postcss-scss"
import { defineConfig } from "vite"
export default defineConfig({
build: {
outDir: "build",
cssCodeSplit: true,
emptyOutDir: true,
minify: false,
assetsDir: "",
rollupOptions: {
input: {
index: "js/index.js",
tailwind: "styles/tailwind.css",
},
output: {
entryFileNames: "[name].js",
assetFileNames: "[name].[ext]",
},
},
},
css: {
postcss: {
syntax: postcssScss,
plugins: [postcssImport, tailwindcssNesting, tailwindcss, autoprefixer],
},
},
clearScreen: true,
publicDir: false,
})
I am facing a similar issue with a library build. I want to have an image relative to my css file, but default it is placed at the root and the reference in the css file is also to the root (just like in your problem). I did not find a perfect solution, but I was able to place the image in the same folder as the css file, where the css file also references the image in the same folder. I used the rollup config option output.assetFileNames for this. You can pass your own function and in that function you can add the complete path to the folder where you want to add the asset.
assetFileNames: (assetInfo: PreRenderedAsset): string => {
if (assetInfo.type === 'asset') {
return 'styles/fonts/[name][extname]';
}
else {
return '[name][extname]';
}
},
This will place the fonts in the build/styles/font folder. The references in the css will also be in this folder.
There is one caveat: The references will begin with '/', so they will be from the root of the domain. I have not found a solution for this.

rollup postcss plugin doesn't seem to work with scss and CSS Modules

The symptom
When are run rollup -c I get a reasonable build, but I get this error if I use the SCSS double slash comments:
CssSyntaxError: //../packages/core/src/styles/layout.module.scss:56:8: Unknown word
You tried to parse SCSS with the standard CSS parser; try again with the postcss-scss parser
As far as I can tell, I have setup the plugin to use sass and to use CSS Modules. When I try to set the parser to "postcss-scss" I get this other error:
[!] (plugin postcss) TypeError: node.getIterator is not a function
rollup.config.js
import url from "#rollup/plugin-url";
import svgr from "#svgr/rollup";
import autoprefixer from "autoprefixer";
import { resolve } from "path";
import postcssNormalize from "postcss-normalize";
import babel from "rollup-plugin-babel";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
import { nodeResolve } from "#rollup/plugin-node-resolve";
import commonjs from "#rollup/plugin-commonjs";
import typescript from "#rollup/plugin-typescript";
import packageJson from "./package.json";
export default [
{
input: "src/components/index.ts",
output: [
{
file: `${packageJson.main}`,
format: "cjs",
sourcemap: true,
},
{
file: `${packageJson.module}`,
format: "esm",
sourcemap: true,
},
],
plugins: [
// include peer deps in the package
peerDepsExternal(),
// The next 2 allow importing commonjs packages like classnames
commonjs(),
nodeResolve(),
// transform
babel({
exclude: "node_modules/**",
}),
typescript({
typescript: require("typescript"),
tsconfig: "./tsconfig-prod.json",
}),
postcss({
plugins: [autoprefixer(), postcssNormalize()],
// exclude: "src/styles/**/*.scss",
namedExports: true,
sourceMap: true,
extract: false,
// modules: true,
autoModules: true,
minimize: true,
extensions: [".scss"],
use: ["sass"],
// parser: "postcss-scss",
}),
url(),
svgr(),
],
},
};
There are a couple of commented out options, which I have also tried. Yes, I can switch comment type - the sheer number of files notwithstanding, but it bothers me that this setup is not quite working, so any help would be much appreciated.
In the src/components folders I have this folder strcuture pattern for each component:
components ->
> Button ->
> index.ts
> Button.tsx
> Button.module.scss

laravel-mix / webpack, ignore sass loaded file (font) to be exported

I am trying to skip a dependency loaded font (with url() ) to be exported.
I used ignore-loader module.
mix.webpackConfig({
module: {
rules: [
{
test: /context-menu-icons\.(eot|ttf|otf|woff|woff2)$/,
loader: 'ignore-loader'
}
]
}
});
The issue is it produce empty files. The behavior I am expecting is to not output these files at all.
The reason for this is this in a dependency in node_modules
#font-face {
font-family: '#{$context-menu-icon-font-name}';
src: url('#{$context-menu-icon-font-path}#{$context-menu-icon-font-name}.eot?#{$context-menu-icons-cachebust}');
src: url('#{$context-menu-icon-font-path}#{$context-menu-icon-font-name}.eot?#{$context-menu-icons-cachebust}#iefix') format('embedded-opentype'),
url('#{$context-menu-icon-font-path}#{$context-menu-icon-font-name}.woff2?#{$context-menu-icons-cachebust}') format('woff2'),
url('#{$context-menu-icon-font-path}#{$context-menu-icon-font-name}.woff?#{$context-menu-icons-cachebust}') format('woff'),
url('#{$context-menu-icon-font-path}#{$context-menu-icon-font-name}.ttf?#{$context-menu-icons-cachebust}') format('truetype');
font-weight: normal;
font-style: normal;
}
Is there a way to just ignore these files from output / copy in my dist folder ?
I could not find a solution because, font-face is loaded from a scss file.
So using options with file-loader to prevent emitting files won't work.
There would be a string in these file with module.exports = ...
In all cases the font files would be emmited empty or not.
So I used clean-webpack-plugin with these options
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
...
mix.webpackConfig({
plugins: [
new CleanWebpackPlugin({
// dry: true,
verbose: true,
// Automatically remove all unused webpack assets on rebuild
cleanStaleWebpackAssets: false,
// Do not allow removal of current webpack assets
protectWebpackAssets: false,
cleanOnceBeforeBuildPatterns: [
'**/*', // clean all
'!views','!views/**/*', // ignore views folder
'!lang','!lang/**/*', // ignore lang folder
],
cleanAfterEveryBuildPatterns: [
'fonts/vendor' // remove fonts/vendor folder after build and watch
],
}),
]
});
...

Grunt sass #import not making css

I'm trying to use sass with grunt and I'm having a weird behavior.
If I create any file with underscore it doesn't work anymore, and it doesn't import either.
That is my Gruntfile, really simple:
module.exports = function(grunt) {
'use strict';
require('load-grunt-tasks')(grunt);
grunt.initConfig({
watch: {
sass: {
files: 'scss/**/*.{scss,sass}',
tasks: ['sass']
}
},
sass: {
example: {
options: {
outputStyle: 'expanded'
},
files: {
'public/css/app.css': 'scss/**/*.{scss,sass}'
}
}
}
});
grunt.registerTask('default', ['watch']);
};
If I create a file, for example, application.scss in scss/, it works and creates the file app.css in public/css, but if I create any file with underscore, for instance: _variables in scss/ it doesn't work anymore, it doesn't create the file or changes anything and it doesn't import either.
application.scss:
#import "variables";
body {
background-color: $bg-color;
}
_variables.scss:
$bg-color: red;
Files with names starting with an underscore are considered as partial in the eyes of SASS. This means that SASS would not make an actual css file out of them. To prevent this, either create an index.scss file and import your partials in it or remove the underscore from their names.
Official DOcs
I solved it by using:
files: [{
expand: true,
cwd: 'scss',
src: '**/*.{scss,sass}',
dest: 'public/css',
ext: '.css'
}]

Resources