Pass options to the builtin svgo from svgr/webpack - svg

Is there an option to pass in svgo options to the svgr/webpack loader ? I want to remove the width & height attributes and keep the viewbox, by default it removes those.
{
test: /\.svg$/,
use: ['#svgr/webpack'],
options : {
svgo: { // Something like this ?
mergePaths: false,
removeViewbox: false,
removeAttrs: true,
}}
},

In my case I got errors that:
plugins should be an array;
Each plugin object requires a name property
So here is what worked for me:
use: {
loader: '#svgr/webpack',
options: {
svgoConfig: {
plugins: [
{
name: 'removeViewBox',
active: false
}
]
}
}
}

https://react-svgr.com/docs/options/
the answer is as the follow...
{
loader: "#svgr/webpack",
options: {
dimensions: false
}
},

It has a little confusing syntax with nested parameters. Here is what I'm using to disable prefixing ids and classnames. I suppose, in your case it will be something like mergePaths.active = false, removeViewbox.active = false.
loader: '#svgr/webpack',
options: {
svgoConfig: {
plugins: [{
prefixIds: {
prefixIds: false,
prefixClassNames: false
}
}]
}
}
I did not test, but I suppose it would look like this (or similar, you might play with it a bit to get the syntax right):
loader: '#svgr/webpack',
options: {
svgoConfig: {
plugins: [{
removePaths: {
active: false,
}
},{
removeViewbox: {
active: false,
}
},{
removeAttrs: {
active: true,
}
}]
}
}
Look into the code here, where you can figure out what props are actually being exported: https://github.com/svg/svgo

I could not find a way of passing arguments through svgr to svgo so I switched to react-svg-loader which has documentation on how to achieve that :
{
test: /\.svg$/,
use: [
'babel-loader',
{
loader: 'react-svg-loader',
options: {
svgo: {
plugins: [{ removeDimensions: true, removeViewBox: false }],
floatPrecision: 2,
},
},
},
],
},

It works as described here or here:
{
test: /\.svg$/,
use: [{
loader: '#svgr/webpack',
options: {
svgoConfig: {
plugins: [
{ mergePaths: false },
{ removeViewbox: false },
{ removeAttrs: true },
],
},
},
}],
}

Related

Storybook does not load SVGs in Components of Vue 3 project

I got the following error when running npm run storybook using vue 3.
me main.js storybook
const path = require('path');
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/addon-interactions",
],
"framework": "#storybook/vue3",
"core": {
"builder": "#storybook/builder-webpack5"
},
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
(() => {
const ruleSVG = config.module.rules.find(rule => {
if (rule.test) {
const test = rule.test.toString();
const regular = '/\.(svg|ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/';
const regularString = regular.toString();
if (test === regularString) {
return rule;
}
}
});
ruleSVG.test = '/\.(ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/'
})();
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: "sass-loader",
options: {
additionalData: `
#import "#/assets/scss/main.scss";
`,
implementation: require('sass'),
},
},
],
include: path.resolve(__dirname, '../'),
});
config.module.rules.push({
test: /\.(svg)(\?.*)?$/,
use: "babel-loader",
enforce: "pre",
oneOf: [
{
resourceQuery: /inline/,
use: [
{
loader: "vue-svg-loader",
options: {
svgo: {
plugins: [
{ removeDoctype: true },
{ removeComments: true },
{ removeDimensions: true },
{ cleanupIDs: false },
{ removeViewBox: false }
]
}
}
}
]
},
{
loader: "file-loader",
options: {
name: "#/assets/icons/[name].[hash:8].[ext]"
}
}
],
exclude: /(node_modules)/
});
config.resolve.alias['#'] = path.resolve('src');
return config;
},
}
me package.json
I tried to connect #babel-preset-react and #babel-preset-env but it did not lead to success.
When I change vue-svg-loader to svg-inline-loader and change main.js a little, I get this:
enter image description here
Does anyone have any ideas how this can be fixed?

Babel config to SWC

Now I have such babel config on the project and I really want to rewrite this case under swc. Would anyone be able to help with this
module.exports = {
sourceMaps: true,
presets: [
[
'#babel/preset-env',
{
exclude: ['transform-async-to-generator', 'transform-regenerator'],
},
],
'#babel/preset-react',
[
'#babel/preset-typescript',
{
isTSX: true,
allExtensions: true,
},
],
],
plugins: [
'#babel/plugin-syntax-dynamic-import',
['#babel/plugin-proposal-decorators', { legacy: true }],
['#babel/plugin-proposal-class-properties', { loose: true }],
['module:fast-async', { spec: true }],
[
'#babel/plugin-transform-regenerator',
{
asyncGenerators: true,
generators: true,
async: false,
},
],
],
};
Now I have written such a config, but part of the application has stopped working with similar errors: [MobX] Cannot decorate undefined property: 'description'
test: /\.(tsx|ts|jsx|js)$/,
loader: 'swc-loader',
options: {
jsc: {
keepClassNames: true,
parser: {
syntax: 'typescript',
decorators: true,
tsx: true,
dynamicImport: true,
preserveAllComments: false
},
transform: {
legacyDecorator: true,
decoratorMetadata: true
},
loose: false
},
},

