Use webpack modifyVars to override ant design default.less variables in create-react-app using react app rewired - reactjs

I want to modify ant design default.less variables in my application that has been setup using create-react-app. I did not eject, but used react-app-rewired to modify inject custom webpack configurations. I am able to override most of the variable by following the link. I have the following directory structure:
--App
|--config-overrides.js
|--src
|--styles
|--styles.css
|--(maybe include a .less file to achieve the purpose)
config-overrides.js
const { injectBabelPlugin } = require('react-app-rewired');
const { compose } = require('react-app-rewired');
const rewireLess = require('react-app-rewire-less');
module.exports = function override(config, env) {
config = injectBabelPlugin(
['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }],
config,
);
config = rewireLess.withLoaderOptions({
modifyVars: {
'#ant-prefix' : 'ant',
'#primary-color': '#006778', //works
'#text-color': '#505050', //works
//Not able to inject styles this way.
"#{ant-prefix}-divider-vertical { height: unset; }" //doesn't work
},
javascriptEnabled: true,
})(config, env);
The app won't start with above when I add the last line in modifyVars object. I want to be able to override the antd classes like this.
eg:
.#{ant-prefix}-btn-primary {
&:hover,
&:focus {
background: #primary-color;
color: #fff;
}
}

modifyVars is only used to do exactly that. Modify variables. More specifically the variables in default.less.
You can't use it to inject CSS like that. This you will have to do in your own .css (or .less) file that you import into the app with a normal import command. (Import CSS in a react app)

Related

How to removed unused selectors from prepending external scss files in SvelteKit?

I am using Scss with SvelteKit now, and I am prepending a Scss files to all <style> like this:
const config = {
compilerOptions: {
immutable: true
},
preprocess: preprocess({
scss: {
prependData: `
#use 'src/specific/vars.scss' as *;
`,
includePaths: ["../../node_modules", "../../libs"]
}
})
};
Unlike classes defined directly in <style>, unused classes from that prepended file will not be purged when build automatically. Is it possible to purge it like other classes?

How to use Fluent UI Icons on an intranet

I made a react project using Fluent UI kit.
I have this code:
import { initializeIcons } from '#fluentui/font-icons-mdl2';
initializeIcons(undefined, { disableWarnings: true });
It works fine on my machine, but this project is deployed on an intranet, so icons don't display on user's machines, i noticed that there are requests for icons like this:
https://spoprod-a.akamaihd.net/files/fabric/assets/icons/fabric-icons-1-4d521695.woff
i would like to self-host this icons on my project.
how could i do that?
thanks for your help.
I use this approach trough projects. The main idea is to use CopyWebpackPlugin to copy icons from node_modules/#fluentui/font-icons-mdl2/fonts to specific folder:
const CopyWebpackPlugin = require('copy-webpack-plugin')
...
module.exports = {
...
plugins: [
new CopyWebpackPlugin([{ from: 'node_modules/#fluentui/font-icons-mdl2/fonts', to: 'fabric-font' }]),
]
}
Change icon destination:
import { initializeIcons } from '#fluentui/font-icons-mdl2';
initializeIcons('/fabric-font/', { disableWarnings: true });
This link also might help.

next/image configuration in Next.js config file

I’m implementing the Next.js Image component in my Headless project. The CMS that I’m using is WordPress. And since the image is coming from an external website, I need to specify the domain on next.config.js, as the documentation specifies:
https://nextjs.org/docs/basic-features/image-optimization
const nextConfig = {
image: {
domains: ['https://example.com'],
},
}
But in my next.config.js file I’ve already have this configuration:
const withStyles = require('#webdeb/next-styles');
module.exports = withStyles({
sass: true,
modules: true,
});
So my struggle is to combine this two on the config file.
Just for some context, without the image configuration, I have this error:
Error: Invalid src prop on next/image, hostname is not configured under images in your next.config.js
I've tried putting it together like the code bellow with the use of next-compose-plugins, but the error keeps showing:
const withStyles = require('#webdeb/next-styles');
const withPlugins = require('next-compose-plugins');
const nextConfig = {
image: {
domains: ['https://example.com'],
},
}
module.exports = withPlugins([
[withStyles({
sass: true,
modules: true,
})]
], nextConfig);
Without the nextConfig at the end of the module.exports, the code works without a problem.
A detail on the URL that I need to pass is that it's a subdomain and an homolog environment, but it doesn't need credentials to be accessed. I don't think it's the issue, tho.
Since I'm new with the Next.js, I just can't figure out how this configuration needs to work.
Your config object should be passed to the last plugin call. So in your case it would look like the following:
const withStyles = require('#webdeb/next-styles');
module.exports = withStyles({
sass: true,
modules: true,
images: {
domains: ['https://example.com'],
}
});
Also note that the correct entry for the next/image configuration is images and not image. Which is why it's probably not working when you tried with next-compose-plugins, as everything else seems to be correct in that code snippet.
For anyone whose above methods doesn't work, please remove the https:// or http:// in next.config.js;
module.exports = {
reactStrictMode: true,
images: {
domains: ['https://your-domain.com'], //make it 'your-domain.com'
},
};

Create React App 2 - remove html attribute for testing

Is it possible to connect Create React App 2 with this plugin: https://www.npmjs.com/package/babel-plugin-jsx-remove-data-test-id without ejecting?
I've created .bablerc file, but it doesn't work.
I want to use custom attribute for bdd testing and remove this attribute on production.
Also, I don't want to create HOC to apply attribute - I have many components and wrap every component is very very difficult.
You can use react-app-rewired https://www.npmjs.com/package/react-app-rewired and override the configs through the config-override.js file:
const {
override,
addBabelPresets,
addBabelPlugins,
} = require('customize-cra');
module.exports = override(
...addBabelPresets([
'#babel/preset-env',
{
modules: false,
useBuiltIns: false,
debug: false,
},
]),
...addBabelPlugins(
'babel-plugin-styled-components',
'babel-plugin-jsx-remove-data-test-id',
),
);

ant design - huge imports

I'm using ant design library for my react application.
And I've faced with huge imports, that hurts my bundle (currently 1.1 mb in minified version because of ant-design lib).
How can I differently import antd components through all my app?
UPDATE:
Seems antd has some huge or non optimized modules.
Here the thing - only difference is import Datepicker module, and.. boom! + almost 2MB (in dev bundle ofc.)
UPD: the underlying issue seems to be resolved for the new (4.0) version of antd.
Therefore, if you try to resolve this issue for the earlier versions, the recommended way is to migrate onto antd 4
Previous answer:
At the moment, a huge part of antd dist is SVG icons.
There is no official way to deal with it yet (check the issue on github).
But a workaround exists.
Adapt webpack to resolve icons differently. In your webpack config:
module.exports = {
//...
resolve: {
alias: {
"#ant-design/icons/lib/dist$": path.resolve(__dirname, "./src/icons.js")
}
}
};
Create icons.js in the folder src/ or wherever you want it. Be sure it matches the alias path!
In this file, you define which icons antd should include.
export {
default as DownOutline
} from "#ant-design/icons/lib/outline/DownOutline";
It's also possible to do this with react-app-rewired (create-react-app modifications) within config-overrides.js
1) Prevent antd to load the all moment localization.
Add webpack plugin and configure it in webpack.config.js like the follow:
plugins: [
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /ru/),
],
resolve: {
alias: {moment: `moment/moment.js`}
},
target: `web`
}
2) Use the same moment version as in antd library.
3) Use modularized antd
Use babel-plugin-import
// .babelrc or babel-loader option
{
"plugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
// `style: true` for less
]
}
I use BundleAnalyzerPlugin to analyze the bundle.
plugins: [new BundleAnalyzerPlugin()]
Looking at the docs
https://ant.design/docs/react/getting-started#Import-on-Demand
there is a recommedation to import individual components on demand.
So, you can try and replace
import { Button} from 'antd'
with
import Button from 'antd/lib/button'
I reduced my bundle size by 500KB by editing config-override.js like so:
config-override.js
const { override, fixBabelImports } = require('customize-cra');
const path = require('path');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css'
}),
// used to minimise bundle size by 500KB
function(config, env) {
const alias = config.resolve.alias || {};
alias['#ant-design/icons/lib/dist$'] = path.resolve(__dirname, './src/icons.js');
config.resolve.alias = alias;
return config;
}
);
./src/icons.js
/**
* List all antd icons you want to use in your source code
*/
export {
default as SearchOutline
} from '#ant-design/icons/lib/outline/SearchOutline';
export {
default as CloseOutline
} from '#ant-design/icons/lib/outline/CloseOutline';
export {
default as QuestionCircleOutline
} from '#ant-design/icons/lib/outline/QuestionCircleOutline';
export {
default as PlayCircleOutline
} from '#ant-design/icons/lib/outline/PlayCircleOutline';
export {
default as PauseCircleOutline
} from '#ant-design/icons/lib/outline/PauseCircleOutline';
export {
default as LoadingOutline
} from '#ant-design/icons/lib/outline/LoadingOutline';
Before
After
Those few components are certainly not 1.2M together. Looks like you are importing the whole library when you only need a few components.
To get antd to load only the needed modules you should use babel-plugin-import. Check your console log for the "You are using a whole package of antd" warning described at that link.
Check out the docs for Create-React-App for how to implement it if you're using CRA.
Try using code splitting using webpack and react router. It will help you to load the modules asynchronously. This is the only solution helped me to improve the page load time when using ant framework.
Issue which caused large bundle size has been fixed in Ant Design 4.0.
Quoting from the release announcement.
Smaller size
In antd # 3.9.0, we introduced the svg icon ([Why use the svg icon?]
()). The icon API
using the string name cannot be loaded on demand, so the svg icon file
is fully introduced, which greatly increases the size of the packaged
product. In 4.0, we adjusted the icon usage API to support tree
shaking, reducing the default package size of Antant by about 150 KB
(Gzipped).
In order to install Ant Design 4 you have to do following
npm install antd#4.0.0-rc.1
// or in yarn
yarn add antd#4.0.0-rc.1

Resources