Can't get webpack to output bundled css? - css

i'm new to webpack and following a course. But one thing they don't really talk about is how to compile different sass to css.
I've given it a try here, but am getting an error. I'm trying to get it to output to styles.css for use with wordpress
const path = require('path'),
settings = require('./settings');
module.exports = {
entry: {
home: [
settings.themeLocation + "js/scripts.js"
],
style: [
settings.themeLocation +'styles/main.sass'
]
App: settings.themeLocation + "js/scripts.js"
},
output: {
home: [
path: path.resolve(__dirname, settings.themeLocation + "js"),
filename: "scripts-bundled.js"
]
style:[
path: path.resolve(__dirname, settings.themeLocation + "styles"),
filename: "styles-bundled.css"
]
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{ test: /\.css$/, use: 'css-loader' }
{ test: /\.sass$/, use: 'sass-loader' }
]
},
mode: 'development'
}

Here is a snippet from my webpack config
You need to install style-loader, css-loader and sass-loader
The following snippet is for development part
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
For production
{
test: /\.css$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
minimize: true,
importLoaders: 2,
},
},
],
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
minimize: true,
importLoaders: 3,
},
},
'sass-loader',
],
},
& add the folling to plugin section
new MiniCssExtractPlugin({
filename: '[name].[chunkhash:8].css',
}),
Note that the above snippets may not work directly for you, Its is just to give you idea how webpack can handle css $ scss

Related

Can't apply styles to React using loaders

In my webpack.config.js, I added "style-loader" and "css-loader" as recommended.
I also imported styles from "./style.css"(import styles from "./style.css") in my root component. But it doesn't apply styles to my app. What am I doing wrong? What am I missing?
I've got "Module not found: Error: Cannot resolve 'file' or 'directory'"
...
output: {
path: __dirname + './static',
filename: 'app.bundle.js'
},
{
test:/\.css$/,
use: [
"style-loader",
"css-loader",
]
}
...
Looks like your output.path is wrong. Works for me like this.
EDIT: also, the loaders go inside modules.rules
const path = require('path');
.
.
.
output: {
path: path.join(__dirname, 'static/')
filename: 'app.bundle.js'
},
module: {
rules:[
{
test:/\.css$/,
use: [
"style-loader",
"css-loader",
]
}
]}
You should change to loader something like this
module: {
rules: [{
test: /\.scss$/,
use: [
'style-loader',
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
minimize: true,
sourceMap: true
}
},
{
loader: "sass-loader"
}
]
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: ["babel-loader", "eslint-loader"]
},
{
test: /\.(jpe?g|png|gif)$/i,
loader: "file-loader"
},
{
test: /\.(woff|ttf|otf|eot|woff2|svg)$/i,
loader: "file-loader"
}
]
}

MiniCssExtractPlugin + SplitChunksPlugin doesn't put scoped css into bundle

I'm using a Webpack 4 setup, where I'm trying to get all my css into a single bundle, including my scoped css from .vue files. I'm using MiniCssExtractPlugin to extract the css from the files and SplitChunksPlugin to bundle all the css into a single file. The problem is that my scoped css from .vue files is being put into separate css files.
My webpack config:
optimization: {
splitChunks: {
cacheGroups: {
common: {
test: /[\\/]node_modules[\\/].*\.js$/,
name: 'common',
chunks: 'all'
},
styles: {
test: /\.css$/,
filename: '[name]-[contenthash].css',
chunks: 'all',
enforce: true
}
}
}
},
module: {
rules: [
{
enforce: 'pre',
test: /\.(js|vue)$/,
exclude: /node_modules/,
use: 'eslint-loader'
},
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.(sa|sc|c)ss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 3,
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
indentedSyntax: true
}
}
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
}),
new PurifyCSSPlugin({
paths: glob.sync([
path.join(__dirname, 'templates/**/*.html'),
path.join(__dirname, 'assets/js/**/*.js'),
path.join(__dirname, 'assets/js/**/*.vue')
]),
purifyOptions: {
info: true,
minify: true,
rejected: true
}
})
],
resolve: {
alias: {
jquery: 'jquery/src/jquery',
'vue': 'vue/dist/vue.js'
},
extensions: ['.js', '.vue', '.json', '.sass']
}
Output:
scoped-css-from-a-vue-file.03371a6565c9f56951dd.css // (172 bytes)
main-css-bundle-from-sass-files.af5152091d41a56d9bdd.css // (303 KiB)

