Removing unused CSS via purgecss-webpack-plugin
-
Hi guys! Forgive me for my bad english!
I use - Vue CLI + Quasar. Almost a default project.
https://gitlab.com/arogonov/vue3-quasar-testThe goal is to remove unused CSS from production using purgecss-webpack-plugin.
vue.config.cfg
const PurgecssPlugin = require('purgecss-webpack-plugin'); const glob = require('glob-all'); const path = require('path'); let plugins = []; if (process.env.NODE_ENV === 'production') { plugins = [ new PurgecssPlugin({ paths: glob.sync([ path.join(__dirname, './src/**/*.vue'), path.join(__dirname, './src/**/*.js'), ]), extractors: [ { extractor: (content) => content.match(/[A-Za-z0-9-_:\/]+/g) || [], extensions: ['html', 'vue', 'js'], }, ], whitelistPatterns: [ /data-v-.*/, ], }), ]; } module.exports = { pluginOptions: { quasar: { importStrategy: 'kebab', rtlSupport: false, }, }, transpileDependencies: [ 'quasar', ], configureWebpack: { plugins, }, };
HelloWorld.vue
<template> <q-page class="flex flex-center"> <div class="q-pa-sm bg-red"> <q-icon name="fas fa-hand-scissors"></q-icon> Quasar style </div> <div class="styleRegular"> <i class="fas fa-hand-peace"></i> Style regular </div> <div class="styleScoped"> styleScoped </div> </q-page> </template> <script> export default { name: 'HelloWorld', }; </script> <style> .styleRegular{ background-color: #ff0000; padding: 10px; } </style> <style scoped> .styleScoped{ background-color: #ffff00; padding: 10px; } </style>
After build, we get not quite what we would like.
Here is https://friendly-turing-742683.netlify.app/Remained in the assembly
- Css from Quasar which we directly used in HelloWorld.vue (class = âq-pa-sm bg-redâ)
- Css from non-Scoped block (class = âstyleRegularâ)
Were removed, but I want to stay.
- Css properties that are used inside Quasar components and are not present in ./src.
- Css from Scoped block (class = âstyleScopedâ) although in PurgecssPlugin settings I have /data-v-.*/ in whitelistPatterns.
Please, tell me what to do!
Thanks in advance.
-
@arogonov There are issues with removing unused CSS. It will remove CSS that it âthinksâ is not used, but in reality it is.
For instance, when you pass a color to a Quasar component, ie: âredâ, behind the scenes, quasar adds the prefix:'bg-' + this.color
But,bg-red
will be removed because no match was found in the code. -
@hawkeye64 said in Removing unused CSS via purgecss-webpack-plugin:
There are issues with removing unused CSS. It will remove CSS that it âthinksâ is not used, but in reality it is.
For instance, when you pass a color to a Quasar component, ie: âredâ, behind the scenes, quasar adds the prefix: âbg-â + this.color
But, bg-red will be removed because no match was found in the code.I may have misunderstood you, but bg-red remained in place, everything is fine. It was not deleted. Everything worked as it should.
-
@arogonov Thatâs good news! I suppose purgeCSS has improved and matured since the last time I tried it
-
@arogonov @Hawkeye64 said in Removing unused CSS via purgecss-webpack-plugin:
So 2 issues remain:
Css properties that are used inside Quasar components and are not present in ./src.
Would that not be solved by adding any other folders that contain Quasar components?
path.join(__dirname, './foo/**/*.vue'), path.join(__dirname, './foo/**/*.js'),
Css from Scoped block (class = âstyleScopedâ) although in PurgecssPlugin settings I have /data-v-.*/ in whitelistPatterns.
Any clue why
whitelistPatterns
doesnât work? -
@dobbel said in Removing unused CSS via purgecss-webpack-plugin:
Would that not be solved by adding any other folders that contain Quasar components?
My HelloWorld.vue uses Quasar components.
Or do you suggest doing this?path.join(__dirname, './node_modules/quasar/src/components/**/*.js'),
But this is a strange idea
@dobbel said in Removing unused CSS via purgecss-webpack-plugin:
Any clue why whitelistPatterns doesnât work?
The question about the scoped block is removed. Iâm an idiot using the old settings. It is necessary like this.
safelist: { standard: [/data-v-.*/], },
-
@arogonov said in Removing unused CSS via purgecss-webpack-plugin:
But this is a strange idea
Sure, but does it work?
-
I found a solution that small SPA sites can use and that works great.
- Install purgecss separately
npm i --save-dev purgecss
- We use the prerender-spa-plugin. And vue.config.js looks like this now
const PrerenderSPAPlugin = require('prerender-spa-plugin'); const path = require('path'); let plugins = []; if (process.env.NODE_ENV === 'production') { plugins = [ new PrerenderSPAPlugin({ staticDir: path.join(__dirname, 'dist'), routes: [ '/', ], }), ]; } module.exports = { pluginOptions: { quasar: { importStrategy: 'kebab', rtlSupport: false, }, }, transpileDependencies: [ 'quasar', ], configureWebpack: { plugins, }, };
- Create purgecss.config.js
module.exports = { content: ['./dist/index.html', './dist/**/*.html', './dist/js/*.js'], css: ['./dist/**/*.css'], output: ['./dist/css/'], keyframes: true, variables: true, };
- edit package.json in scripts section
"scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build && purgecss --config ./purgecss.config.js", "lint": "vue-cli-service lint" },
This method works perfectly (the css file has decreased from almost 200 to 15kb, ideally leaving only the css that is needed), but will not work for large sites with changing content.
@dobbel said in Removing unused CSS via purgecss-webpack-plugin:
Sure, but does it work?
Iâll try it now, but in any case, you cannot use this command
path.join(__dirname, './node_modules/quasar/src/components/**/*.js'),
Since then all js files from all components will be checked - and this makes no sense, since all CSS properties will be exported, even those components that I do not use.
Today I will think about what can be done about it.
-
Through experiments, it turned out that if in the example above you make this purgecss.config.js
module.exports = { content: ['./dist/js/*.js'], css: ['./dist/css/*.css'], output: ['./dist/css/'], keyframes: true, variables: true, safelist: { standard: [/fixed-.*/], }, };
Works on a project without a prerender-spa-plugin. In any case, on the default project.
The solution is not reliable and requires constant testing during development. Since even in the default project, purgecss could not find the âfixed-topâ properties in the js files. In a large project, there can be much more such losses.
I want something more reliable, but how to do it is not clear.
-
This is the best attempt I have seen so far to integrate purgecss with Quasar to decrease css bundle size.
You could create a github issue with your findings/progres.