PurgeCss remove necessary css with .ejs files - javascript

I'm using in my project bootstrap and webpack. I'm importing bootstrap library from source files, in this way I'm able to import only css and js component I need. However I want more advanced optimization for my css and I'm using purgecss too. Purgecss needs to point out pages that have html or injects html, into the content option of the plugin. I have this configuration in my
webpack.production.config.js
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
//prettier-ignore
plugins:[autoprefixer(),
purgecss({
content: [
"./src/**/index.ejs",
//"./dist/**/index.html",
//"./dist/**/*.js",
"./node_modules/bootstrap/js/src/popover.js",
"./src/**/*.js",
],
})],
},
},
},
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
autoprefixer(),
purgecss({
content: [
"./src/**/index.ejs",
//"./dist/**/index.html",
//"./dist/**/*.js",
"./node_modules/bootstrap/js/src/popover.js",
"./src/**/*.js",
],
}),
],
},
},
},
"sass-loader",
],
},
I'm using purgecss with postcss.
However the purgecss plugin seems doesn't recognize my index.ejs file and vital css is removed . If I cheat and I point out to my purgecss plugin the index.html file generated in the dist folder in the previous build it's all right. Then, purgecss can't handle .ejs files? Is there some workaround?
(Note that I have to indicate to the plugin the popover.js of the bootstrap library otherwise the css of the popover isn't included because it's a dynamic component not present in the html page but is added by popover.js)
(Note that my example is a minimal reproducible example to illustrate the problem)

Related

Generating CSS modules for React components in Bit

We started sharing a number of React components in our SPA as Bit.dev components and ran into an issue: can't use our components on Bit's dashboard due to CSS-modules as Bit's build process does not create them. We use Bit 0.0.687. Use "bit start" to launch Bit dashboard or "bit export" to publish the components to a remote scope, then open a remote dashboard. Our components which use: import style from './style.css' and relay on a CSS module get undefined "style" under Bit. May someone tell, please, if there is a way to alter Bit's build process to generate CSS modules? In our Application's Webpack build we use:
module: {
rules: [
{
test: /\.css$/i,
include: /src/,
exclude: /node_modules/,
use: [
{
loader: require.resolve('style-loader', {
paths: [require.resolve('webpack-config-single-spa')],
}),
},
{
loader: require.resolve('css-loader', {
paths: [require.resolve('webpack-config-single-spa')],
}),
options: {
importLoaders: 1,
sourceMap: true,
modules: {
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
},
},
],
}
]}
and Webpack 5.x.
As Bit uses CRA under the hood, renaming CSS files to style.module.css helps. CRA recognizes "module" suffix and compiles these CSS as modules.

How to load CSS files with webpack

Im trying to have my CSS file in the src folder copied into the dist folder on build - Im currently using a HTML file in my dist - ie im not using a javascript file so dont want the styles to be created as javascript.I just need the files to be copied into the dist. Heres my current config that isnt working.
const htmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
devServer:{
port:8000
},
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
},
{
test: /\.css$/i,
use: [ 'style-loader','css-loader'],
},
{
test: /\.(png|jpe?g|gif|glb|gltf|typeface.json)$/i,
loader: 'file-loader',
options: {
publicPath: './',
name: '[name].[ext]'
},
},
]
},
plugins: [
new htmlWebpackPlugin({
template: './src/index.html',
filename: './index.html'
})
]
}
I then use a link tag to add the css into the index.html file eg
<link rel="stylesheet" href="./style.css">
But this just adds javascript to the HTML file it builds in the dist.
How can i do this?
***EDIT: Im trying to add CSS files without merging them into my Javascript files
You can try using MiniCssExtractPlugin. As written in the documentation:
This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
To use it, you can first install it, import it, add a loader and a plugin to your webpack config. Here's an example (don't forget to note the order must be correct):
...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
...
module: {
rules: [
...
{
test: /\.css$/i,
use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader'],
},
...
],
},
plugins: [
...
new MiniCssExtractPlugin(),
],
};
It will also add an automatic link tag to your css files in index.html results.

CSS images not copied to output folder in Webpack

I am using Webpack to bundle a number of js/css files in a site. I am bundling bootstrap.css and chosen.css as part of my bundles. In order to create the bundles, I have a main.js that I am using as an entry point to import all the other files that I will need. I am using file-loader to process font and image files and move them to the appropriate directories. I am using the ExtractTextPlugin with the css-loader and resolve-url-loader to create a separate css bundle from my js bundle.
My main.js is:
import 'bootstrap/dist/css/bootstrap.css';
import 'chosen-js/chosen.css';
import './datetimehelper.js';
import './deletelink.js';
import './dropdown.js';
My webpack.config.js is:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/js/main.js',
output: {
filename: 'wwwroot/js/bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'images/[name].[ext]',
outputPath: 'wwwroot/'
}
}
]
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]',
outputPath: 'wwwroot/'
}
}
]
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: ['css-loader?url=false', 'resolve-url-loader'],
publicPath: '../'
})
}
]
},
plugins: [
new ExtractTextPlugin({
filename: 'wwwroot/css/bundle.css'
})
]
};
With the above configuration, the font references in bootstrap.css are picked up, moved to the appropriate directory and the urls are fixed in the css bundle that is emitted. However, the images that are referenced in chosen.css are not being picked up. Can anyone tell me what I need to do to make the images work correctly? I've tried replacing file-loader with url-loader and no change. I've also tried importing the images in my main.js and they were moved, but the urls in the css bundle were not rewritten correctly.
Having path configured in output makes life a lot easier. That would serve as the base output folder and all other loaders/plugins can work relative to that. May be the files were copied but not to your intended directory. Please do take a look at WebpackBootstrap repo. The config copies as well as converts image paths properly.
I finally figured it out. In the rules, I had:
{
test: /\.css$/,
use: ExtractTextPlugin.extract('css-loader', 'resolve-url-loader')
}
Instead, it should be:
{
test: /\.css$/,
loader: ExtratTextPlugin.extract('css-loader', 'resolve-url-loader')
}
Not sure what the difference is between use and loader because I'm fairly new to Webpack, but in this case it makes all the difference.

