Webpack SASS to CSS with same folder structure - css

I'm reaching you because I don't understand how to configure webpack to build same style folder structure with css file in.
Here is my base structure in source folder :
src
|-images
| |--lorem-picsum.png
|-pages
| |--about.html
| |--home.html
|-styles
| |-pages
| | |--home.scss
| | |--home.scss
| |--main.scss
What I want is simply a compiling from scss to css file. Moreover, I want to keep the same folder/file structure as in my source folder. Like this :
src
|-images
| |--lorem-picsum.png
|-pages
| |--about.html
| |--home.html
|-styles
| |-pages
| | |--home.css
| | |--home.css
| |--main.css
So, I'm using MiniCssExtractPlugin, css-loader and sass-loader.
Like this : (webpack.config.js)
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// List of the pages
const pages = ["about", "home"];
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, './src/entry.js'),
output: {
path: path.resolve(__dirname, './dist'),
filename: 'main.js',
},
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
minimize: false,
}
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[name][ext]'
}
},
{
test: /\.(s(a|c)ss)$/,
use: [MiniCssExtractPlugin.loader,'css-loader', 'sass-loader']
}
],
},
plugins: [].concat(
pages.map((page) =>
new HtmlWebpackPlugin({
template: path.resolve(__dirname, `./src/pages/${page}.html`),
filename: path.resolve(__dirname, `./dist/pages/${page}.html`),
chunks: [page],
})
),
new MiniCssExtractPlugin(),
),
};
But when I build the project, I just get a scss file with barely nothing in it :
dist
|-images
| |--lorem-picsum.png
|-pages
| |--about.html
| |--home.html
|--b88d04fba731603756b1.scss
|--main.js
(b88d04fba731603756b1.scss)
// extracted by mini-css-extract-plugin
export {};
If you see where I'm going wrong, I'd love to hear from you.
Thank you in advance for your help

Related

How do I import all CSS files ins subdirectory with webpack / postcss #import '../Components/**/_partial.css';

Using a Webpack and PostCSS environment I would like to import all CSS files in my Components folder and the subdirectory. I've tried both PostCSS plugins postcss-easy-import & postcss-import and know they both need to come first. Regular Imports with direct paths work, could it be that ** placeholders don't work?
Thanks in advance
The best practice to import css or scss files is importing all your css files or components in one main.css or scss file. Then import that file in your entry *.js file and finally set that *.js file in your webpack config file as an entry.
For example if you have a folder called SampleProject and a folder and file structure like this:
SampleProject
|
|--css
| |--components
| | |--style1.css
| | |--style2.css
| | |--style3.css
|
|--js
| |--components
| | |--script1.js
| | |--script2.js
|
main.css
index.js
index.html
webpack.prod.js
package.json
Then you can import all you 3 style files in your main.css file like below:
main.css
#import 'css/components/style1.css';
#import 'css/components/style2.css';
#import 'css/components/style3.css';
Then you can import the main.css file into index.js with other js chunks like this:
index.js
import './main.css';
import 'js/components/script1.js';
import 'js/components/script2.js';
Finally, you can use this index.js as an entry point into your webpack config file like this:
webpack.prod.js:
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
entry: {
main: './index.js'
},
output: {
path: path.join(__dirname, './build'),
filename: '[name].[chunkhash:8].bundle.js',
chunkFilename: '[name].[chunkhash:8].chunk.js',
},
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
//'sass-loader',
],
},
{
test: /\.(png|svg|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/img',
esModule: false,
},
},
],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/font',
},
},
],
},
{
test: /\.html$/i,
use: {
loader: 'html-loader',
options: {
attributes: {
list: [
{
tag: 'img',
attribute: 'src',
type: 'src',
},
{
tag: 'img',
attribute: 'srcset',
type: 'srcset',
},
{
tag: 'img',
attribute: 'data-src',
type: 'src',
},
{
tag: 'img',
attribute: 'data-srcset',
type: 'srcset',
},
],
},
},
},
},
],
},
optimization: {
minimizer: [new TerserJSPlugin(), new OptimizeCSSAssetsPlugin()],
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
chunks: 'all',
},
runtimeChunk: {
name: 'runtime',
},
},
plugins: [
// load jQuery
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[chunkhash:8].bundle.css',
chunkFilename: '[name].[chunkhash:8].chunk.css',
}),
new HtmlWebpackPlugin({
chunks: ['main'],
template: 'index.html',
filename: 'index.html',
}),
],
};
And MiniCssExtractPlugin will extract all styles of your project automatically and save them as one file in build folder in root of your project.

Is it possible for Webpack (with plugins) to minify my CSS files, place it in my dist folder, and add a tag to index.html

