Webpack throwing error on SCSS #import SCSS - css

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';

Related

Webpack 5 Split chunks not working with scss imports

I have a very basic webpack(v5.75.0) file setup:
webpack.config.js:
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
home: './src/home.js',
about: './src/about.js'
},
mode: "development",
resolve: {
extensions: ['.js', '.jsx', '.scss']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].js',
clean: true
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
MiniCssExtractPlugin.loader, "css-loader", "sass-loader",
],
},
],
},
plugins: [new MiniCssExtractPlugin({ filename: "css/[name].css"})],
optimization: {
splitChunks: {
chunks: 'all',
minSize: 0,
},
},
};
Home.js:
import "./home.scss";
About.js:
#import "./about.scss";
home.scss:
#import "./card.scss";
about.scss
#import "./card.scss";
My understanding is that with my splitChunk settings, this should create a seperated stylesheet, with the card css, so I can share it around the project.
However, all I get is an output of about.css and a home.scss, both containing the same card css, and no shared file is created.
interestingly, if I change both the imports in home/about.js to css instead:
#import "./card.css";
Then a separate chunk file is created, and the css is split perfectly.
Could anyone tell me what I have done wrong, please?
Answering my own question.
Turns out it was a very simple fix.
I had to import all my page specific .scss into my home/about.js file, rather than trying to make a single entry scss file (that imports all the page specific scss).
I assume #import in scss is copying the css into the file(as it should), and doesn't care about chunking, like the js does.

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

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

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.

How does one deploy a ReactJs component that imports its own stylesheets?

I'm developing a large React component that I want to import into another React app. (I could have done it all as one big app, but I decided to separate this component into a its own project so that I could focus on the component separately.) It uses its own stylesheets, which it pulls in with "require('path/to/stylesheet.[s]css')".
For development, I serve it with webpack-dev-server which takes care of loading and pre-processing those stylesheets. My problem is that I don't know how to deploy the component so that another app can include it without breaking when the browser encounters those calls to require(path/to/stylesheet).
I've found lots of examples where projects use webpack-dev-server for development, but invoke babel (or other pre-processors) directly in order to deploy components to a dist/ directory, so this seems to be a common practice. But what to do about those invocations of "require('path/to/stylesheet.[s]css')"? Without webpack and its loaders to rely on, they all fail.
Ideally, I'd like to be able to use webpack for both development and production. Then I could deploy my component as a complete bundle and the css would be included in the code. I tried this earlier but it didn't work. It also has the disadvantage of making it hard for the main app to over-ride the styles in the component.
I suppose another way might be to set up my pipeline so that a main.scss includes all the other stylesheets and let Sass output a single style.css file that the consuming app has to include separately. Less elegant, but it makes it easier to override these styles.
I'm still mastering React and its eco-system, so I'd love to know what the best practice is for this in case anyone knows.
You need to run webpack and bundle all of your JS/CSS so that it can be consumed in your other project. If you use the correct loaders, the CSS is bundled directly into your JS bundle. Or, you can use a different loader to have webpack generate you a nice style.css file that bundles all your require(/path/to/css) into one file.
There are three or four basic things you need to do (Assuming webpack#3.*):
Use the "externals" in your webpack config file to exclude libraries in your package.json dependencies list.
Use babel-loader to transpile your javascript (ES2015 is supported by most browsers).
Use 'style-loader', 'css-loader', and 'sass-loader' to bundle your css/scss into your webpack js bundle. (This assumes you aren't using server-side react rendering. That's a bit trickier. You would need to use an isomorphic style loader instead.)
Optionally, use the extract-text-webpack-plugin to pull your css out into a separate file. (Commented out in the example below)
Be sure to make your bundle.js file the entry point in your package.json
Here is a good example of what you are trying to do: (This example works for server-side rendering as well as browser rendering. The BABEL_ENV lets us only require css files on the browser.)
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const env = process.env.NODE_ENV;
console.log('Environment: ', env)
module.exports = {
devtool: 'source-map',
entry: env == 'production' ? './src/components/index.js' : './src/index.js',
output: {
path: env !== 'production' ? require('path').resolve('./dev'): require('path').resolve('./dist'),
filename: 'bundle.js',
publicPath: '/',
library: 'reactPorto',
libraryTarget: 'umd'
},
externals: env == 'production' ? [
'jquery',
'react',
'react-dom',
'react-bootstrap',
/^react-bootstrap\/.+$/,
'classnames',
'dom-helpers',
'react-owl-carousel',
'react-owl-carousel2',
'uncontrollable',
'warning',
'keycode',
'font-awesome'
] : [],
devServer: {
inline: true,
contentBase: './dev',
staticOptions: { index: 'test.html' },
historyApiFallback: {
rewrites:[{ from: /./, to: 'test.html' }],
},
hot: true,
},
plugins: [
// new ExtractTextPlugin({
// filename: 'style.css',
// allChunks: true
// }),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(env || 'development'),
'BABEL_ENV': JSON.stringify(env || 'development')
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
...(env != 'production' ? [new webpack.HotModuleReplacementPlugin()] : []),
...(env == 'production' ? [new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } })] : []),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: [
'es2015',
'react',
'stage-2',
...(env != 'production' ? ['react-hmre'] : [])
],
plugins: []
}
}
},
{
test : /(\.css|\.scss)/,
// exclude: /node_modules/,
// use : ExtractTextPlugin.extract({
// use: [
// 'isomorphic-style-loader',
// {
// loader: 'css-loader',
// options: {
// importLoaders: 1
// }
// },
// 'sass-loader'
// ]
// }),
use: ['iso-morphic-style-loader', 'css-loader', 'sass-loader']
},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml'},
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/octet-stream"},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader"},
{test: /\.(png|jpg|jpeg)/, loader: 'file-loader' }
]
}
}

Compiling a .less file to a specific .css file using webpack

I want to use webpack, to compile a style.less file to a module.css file.
I have found https://github.com/webpack-contrib/less-loader as a very popular package, which however does not seem to work for me, since I really need to create that module.css file.
So how can I do that with webpack?
Found the solution myself. The following webpack.config.js snippet works for me:
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = function(env) {
return {
...
module: {
loaders: [
{
test: /.*\.less$/,
loader: ExtractTextPlugin.extract({
loader:[ 'css-loader', 'less-loader' ],
fallbackLoader: 'style-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin({ filename: 'module.css', disable: false, allChunks: true })
]
};
};
Where ... is a placeholder for other parts of the config, which are not relevant here.

Resources