How to merge several css files into one in webpack 4? - css

I want to compose one main.css file from several css files. How can I make this using webpack 4?
This is my webpack.config.js:
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, 'public/app.js'),
output: {
path: path.resolve(__dirname, 'public'),
filename: 'app.bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
plugins: ['#babel/plugin-proposal-class-properties']
}
}
}
]
},
plugins: []
};

Webpack has some awesome tools available for merging files into one, I would suggest you using .scss files and let those merge into css files. However that is your own preferred issue.
Please take a look at this plugin to merge multiple css files into one.
https://github.com/oklas/merge-webpack-plugin
A better understanding can be found at this post as well: https://medium.com/trabe/multiple-css-bundles-with-webpack-75f263095f09

Related

Webpack 4 - Style-loader/url not working

I'm having my webpack set up and it's running all fine, but in development it is serving my compiled scss stylesheets inline instead of using an URL.
module: {
rules: [
{
test: /\.scss$/,
use: [
{ loader: "style-loader"},
{ loader: "css-loader" },
{ loader: 'postcss-loader',
options: {
plugins: () => [require('autoprefixer')]
}
},
{ loader: "sass-loader" }
]
}
]
}
So I grabbed the docs and read up on how to use a single CSS file instead. I updated my webpack config to the following and since all loaders are running in reverse order this should be working;
module: {
rules: [
{
test: /\.scss$/,
use: [
{ loader: "style-loader/url"},
{ loader: "file-loader" },
{ loader: "css-loader" },
{ loader: 'postcss-loader',
options: {
plugins: () => [require('autoprefixer')]
}
},
{ loader: "sass-loader" }
]
}
]
}
It results in no errors, and inserts the following stylesheet into my header;
<link rel="stylesheet" type="text/css" href="6bbafb3b6c677b38556511efc7391506.scss">
As you can see it's creating an scss file, whereas I was expecting a .css file. I tried moving the file-loader around but that didn't work either and resulted in several crashes. Any idea how to turn this into a working css file?
I can't use mini-css-extract in my dev env since I'm using HMR. I already got this working on my prod env.
Update: When removing css-loader it compiles and shows my css applied to the page. But when I inspect the elements everything is on line 1 and the file it refers to can not be found
I'm importing my css like this in index.js by the way;
import '../css/styles.scss';
You can install extract-text-webpack-plugin for webpack 4 using:
npm i -D extract-text-webpack-plugin#next
The you can define the following constants:
// Configuring PostCSS loader
const postcssLoader = {
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
// Write future-proof CSS and forget old preprocessor specific syntax.
// It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support.
require('postcss-preset-env')()
]
}
};
// Configuring CSS loader
const cssloader = {
loader: 'css-loader',
options: {
importLoaders: 1
}
};
Then in your SASS loader section, you can use the following:
ExtractTextPlugin.extract({
use: [cssloader, postcssLoader, 'sass-loader']
})
Then in you plugins section, you need to use the following:
new ExtractTextPlugin({
filename: 'css/[name].css'
)
Now suppose that your entry section is like below:
entry: {
app: 'index.js'
}
The generated CSS will be named as app.css and placed inside the css folder.
Another useful plugins for handling these type of post creating operations are:
HtmlWebpackPlugin and HtmlWebpackIncludeAssetsPlugin
Working with these plugins along with extract-text-webpack-plugin gives you a lot of flexibility.
I had a similar issue with webpack, after searching for a long time i found the soluton of combining a few plugins:
This is my result config: (as a bonus it preserves your sass sourcemaps;))
watch: true,
mode: 'development',
devtool: 'source-map',
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css", //make sure you use this format to prevent .scss extention in the hot reload file
chunkFilename: "[id].css"
})
],
module: {
rules: [
{
test: /\.scss$/,
use: [
'css-hot-loader', //5. this will hot load all the extracted css.
MiniCssExtractPlugin.loader, //4 this will extract all css
{
loader: "css-loader", //3. this is where the fun starts
options: {
sourceMap: true
}
},
{
loader: "postcss-loader", //2. add post css
options: {
sourceMap: true
}
},
{
loader: "sass-loader", //1 . you can ingore the globImporter
options: {
importer: globImporter(),
includePaths: ["node_modules"],
sourceMap: true
}
}
]
},
]
}

Webpack build successfull but styles.css file style is not reflecting

I am developing a web application in angular 5.Now I have included webpack 4 in my application.But There is a problem all styles written in styles.css file are not reflecting in the build created from webpack.
Need solution for this problem.
Below is my webpack.common.js file which is used for loading diffrent types of files present in my application build always succeed but the styles.css code is not reflection on my site when it gets loaded in browser.But code written in components .scss file reflects properly i have searched a lot but did not find any solution for this issue why is is happening.
import styles from './styles.css';
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
entry: {
'polyfill': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/main.ts'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
loader: ['awesome-typescript-loader','angular2-template-loader','angular-router-loader'
],
exclude:[/node_modules/]
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file-loader?name=assets/images/[name].[hash].[ext]'
},
{
test: /\.(css|scss)$/,
include: helpers.root('src', 'app'),
loaders: ['css-loader']
},
{
test: /\.js$/,
include: helpers.root('src', 'app'),
loader: 'babel-loader',
exclude:[/node_modules/],
query:{
presets:['es2015']
}
}
]
},
plugins: [
// Workaround for angular/angular#11580
new webpack.ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)#angular/,
helpers.root('./src'), // location of your src
{} // a map of your routes
),
new ExtractTextPlugin("src/styles.css"),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
You should import your css stylesheet using #import from your main css/scss stylesheet.
Do NOT import a css file as a javascript module from the webpack config file. This has no sense.