I would like to end up with a CSS file that is a merged and minified version of my development environments standard CSS files. With a hashed name based on the content of the file which is automatically added as a tag in my resulting index.html file in my distribution folder.
Is this possible? I assume it is since I've gotten Webpack 4 to do just about everything else I've needed it to do. If it is, how would I go about it?
Mind you, it has to be set up this way. I'm not allowed to use import statements or the like in my JS.
I have tried playing with the Mini Css Extract plugin and Optimize CSS Assets Webpack plugin to see if they could do what I want, but I'm likely doing something wrong as I never get any output file ( I know it wouldn't give me a modified index.html, but having the CSS file would be a start at least).
My current file structure is basically:
'mainFolder'/public/css <- the src css folder,
'mainFolder'/dist/css <- the dist folder where I would like to put the minified file
My config is currently set up like thus:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: [
'./public/js/app.js',
'./public/js/filters/weekday.js',
'./public/js/filters/dial-in.js',
'./public/js/filters/time.js',
'./public/js/filters/group-member.js',
'./public/js/filters/bool-to-icon.js',
'./public/js/filters/date-format.js',
'./public/js/filters/time-format.js',
'./public/js/services/main.js',
'./public/js/configs/config.js',
'./public/js/controllers/main.js',
'./public/js/pages/calendar/controller.js',
'./public/js/pages/company/view/controller.js',
'./public/js/pages/company/edit/controller.js',
'./public/js/pages/group-meeting/create/controller.js',
'./public/js/pages/group-meeting/detail/controller.js',
'./public/js/pages/group-meeting/view/controller.js',
'./public/js/pages/group-meeting-calendar/controller.js',
'./public/js/pages/login/controller.js',
'./public/js/pages/meeting-link/view/controller.js',
'./public/js/pages/meeting-link/edit/controller.js',
'./public/js/pages/meeting-link/detail/controller.js',
'./public/js/pages/user/view/controller.js',
'./public/js/pages/user/edit/controller.js',
'./public/js/lib/angular-semantic-ui.min.js'
],
output: {
filename: 'js/[contenthash].js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'dist'
},
devtool: 'source-map ',
plugins: [
new CleanWebpackPlugin(['dist'], {
}),
new HtmlWebpackPlugin({
title: 'Zenvite',
template: './public/templates/index.html',
filename: 'templates/index.html'
}),
new CopyWebpackPlugin([
//{ from: 'public/css', to:'css'},
{ from: 'public/media', to:'media'},
{ from: 'public/js/pages', to: 'js/pages', ignore: [ '*.js' ]},
{ from: 'public/templates/app.html', to: 'templates'}
]),
new MiniCssExtractPlugin({
filename: 'app.css',
chunkFilename: '[contenthash].css',
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it use publicPath in webpackOptions.output
publicPath: '../public'
}
},
"css-loader"
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
}
}
}
},
};
Again the optimal result would be having something like [contenthash].css with merged and minified versions of my standard CSS and if possible an added tag in my index.html file.
So far I've got nothing of the sort (except copying the standard files over to the dist directory)
Thanks in advance for any help and if I can answer any questions, feel free to ask.
In the end, when my supervisor realized the import statement was stripped out during compile they allowed it. So we went using that route to achieve what we want. Bellow is ultimately what we went with
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
entry: [
'./public/js/app.js',
'./public/js/filters/weekday.js',
'./public/js/filters/dial-in.js',
'./public/js/filters/time.js',
'./public/js/filters/group-member.js',
'./public/js/filters/bool-to-icon.js',
'./public/js/filters/date-format.js',
'./public/js/filters/time-format.js',
'./public/js/services/main.js',
'./public/js/configs/config.js',
'./public/js/controllers/main.js',
'./public/js/pages/calendar/controller.js',
'./public/js/pages/company/view/controller.js',
'./public/js/pages/company/edit/controller.js',
'./public/js/pages/group-meeting/create/controller.js',
'./public/js/pages/group-meeting/detail/controller.js',
'./public/js/pages/group-meeting/view/controller.js',
'./public/js/pages/group-meeting-calendar/controller.js',
'./public/js/pages/login/controller.js',
'./public/js/pages/meeting-link/view/controller.js',
'./public/js/pages/meeting-link/edit/controller.js',
'./public/js/pages/meeting-link/detail/controller.js',
'./public/js/pages/user/view/controller.js',
'./public/js/pages/user/edit/controller.js',
'./public/js/lib/angular-semantic-ui.min.js'
],
output: {
filename: 'js/app.[contenthash].js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'dist'
},
devtool: 'source-map ',
plugins: [
new CleanWebpackPlugin(['dist'], {
}),
new HtmlWebpackPlugin({
title: 'Zenvite',
template: './public/templates/index.html',
filename: 'templates/index.html'
}),
new CopyWebpackPlugin([
//{ from: 'public/css', to:'css'},
{ from: 'public/media', to:'media'},
{ from: 'public/js/pages', to: 'js/pages', ignore: [ '*.js' ]},
{ from: 'public/templates/app.html', to: 'templates'}
]),
new MiniCssExtractPlugin({
filename: 'css/app.[contenthash].css'
})
],
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
}]
},
optimization: {
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true, // Must be set to true if using source-maps in production
}),
new OptimizeCSSAssetsPlugin({})
]
}
};