Styling differences in Webpack Dev versus Prod

Short Summary:
I've noticed that there are small styling discrepancies between my dev/prod configurations of webpack when testing locally. It seems to have to do with the sass-loader, but it might expand outside of that? I can't be sure because it's very difficult to track down the bug.
(Code at bottom, images just to highlight certain elements)
The Clue
The majority of styles that are missing on dev or overwritten come from my Sass file. Therefore I imagine the culprit is buried somewhere in how I process Sass files on prod.config.js versus dev.config.js. Specifically, I've noticed that variables in Sass like $main-font are not interpreted on dev, but do seem ok on prod config. I've also noticed some weird overrides happening where dev might have a border applied from a set of classes, but production doesn't. Perhaps Minicssextract is doing something differently for prod?
The Problem
In the image below, the left is my production configuration. As you can see it's extracting text into a CSS file which is called in index.html. It's loading my SCSS variables just fine. On the right, I don't use minicssextractloader and all my styles get put into tags and injected. It's switching the font-family over to something that I haven't defined anywhere in my code?
The Loader
On the left is dev, on the right is prod for Sass.
Here's how this font is defined in Sass:
Ideas and tests:
Style-loader: I tried removing postcss, sass-loader, and style-loader on dev form the scss test. Didn't seem to fix the problem.
Is there a chance webpack is doing something funky between dev/production modes?
Perhaps my css compression on prod is making things strange?
Dev.config
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
require('babel-polyfill').default;
const PATHS = {
app: path.join(__dirname, '../src'),
build: path.join(__dirname, '../dist'),
};
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: ['webpack-hot-middleware/client', './src/index'],
mode: 'development',
output: {
publicPath: '/dist/',
filename: 'bundle.js',
},
resolve: {
extensions: ['.jsx', '.js', '.json', '.scss', '.less'],
modules: ['node_modules', PATHS.app],
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'sass-loader',
],
},
{
test: /\.less$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'less-loader',
},
],
},
{
test: /bootstrap-sass\/assets\/javascripts\//,
use: [
{
loader: 'imports-loader',
options: {
jQuery: 'jquery',
},
},
],
},
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: '$',
},
{
loader: 'expose-loader',
options: 'jQuery',
},
],
},
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 50000,
mimetype: 'application/font-woff',
},
},
],
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
},
},
],
},
{
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-otf',
},
},
],
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
},
},
],
},
{
test: /\.png$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.jpg$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.ico$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"development"',
},
__DEVELOPMENT__: true,
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.ProvidePlugin({
jQuery: 'jquery',
}),
],
};
Prod.config
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
require('babel-polyfill').default;
// const PurifyCSSPlugin = require('purifycss-webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const StatsPlugin = require('stats-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const cssnano = require('cssnano');
const PATHS = {
app: path.join(__dirname, '../src'),
build: path.join(__dirname, '../dist'),
};
const pathsToClean = [
'../dist/*.{js,css,eot,woff,woff2,svg,ttf,jpg,map}',
'../dist/index.html',
];
const cleanOptions = {
root: PATHS.build,
exclude: [
'sitemap.xml',
],
dry: false,
};
module.exports = {
// devtool: 'source-map',
entry: ['./src/index'],
mode: 'production',
output: {
publicPath: '/dist/',
chunkFilename: '[name].[chunkhash:4].js',
filename: '[name].[chunkhash:4].js',
},
resolve: {
extensions: ['.jsx', '.js', '.json', '.scss', '.less'],
modules: ['node_modules', PATHS.app],
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'sass-loader',
],
},
{
test: /\.less$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'less-loader',
},
],
},
{
test: /bootstrap-sass\/assets\/javascripts\//,
use: [
{
loader: 'imports-loader',
options: {
jQuery: 'jquery',
},
},
],
},
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: '$',
},
{
loader: 'expose-loader',
options: 'jQuery',
},
],
},
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
// test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 50000,
mimetype: 'application/font-woff',
},
},
],
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
},
},
],
},
{
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-otf',
},
},
],
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
},
},
],
},
{
test: /\.png$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.jpg$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.ico$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
__DEVELOPMENT__: false,
}),
new CleanWebpackPlugin(pathsToClean, cleanOptions),
new MiniCssExtractPlugin({
filename: '[name].[contenthash:4].css',
}),
new OptimizeCSSAssetsPlugin({
cssProcessor: cssnano,
cssProcessorOptions: {
options: {
discardComments: {
removeAll: true,
},
// Run cssnano in safe mode to avoid
// potentially unsafe transformations.
safe: true,
},
},
canPrint: false,
}),
new StatsPlugin('stats.json', {
chunkModules: true,
exclude: [/node_modules[\\/]react/],
}),
// new PurifyCSSPlugin({
// paths: glob.sync(PATHS.app),
// }),
],
optimization: {
minimizer: [
new UglifyJsPlugin({
sourceMap: true,
}),
],
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'initial',
},
},
},
runtimeChunk: {
name: 'manifest',
},
},
};
Some of the Sass that seems to be having trouble?
/** 03. Typography **/
$font-source: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif;
body {
font-size: 1em;
line-height: 1.85em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: $font-source;
color: $color-secondary;
font-weight: 400;
}
Found this old q while looking into why I had a similar problem.
In my case, there was iffy css in a sass file (an opacity value set as a percentage instead of a decimal)
Dev coped with that but prod didn't. I'm still not sure why beyond "prod is more strict" - but correcting the css syntax made it work on prod (of course)