How to disable removeViewBox plugin in Next.Js and svgr?

I would like to disable the removeViewBox plugin in Next.js/svgr/svgo. The following next.config.js should work but it does not.
Anybody can help ?
I'm using it with:
"#svgr/webpack": "^6.2.0", "react": "17.0.2", "next": "^12.0.7",
module.exports = {
reactStrictMode: true,
i18n,
webpack(config) {
config.module.rules.push(
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: [
{
loader: '#svgr/webpack',
options: {
prettier: false,
svgo: true,
icon: true,
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
],
},
titleProp: true,
},
},
],
})
return config
},
}
For #svgr/webpack#5.5.0 it worked when I added { removeViewBox: false } right to plugins array:
{
loader: '#svgr/webpack',
options: {
svgoConfig: {
plugins: [
{ removeViewBox: false },
],
},
},
},
This is what's worked for my with next#13.0.5 and #svgr/webpack#6.5.1
config.module.rules.push({
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: [{ loader: '#svgr/webpack', options: { icon: true } }]
});

Module not found: Error: Can't resolve in webpack.common.js

when I do npm run build I am getting below error
ERROR in ./src/assets/scss/theme.scss
(./node_modules/css-loader/dist/cjs.js!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js!./src/assets/scss/theme.scss)
Module not found: Error: Can't resolve
'../../../../fonts/materialdesignicons-webfont.woff?v=4.4.95' in
'D:\Work\BBYN\external\src\assets\scss' #
./src/assets/scss/theme.scss
(./node_modules/css-loader/dist/cjs.js!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js!./src/assets/scss/theme.scss)
7:36-106 # ./src/assets/scss/theme.scss #
./src/extensions/masterApplicationCustomizer/MasterApplicationCustomizerApplicationCustomizer.ts
but If I run npm run watch it works properly
My webpack.commom.js is as below
const path = require('path')
const merge = require('webpack-merge')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const SetPublicPathPlugin = require('#rushstack/set-webpack-public-path-plugin').SetPublicPathPlugin
module.exports = merge({
target: 'web',
entry: {
'profile-web-part': path.join(__dirname, '../src/webparts/profile/ProfileWebPart.ts'),
'master-application-customizer-application-customizer': path.join(
__dirname,
'../src/extensions/masterApplicationCustomizer/MasterApplicationCustomizerApplicationCustomizer.ts'
),
'list-data-web-part': path.join(__dirname, '../src/webparts/listData/ListDataWebPart.ts')
},
output: {
path: path.join(__dirname, '../dist'),
filename: '[name].js',
libraryTarget: 'umd',
library: '[name]'
},
performance: {
hints: false
},
stats: {
errors: true,
colors: true,
chunks: false,
modules: false,
assets: false
},
externals: [/^#microsoft\//, 'ProfileWebPartStrings', 'ControlStrings', 'MasterApplicationCustomizerApplicationCustomizerStrings', 'ListDataWebPartStrings'],
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
transpileOnly: true
},
exclude: /node_modules/
},
{
test: /\.(jpg|png|woff|woff2|eot|ttf|svg|gif|dds)$/,
use: [
{
loader: '#microsoft/loader-cased-file',
options: {
name: '[name:lower]_[hash].[ext]'
}
}
]
},
{
test: /\.css$/,
use: [
{
loader: '#microsoft/loader-load-themed-styles',
options: {
async: true
}
},
{
loader: 'css-loader'
}
]
},
{
test: function (fileName) {
return fileName.endsWith('.module.scss') // scss modules support
},
use: [
{
loader: '#microsoft/loader-load-themed-styles',
options: {
async: true
}
},
'css-modules-typescript-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}, // translates CSS into CommonJS
'sass-loader' // compiles Sass to CSS, using Node Sass by default
]
},
{
test: function (fileName) {
return !fileName.endsWith('.module.scss') && fileName.endsWith('.scss') // just regular .scss
},
use: [
{
loader: '#microsoft/loader-load-themed-styles',
options: {
async: true
}
},
'css-loader', // translates CSS into CommonJS
{
loader: 'resolve-url-loader'
},
'sass-loader' // compiles Sass to CSS, using Node Sass by default
]
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
plugins: [
new ForkTsCheckerWebpackPlugin({
tslint: true
}),
new SetPublicPathPlugin({
scriptName: {
name: '[name]_?[a-zA-Z0-9-_]*.js',
isTokenized: true
}
})
]
})
I could solve the issue by using resolve-url-loader module. It can help to somebody Below is part of webpack.js
{
test: function (fileName) {
return !fileName.endsWith('.module.scss') && fileName.endsWith('.scss') // just regular .scss
},
use: [
{
loader: '#microsoft/loader-load-themed-styles',
options: {
async: true
}
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
}, // translates CSS into CommonJS
'resolve-url-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true
}
} // compiles Sass to CSS, using Node Sass by default
]
}
]