Webpack 4.6.0 loading css file: You may need an appropriate loader to handle this file type

I have been using webpack 4.6.0:
I have following issue when compiling:
Uncaught Error: Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type.
| div {
| background-color: yellow;
| color: red;
my webpck config is as following:
var path = require('path');
var webpack = require('webpack');
module.exports = {
mode:'development',
entry: './src/code/app.js',
output: { path: __dirname, filename: 'bundle.js'},
watch: true,
module: {
rules: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: "transform-class-properties",
presets: ['es2015', 'react']
}
},
{
// Do not transform vendor's CSS with CSS-modules
// The point is that they remain in global scope.
// Since we require these CSS files in our JS or CSS files,
// they will be a part of our compilation either way.
// So, no need for ExtractTextPlugin here.
test: /\.css$/,
include: /node_modules/,
loader: 'css-loader'
}
]
}
};
and I have :
"css-loader": "^0.28.11",
and my file struct is like:
root:
-src
|-code
|-XXXX.js
|-css
|-HomePage.css
I think it is something related to my css loader, I have tried many methods online, but none of them works. Is there something related to my file structure?
I believe you still need to add a rule for your own css files. Try adding this to your rules.
{
// Preprocess your css files
// you can add additional loaders here (e.g. sass/less etc.)
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader'],
}

Webpack throwing error on SCSS #import SCSS

I'm trying to process multiple SCSS files into a single external CSS file in Webpack (3.6.0) except I'm encountering issues around the parsing of the #import statements.
Entry index.js contains:
import './styles/main.scss';
Entry SCSS:
#import 'reset.scss';
#import 'global.scss';
#import 'fonts.scss';
#import 'system.scss';
Current webpack:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js'
},
context: path.resolve(__dirname),
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
},
plugins: [
new CleanWebpackPlugin(['app']),
new HtmlWebpackPlugin({
title: 'Minimum-Viable',
filename: 'index.html',
template: './public/index.html',
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'es2015',
'react',
],
plugins: ['transform-class-properties'],
},
},
},
{
test: /\.scss$/,
include: [
path.resolve(__dirname, 'styles')
],
use: [
{loader:'style-loader'},
{loader:'css-loader'},
{loader:'sass-loader'}
]
},
],
},
resolve: {
extensions: ['.js','.scss']
}
};
The Error being thrown is:
ERROR in ./src/styles/main.scss Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type. | #import 'reset.scss';
Any pointers gratefully received.
I managed to reproduce the error and it seems to come from:
include: [
path.resolve(__dirname, 'styles')
],
The path is the issue cause the loader searches for /styles in ./styles but looking at your entry point:
entry: {
app: './src/index.js'
},
It should actually be ./src/styles so:
include: [
path.resolve(__dirname, 'src', 'styles')
],
with:
include: [
path.resolve(__dirname, 'styles')
],
you are instructing webpack to use your loader chain only on files residing in your styles folder.
reset.scss looks like a node dependency usually stored in your node_module, which is excluded from SASS processing by the include option.
Try to remove your SASS include option or to extend it in order to include node_folder or the specific module imported by your styles.
I basically have the same config as you, except for two things:
{
test: /\.scss$/,
exclude: /node_modules/,
use: ["style-loader", "css-loader", "sass-loader"]
}
If your webpack is in a different folder compared to your project root, __dirname may not work out for you. You might need to remove that statement all together or change it to process.cwd(). I can give you another hint and that may be that you are missing the node-sass package. Secondly, you are probably not using the right syntax for webpack version 2 or 3 as shown in the use key.
Have you tried Extract text webpack plugin
https://github.com/webpack-contrib/extract-text-webpack-plugin
Basically it will collect all of your styles files(imported in your code) and pack it to bundled css which you can then just link to your html.
Did you try this way?
index.js:
import './styles/main.scss';
import './styles/reset.scss';
import './styles/global.scss';
import './styles/fonts.scss';
import './styles/system.scss';

How to use autoprefixer for external css files - webpack

I have all the css files inside ${ROOT}/resource/css/. While building using webpack, I want to copy all the css files to ${ROOT}/build/css/ with desired vendor prefixes added to all the css rules.
Currently I am using copywebpackplugin to copy all the css files as is to ${ROOT}/build/css/. I am struggling to add add a step to add vender prefixes. Please help.
Below the my webpack config:
config = {
entry: {
"new": "./resources/js/new",
"view": "./resources/js/view",
"edit": "./resources/js/edit",
"preview": "./resources/js/preview",
"sidebar": "./resources/js/sidebar",
"frame": "./resources/js/frame"
},
output: {
filename: "[name].js",
path: "build/js"
},
module: {
loaders: [
{test: /\.js$/, loaders: ["babel-loader", "eslint-loader"]}
]
},
plugins: [
new CopyWebpackPlugin([{
from: './resources/css/*.css',
to: './build/css/[name].css'
}])
]
}

Resources