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

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.

Related

Compile CSS and JS in difference files / WEBPACK

For 2 days I have been trying to compile the js and css file to a separate file because now everything is together. Does anyone have any idea how this can be solved?
I would be very grateful for your help.
There is my code webpack.config.js
const path = require('path');
const webpack = require('webpack');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'src/dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
{
loader: "css-loader",
options: {
url: false
}
},
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
]
},
plugins: [
new BrowserSyncPlugin({
// browse to http://localhost:3000/ during development,
// ./public directory is being served
host: 'localhost',
port: 3000,
files: ['./src/*.html'],
server: { baseDir: ['src'] }
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
};
I think MiniCssExtractPlugin is what you are looking for.
It takes the output of css-loader and create .css bundles. It takes care of downloading them in the browser (by pushing a section of code in webpack runtime code), and also yeah, it minifies the .css :).
Simple usage:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
Yes you are right. Style-loader creates javascript snippets that later in runtime creates .css rules and push them to the browser global css scope.

Minimize SCSS to CSS with webpack keeping file/folder structure

I am having trouble understanding how to compile and minify my scss files to css, while keeping the same folder and file structure. I am using MiniCssExtractPlugin to extract everything, as well as style-loader, css-loader, postcss-loader, and sass-loader
Here is the file structure in my src folder
app.scss contains all the imports. importing from folders 1-7. I am first having trouble with the imports, and then have trouble compiling and minimizing the remaining scss files.
The end goal is to have an compiled folder look like this with each file being minimized and app.scss bundle all the imports
Here is a run down of the code I have so far for webpack.config.js
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: '[id].css'
})
],
module: {
rules: [
{
test: /\.(scss|css)$/,
use: [
'style-loader',
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { sourceMap: true } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } },
]
}
]
},
optimization: {
minimizer: [new TerserJSPlugin({extractComments: false}), ],
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/](lodash)[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
When running this code, I just get an app.css file under a css folder that does not have imports included, and no other files are included as well. Can someone help my understand the process I need to take? I've been all over docs for each loader and not really understanding what I am looking for.
Thanks!

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 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 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' }
]
}
}

Resources