Expected 'styleUrls' to be an array of strings aith webpack 4 and angular 5

I'm updating a project to new webpack and angular versions.
My webpack.config is as follows:
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: ['es2015']
}
},
{
test: /\.(jpg|png|webp|gif|otf|ttf|woff|woff2|ani)$/,
loader: "url-loader?name=[name].[hash:20].[ext]&limit=10000"
},
{
test: /\.ts$/,
loaders: ['ts-loader', 'angular2-template-loader?keepUrl=true'],
exclude: [/\.(spec|e2e)\.ts$/]
},
{
test: /\.css$/,
use: ['style-loader', {
loader: 'css-loader',
options: {
sourceMap: false,
importLoaders: 1
}
}, 'postcss-loader']
},
{
test: /\.html$/,
use: 'raw-loader'
},
{
test: /\.(svg)$/,
loader: 'html-loader'
},
]
}
and postcss.config:
module.exports = {
parser: 'postcss-scss',
plugins: {
'postcss-import': {},
'postcss-cssnext': {},
'cssnano': {}
}
Now I'm getting an error in the title of the question.
I know it was asked several times, but none of the answers helped me. What's wrong with my configs?
}
All my components have something like styleUrls: ['./component.style.css']. So I guess the problem is that those files can not be read. But I don't have an idea why

images in css with webpack 3

I have went over every stack overflow post regarding this issue, and still have been unable to solve this issue. I cannot get background-image: url() to work for the life of me. I am not kidding when I say I have gone through every post. Why is webpack so frustrating when it comes to this simple task? Below is my modules in my webpack.config. Please someone help I have been at this for two days.
module: {
loaders: [
{test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel-loader']},
{test: /bootstrap\/js\//, loader: 'imports?jQuery=jquery' },
{test: /\.css$/, loader: 'style-loader!css-loader'},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('css!scss')
},
{test: /\.woff(2)?(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/font-woff" },
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=images/svg+xml" },
{test: /\.(jpe?g|png|gif|svg)$/i, loaders: [
'file-loader?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false',
'url-loader?limit=90000000&name=src/images/[name].[ext]'
]}
]
}
You need to use resolve-url-loader to be able to use relative paths in scss, here an example of how to use it:
module: {
rules: [{
test: /\.scss$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[local]'
}
}, {
loader: 'resolve-url-loader',
options: {
sourceMap: true
}
}, {
loader: 'sass-loader',
options: {
outputStyle: 'compressed',
sourceMap: true
}
}
]
})
}, {
test: /\.(jpe?g|png|gif|svg)$/,
loaders: [{
loader: 'file-loader',
options: {
name: '[path][name].[hash:base64:5].[ext]',
publicPath: '/',
outputPath: 'img/'
}
}, {
loader: 'image-webpack-loader',
options: {
gifsicle: {
interlaced: false
},
optipng: {
optimizationLevel: 7
},
pngquant: {
quality: '65-90',
speed: 4
},
mozjpeg: {
progressive: true,
quality: 70
}
}
}]
}]
}
Pay attention to the options in file-loader that configuration tells webpack where to output the images.
In this commit there is a running example.

Resources