Extract multiple css files to different directories

I'm trying to compile some sass files and extract each one to multiple paths.
Example:
resources/home/a.scss -> public/home/a.css
resources/home/layout/b.scss -> public/home/layout/b.scss
resources/login/c.scss -> public/login/c.css
At the moment I'm using this config and it bundles every scss file:
const path = require("path")
const webpack = require("webpack")
const ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
// Context is an absolute path to the directory where webpack will be
// looking for our entry points.
context: path.resolve(process.cwd(), 'resources/assets'),
entry:
[
'./sass/app/home/a.scss',
'./sass/app/home/layout/b.scss',
'./sass/app/login/c.scss',
],
output: {
path: __dirname,
filename: '[name].js'
},
module: {
rules: [
{
test: /\.(scss)$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader'])
}
]
},
plugins: [
new ExtractTextPlugin({ filename: '[name].css', allChunks: true })
]
}
I think the problem is you are using an Array as the entry, which means that all of the dependencies (in this case the different css files, are added into the same output file).
You should change it to:
entry: {
a: './sass/app/home/a.scss',
b: './sass/app/home/layout/b.scss',
c: './sass/app/login/c.scss'
}
You can read more here https://webpack.js.org/concepts/entry-points/#object-syntax

How to load css in react app?

I created a react app using create-react-app and everything works fine except that I can't figure out how to load css/stylus files.
In my previous react project that wasn't created using create-react-app I used webpack.config but now I don't know where to include this file and how to use it.
This is my folder structure:
.
+--client
| +--node_modules
| +--public
| +--src
| +--package.json
+--server
| +--node_modules
| +--src
| +--.babelrc
| +--package.json
This is my previous webpack.config.dev.js file:
import path from 'path';
import webpack from 'webpack';
export default {
entry: [
'webpack-hot-middleware/client?reload=true',
path.join(__dirname, '/client/index.js')
],
output: {
filename: 'bundle.js',
path: '/',
publicPath: '/'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [
{
test: /\.js$/,
include: path.join(__dirname, 'client'),
loader: 'babel-loader',
},
{
test: /\.styl$/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
},
],
},
{
test: /\.css?$/,
use: [
'style-loader',
{
loader: 'css-loader',
},
],
},
],
},
resolve: {
extensions: [ '.js', '.styl' ]
}
}
Please let me know if I need to provide additional information.
There is detailed informations about how to add SCSS and Less files to create-react-app project on their documentation. You can check here for more detail.
You can add basic CSS styling with just importing the file like shown below;
import '/css/main.css';
Or you can add as classNames
const styles = {
header: {
fontSize: 18,
color: '#909090',
}
};
export default class Header extends React.Component {
render() {
return (
<h1 className={styles.header}>This is a header</h1>
);
}
}
One of the approaches involves loading CSS files (via css-loader) from your JS files, for a Text.jsx
import React from 'react';
import './screen.css'; // if screen.css is located next to Text.jsx
class Text extends React.Component {
// ...
}
export default Text;
You could also generate an output CSS, using e.g. ExtractTextPlugin (see Webpack2 loading and extracting LESS file)

How do i add Bootstrap css and js file in my project from webpack in reactjs and what do i add in webpack config file?

I am new to react and i have a project in which i am using bootstrap for css but now i want to load that css and js file from webpack.. I don't know how to load bootstrap files from webpack and how to write the config file of webpack but then also i have tried to load by searching about it..
here is my config file
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './index.js',
output: { filename: 'bundle.js' },
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
]
},
};
Please tell me any solution how do i do that?
Thanks a lot in advance.
And what do i import in my index.js file?
i just have my routes there..
import ReactDOM from "react-dom";
ReactDOM.render(
routes ,
document.getElementById("crm")
);
This is one option using Webpack 2 and HtmlWebpackPlugin / ExtractTextPlugin.
Add import './style.css'; (or wherever they are) to your react index.js (Where it says style you could also put bootstrap.min.css and/or other files.
Same for the js files import './jquery.js'; and import './bootstrap.js';.
The stylesheet Link/href will be injected in your index.html and the output css file(s) put in the dist (output.path) dir. The js files will be injected in your bundle.js (check CommonsChunkPlugin (link) to output these and other files in separate .js files.
output.publicPatch is important to make it not only work when index.html is requested directly but also via a route. This makes sure the link to css is added as /style.css not just style.css in index.html.
webpack.config:
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const path = require('path');
const config = {
entry: {
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/', <- used by HtmlWebpackPlugin
filename: 'bundle.js'
},
module: {
rules: [
{
use: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html'
}),
new ExtractTextPlugin("styles.css")
]
}
module.exports = config;
Hope this helps. Let me know.

Resources