How to include all CSS files in node_modules to be built by css-loader?

I am trying to extract all the CSS files found in the node_modules directory into a single file. My Webpack config is as follows:
{ // node_modules css in /node_modules/**/*.css
test: /\.css$/,
include: /node_modules/,
// extract to the node modules css file
use: ExtractTextPluginNodeMods.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
modules: false,
},
},
],
}),
}
Unfortunately, none of the CSS files in the node_modules directory are being bundled into the file specified with ExtractTextPluginNodeMods. I have another ExtractTextPlugin instance that is successfully extracting CSS from my src directory. Any idea why I cannot get extraction of CSS from node_modules?
For reference, my other ExtractTextPlugin/Webpack config (which is bundling all of my CSS is here:
{
// OUR css in /src/
// the css output from sass loader will be caught here
// fonts are imported by css loader
// after transpiling of sass -> css, css-loader in webpack should take care of this
// https://github.com/webpack-contrib/css-loader
test: /\.css$/,
exclude: /node_modules/,
// extract to our css file
use: ExtractTextPluginSrc.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
// create modular css with the '[name]__[local]___[hash:base64:5]'
options: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
'postcss-loader',
],
}),
}
Webpack won't include the CSS files unless you explicitly import them from your javascript code. So you'll need:
import 'some_package/css/component.css';
in the part of your app that uses the CSS.
Alternatively you could use something like glob-loader to do
import 'glob-loader?node_modules_pattern_file';
and then have your "node_modules_pattern_file" include a glob like
../node_modules/**/*.css
...but I don't recommend this approach because you'll end up pulling in loads of files you don't need and it will be hard to maintain.

Vue.js + Webpack + vue-loader + bootstrap-sass + sass-loader

I'm just getting started with Vue.js + Webpack + vue-loader + bootstrap-sass + sass-loader and I'm a little lost.
What I'd like to do is use the SASS version of bootstrap with my SPA Vue.js code. I want to do this so my bootstrap customisations can be done using SASS. Here is what I've done:
Created a new Vue.js + webpack project with vue-cli.
Installed bootstrap-sass and sass-loader.
Added the following to build/webpack.base.conf.js:
{ test: /\.scss$/, loaders: [ 'style', 'css', 'sass' ] },
{ test: /\.(woff2?|ttf|eot|svg)$/, loader: 'url', query: { limit: 10000 } }
Created src/style.scss with one line: #import 'bootstrap';
Added this line to the top of src/main.js: import './style.scss'
When I now run npm run dev I get the following error:
ERROR in ./src/main.js
Module not found: Error: Cannot resolve module 'style' in Users/rstuart/Workspace/javascript/kapiche-demo/src
# ./src/main.js 3:0-25
I'm not sure why this isn't working.
Also, related to this question, how do I get access to Bootstrap SASS variables inside my Vue components? If I understand what is going on here, the SASS will be compiled to CSS before being included inline in main.js meaning there is no access to any Bootstrap variables in my components. Is there a way to achieve this?
I managed to solve this problem myself. Instead of trying to directly import style.scss, I deleted the file entirely and I replaced the <style> element of App.vue with the following:
<style lang="sass">
$icon-font-path: "../node_modules/bootstrap-sass/assets/fonts/bootstrap/";
#import '../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap';
.wrapper {
margin-top: $navbar-height;
}
</style>
This has the added bonus of making Bootstrap variables available in the style block of Vue components. Also, I removed { test: /\.scss$/, loaders: [ 'style', 'css', 'sass' ] } from webpacker.base.conf.js entirely but kept the bit dealing with fonts. The loader for .vue files already deals with sass.
I managed to worked it the right way like this:
Vue:
<style lang="sass">
$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
#import "~bootstrap-sass/assets/stylesheets/bootstrap";
</style>
webpack config loader:
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
{
test: /\.scss$/,
loaders: [ 'style-loader', 'css-loader', 'sass-loader' ]
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader?limit=10000&minetype=application/font-woff"
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "file-loader"
}
Take note that I use the bootstrap-sass and not the default boostrap
It's trying to resolve the style module that you specified as a loader in this section of your webpack.base.conf.js:
{ test: /\.scss$/, loaders: [ **'style'**, 'css', 'sass' ] }
Given that you have a css and sass loader, that's likely an erroneous entry that you can remove to get yourself going.

Categories