Sass relative import with webpack

I'm trying to import the SCSS files relative to the component in the same folder but ex:
import './ngg.scss';
The strange thing is when I change the path of this SCSS file or using dev server it's working fine but when I run it for the production it doesn't work as if the SCSS file doesn't exist, I'm using web-pack 4, I can't see the issue really because there are some components use relative import and it's working fine, please help!!
module.exports = function makeWebpackConfig(options) {
var BUILD = options.environment === 'prod';
var DEV_SERVER = process.env.WEBPACK_MODE === 'watch';
var config = {
mode: BUILD ? 'production' : 'development',
optimization: {
chunkIds: 'named',
moduleIds: 'hashed',
namedModules: true,
noEmitOnErrors: true,
usedExports: true,
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
desktop: {
test: /Resources\/desktop\/assets\/js/,
name: 'common-desktop',
chunks: 'initial',
minChunks: 5
},
mobile: {
test: /Resources\/mobile\/assets\/js/,
name: 'common-mobile',
chunks: 'initial',
minChunks: 5
}
}
},
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true
})
]
},
entry: options.entry,
resolve: {
alias: options.alias,
extensions: ['.js', '.jsx'],
modules: ['node_modules']
},
output: {
path: options.parameters.path ? options.parameters.path : __dirname + '/../../web/compiled/',
publicPath: publicPath,
filename: BUILD ? '[name].[contenthash].js' : '[name].[hash].js',
chunkFilename: BUILD ? '[name].[contenthash].js' : '[name].[hash].js'
},
devServer: {
disableHostCheck: true,
overlay: {
warnings: true,
errors: true
},
headers: {
'Access-Control-Allow-Origin': '*'
}
}
};
config.module = {
rules: [
{
test: /\.jsx?$/i,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
minified: !DEV_SERVER,
cacheDirectory: DEV_SERVER,
presets: ['es2015', 'react']
}
},
{
test: /\.(gif|png|jpe?g)(\?.*)?$/i,
enforce: 'pre',
loader: 'image-webpack-loader',
options: options.parameters.image_loader_options || !DEV_SERVER ? {
optipng: {
optimizationLevel: 7,
progressive: true
}
} : {
disable: true
}
},
{
test: /\.(png|jpg|jpeg|gif|svg)(\?.*)?$/i,
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]'
}
},
{
test: /\.(eot|ttf|woff|woff2)$/,
loader: 'url-loader',
},
{
test: /\.html$/i,
loader: 'raw-loader'
},
{
test: /\.(css|scss)$/i,
use: [
DEV_SERVER ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
minimize: false,
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: function () {
return [
autoprefixer({
browsers: ['last 2 version']
})
];
}
}
},
]
},
{
test: /\.scss$/i,
loader: 'sass-loader?sourceMap',
options: {
enforce: 'pre'
}
}
]
};
config.plugins = [
new MiniCssExtractPlugin({
filename: BUILD ? '[name].[id].[chunkhash].css' : '[name].[hash].css'
}),
new PostCssPipelineWebpackPlugin({
suffix: 'critical',
processor: postcss([
criticalSplit({
output: criticalSplit.output_types.CRITICAL_CSS
})
])
}),
new PostCssPipelineWebpackPlugin({
suffix: 'rest',
processor: postcss([
criticalSplit({
output: criticalSplit.output_types.REST_CSS
})
])
}),
new PostCssPipelineWebpackPlugin({
suffix: 'min',
processor: postcss([
csso({
restructure: false,
comments: false
})
]),
map: {
inline: false
}
}),
new AssetsPlugin({
filename: path.basename(options.manifest_path),
path: path.dirname(options.manifest_path)
}),
new webpack.ProvidePlugin({
React: "react",
ReactDOM: "react-dom",
$: "jquery",
jQuery: "jquery"
})
];
if (BUILD) {
config.devtool = 'nosources-source-map';
} else {
config.devtool = 'source-map';
}
return config;
};
Below is my webpack config
module: {
rules: [{
test: /\.scss$/,
use: [
'style-loader',
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
minimize: true,
sourceMap: true
}
},
{
loader: "sass-loader"
}
]
}
]
}
Then in my js I only need to import like this
import "css/Client/client.scss";
You can view my full config here

Resources