Less module build failed in webpack after migrating from grunt - css

I can't figure out how to compile my less files to css and then include them in my build folder, without the app failing to run. Trying to build/run the application returns the following error:
ERROR in ./content/styles/less/ts.less
Module build failed:
#import "node_modules/bootstrap/less/mixins/buttons.less";
#import "node_modules/Font-awesome/less/font-awesome.less";
^
Can't resolve './node_modules/Font-awesome/less/font-awesome.less' in '/home/thinkpad/work/EPD.SPA/EpdSPA/content/styles/less'
in /home/thinkpad/work/EPD.SPA/EpdSPA/content/styles/less/ts.less (line 4, column 0)
# multi ./content/styles/less/for.less ./content/styles/less/kladd.less ./content/styles/less/ts.less
To clarify: These files have already proved to be working with grunt. The webpack migration triggered these errors.
I'm using the webpack config examples from here. My config file:
var webpack = require('webpack');
var globby = require('globby');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var AssetsPlugin = require('assets-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
const extractLESS = new ExtractTextPlugin('stylesheets/[name]-two.css');
module.exports = {
entry: {
app: globby.sync(['./app/app.js','./app/app.run.js', './app/app.config.js', './app/**/*.js']),
styles: globby.sync(['./content/styles/*.css']),
lessStyles: globby.sync(['./content/styles/less/*.less']),
images: globby.sync(['./content/images/**/*.*']),
vendor: [
// removed to save space
]
},
output: {
filename: './scripts/[name].bundle.js',
path: path.join(__dirname, "public")
},
devServer: {
port: 1384,
contentBase: './public/'
},
// Enable sourcemaps for debugging webpack's output.
devtool: 'source-map',
module: {
rules: [
{ test: /\.less$/,
use: extractLESS.extract([ 'css-loader', 'less-loader' ])
},
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [/node_modules/]
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }),
},
{
test: /\.(ico)$/,
loader: "url-loader?name=./[name].[ext]",
include: path.resolve(__dirname, "content", "images")
},
{
test: /\.svg$/,
loader: 'svg-loader'
},
{
test: /\.(jpg|jpeg|gif|png|PNG|tiff|svg)$/,
loader: 'file-loader?name=/[path]/[name].[ext]',
include: path.resolve(__dirname, "content", "images"),
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?minetype=application/font-woff&name=./fonts/[name].[ext]'
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
},
{
test: require.resolve('adal-angular/lib/adal'),
loader: 'expose-loader?AuthenticationContext'
},
{
test: /\.js$/,
enforce: "pre",
loader: 'source-map-loader'
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './app/layout.html',
filename: 'index.html'
}),
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: './scripts/vendor.bundle.js' }),
new ExtractTextPlugin({ filename: './[name].bundle.css' }),
/*
new CleanWebpackPlugin(['./public'], {
verbose: false
}),
*/
new AssetsPlugin({
filename: 'webpack.assets.json',
path: './public/scripts',
prettyPrint: true
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery',
"window.AuthenticationContext": "AuthenticationContext",
_: 'underscore'
}),
new CopyWebpackPlugin([
{from: './app/**/*.html', to: './'}
]),
extractLESS // including the less files here
],
externals: [
{ xmlhttprequest: '{XMLHttpRequest:XMLHttpRequest}' }
]
}
Here you can see that the less files have been compiled to css and included in the public(build) folder. Why do i get errors, if the config file executes as intended?
Here it also shows that all the files are included in the application in the browser as well. I have checked all my dependencies and they are all running latest versions.

The path for the imports in the less files, were incorrect. Here is the working references:
#import "~bootstrap/less/variables.less";
#import "~bootstrap/less/mixins/buttons.less";
#import "~font-awesome/less/font-awesome.less";

I think the problem is with your font_awesome path.
Try to change import to (font_awesome instead of Font_awesome)
#import "node_modules/font-awesome/less/font-awesome.less";

Related

Error importing mobiscroll css styles in webpack

I have a problem with importing mobiscroll css styles in my react project (created by webpack)
Other css files are working well but
This line generates Error:
import '#mobiscroll/react-lite/dist/css/mobiscroll.min.css'
The generated Error:
./node_modules/#mobiscroll/react-lite/dist/css/icons_mobiscroll.ttf?vtxdtu 1:0
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
./node_modules/#mobiscroll/react-lite/dist/css/icons_mobiscroll.woff?vtxdtu 1:4
Module parse failed: Unexpected character '�' (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
./node_modules/#mobiscroll/react-lite/dist/css/icons_mobiscroll.woff 1:4
Module parse failed: Unexpected character '�' (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
and my webpack.config.js:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const path = require('path');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CSSModuleLoader = {
loader: 'css-loader',
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: true
}
};
const CSSLoader = { loader: 'css-loader' };
const PostCSSLoader = {
loader: 'postcss-loader',
options: {
ident: 'postcss',
sourceMap: false, // turned off as causes delay
plugins: () => [
autoprefixer({
browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9']
})
]
}
};
const StyleLoader = {
loader: 'style-loader'
};
const SassLoader = {
loader: 'sass-loader'
};
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
chunkFilename: '[id].js',
publicPath: ''
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}, {
test: /\.html$/,
use: [{loader: 'html-loader'}]
},
{
test: /\.(sa|sc|c)ss$/,
exclude: /\.module\.(sa|sc|c)ss$/,
use: [StyleLoader, CSSLoader, PostCSSLoader, SassLoader]
},
{
test: /\.module\.(sa|sc|c)ss$/,
use: [StyleLoader, CSSModuleLoader, PostCSSLoader, SassLoader]
},
{
test: /\.(svg|png|jpe?g|gif|bmp)$/,
loader: 'url-loader?limit=10000&name=img/[name].[ext]'
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file?name=[name].[ext]'
}
]
},
plugins: [
new CopyWebpackPlugin({
patterns: [ // for copying the content of 'public/static' folder to 'dist' folder
{ from: path.resolve(__dirname, 'public/static'), to: path.resolve(__dirname, 'dist/static')}
]
}),
new HtmlWebpackPlugin({
template: __dirname + '/public/index.html',
filename: 'index.html',
inject: 'body'
}),
]
};
my webpack configuration is working well for all other css or scss files but can not load that css file. what's the problem?
please help me with this.
I found out my mistake. I haven't defined a loader for font files and that css file was using some fonts.
This solved my Problem:
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
// exclude: /node_modules/,
loader: 'file-loader',
options: {
limit: 1024,
name: '[name].[ext]',
publicPath: 'dist/assets/',
outputPath: 'dist/assets/'
}
}

How can I grab bunch of scss files and make one css file for all application

I've got webpack.config and don't know what module I need to place in it, cause I found modules, whitch only minimises css or scss files, but not collecting them.
So I have 8-9 scss files, and need one css file, which collects all code from them
var path = require('path');
module.exports = {
entry: {
home: './src/main/js/home/home.js',
products: './src/main/js/products/products.js',
product: './src/main/js/product/product.js',
profile: './src/main/js/profile/profile.js',
topics: './src/main/js/topics/topics.js',
topic: './src/main/js/topic/topic.js',
},
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/[name].bundle.js'
},
module: {
rules: [
{
test: path.join(__dirname, '.'),
exclude: /(node_modules)/,
use: [{
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}]
}
]
}
};
What module I Should install, and where I need to put code in webpack.config. Please help, I've never worked with webpack!
var path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: {
home: './src/main/js/home/home.js',
products: './src/main/js/products/products.js',
product: './src/main/js/product/product.js',
profile: './src/main/js/profile/profile.js',
topics: './src/main/js/topics/topics.js',
topic: './src/main/js/topic/topic.js',
_article: './src/main/resources/static/sass/_article.scss',
_catalog: './src/main/resources/static/sass/_catalog.scss',
_home: './src/main/resources/static/sass/_home.scss',
_header: './src/main/resources/static/sass/_header.scss',
_footer: './src/main/resources/static/sass/_footer.scss',
},
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/[name].bundle.js'
},
module: {
rules: [
{
test: [ /\.scss$/, path.join(__dirname, '.')],
exclude: /(node_modules)/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
})[{
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}]
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
};
That'smy webpack.config
webpack works different than gulp. Gulp is a task runner, which can work with globs and file patterns. Webpack is a bundler, which analyses the dependency tree given your entry points to be able to create your bundles.
In order to work with webpack, and bundle all scss files, they would need to be imported somewhere from your entry point. That is the only way that webpack will know these files exist.
Edit: Correct config.
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
home: './src/main/js/home/home.js',
products: './src/main/js/products/products.js',
product: './src/main/js/product/product.js',
profile: './src/main/js/profile/profile.js',
topics: './src/main/js/topics/topics.js',
topic: './src/main/js/topic/topic.js',
_article: './src/main/resources/static/sass/_article.scss',
_catalog: './src/main/resources/static/sass/_catalog.scss',
_home: './src/main/resources/static/sass/_home.scss',
_header: './src/main/resources/static/sass/_header.scss',
_footer: './src/main/resources/static/sass/_footer.scss',
},
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/[name].bundle.js'
},
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}
}
]
},
plugins: [
new MiniCssExtractPlugin()
]
};

Unable to inline styles with `sass-loader`

I have a project setup where I use ExtractTextPlugin to create a CSS file. I'm trying to create a dev Webpack config with the styles injected onto the page using style-loader, css-loader, and sass-loader.
As far as I am aware the default behaviour is to inject the styles into a <style /> tag and I've removed all traces of ExtractTextPlugin but it still doesn't want to inject the styles.
Does anybody know what might cause the styles to be lost? My Webpack config is below.
Config:
const webpack = require('webpack')
module.exports = config => Object.assign({}, {
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
},
plugins: [
new webpack.SourceMapDevToolPlugin({
filename: 'bundle.js.map'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
]
}, config)
Called with:
module.exports = require('../../dev')({
name: 'Onboarding',
entry: './src/apps/components/Onboarding/index.js'
})
I was able to get it working by rewriting most of my Webpack config. I had already tried the css-loader options below, so I'm not sure why they worked now but not before.
This is my new dev-only config:
const webpack = require('webpack')
const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')
module.exports = config => {
const { out, libraryTarget, name = 'main' } = config
const filename = `${name}.js`
delete config.out
return Object.assign({}, {
output: {
path: path.resolve(__dirname, '../../../' + out),
filename,
libraryTarget,
publicPath: '/assets/js/'
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
query: {
importLoaders: 1,
modules: true,
localIdentName: '[name]_[local]_[hash:base64:5]'
}
},
'sass-loader']
}
]
},
plugins: [
new HTMLWebpackPlugin({
title: 'App Name',
filename: '../../index.html',
template: './test-lambda/template-dev.html',
inject: 'body'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.SourceMapDevToolPlugin({
filename: `${filename}.map`
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
]
}, config)
}

Rearrange style order in ccs bundle

After a migration from grunt, the styles are not working as intended with webpack. All the styles were concatenated in the gruntfile like this:
target: {
files: {
"all.css": [
"node_modules/bootstrap/dist/css/bootstrap.css",
"bower_components/toastr/toastr.css",
"bower_components/angular-ui-select/dist/select.css",
"node_modules/font-awesome/font-awesome.css",
"bower_components/angular-loading-bar/build/loading-bar.css",
"bower_components/angular-ui-tree/dist/angular-ui-tree.css",
"content/styles/awesome-bootstrap-checkbox.css",
"content/styles/tradesolution.css",
"content/styles/site.css",
"content/styles/ts.css",
"content/styles/nyKladd.css"
]
}
}
My current config in webpack:
var webpack = require('webpack');
var globby = require('globby');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var AssetsPlugin = require('assets-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var DashboardPlugin = require('webpack-dashboard/plugin');
const ConcatPlugin = require('webpack-concat-plugin');
const extractCSS = new ExtractTextPlugin('[name].css');
const extractLESS = new ExtractTextPlugin('[name].css');
module.exports = {
entry: {
app: globby.sync(['./app/app.js','./app/app.run.js', './app/app.config.js', './app/**/*.js']),
Ztyles: globby.sync(['./content/styles/less/*.less']),
styles: globby.sync(['./content/styles/*.css']),
images: globby.sync(['./content/images/**/*.*']),
vendor: [
// removed to save space
],
},
output: {
filename: './scripts/[name].bundle.js',
path: path.join(__dirname, "public")
},
devServer: {
port: 1384,
contentBase: './public/'
},
// Enable sourcemaps for debugging webpack's output.
devtool: (() => {
if(NODE_ENV = "devlopment") return 'source-map'
else return 'cheap-module-eval-source-map'
}) (),
module: {
rules: [
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [/node_modules/]
},
{
test: /\.css$/,
loader: extractCSS.extract(
{ fallback: 'style-loader', use: 'css-loader' }
),
//'style-loader', 'css-loader'
},
{ test: /\.less$/,
use: extractLESS.extract(
{fallback:'style-loader', use: ['css-loader','less-loader']}
)
//'style-loader', 'css-loader!less-loader'
},
{
test: /\.(ico)$/,
loader: "url-loader?name=./[name].[ext]",
include: path.resolve(__dirname, "content", "images")
},
{
test: /\.(jpg|jpeg|gif|png|PNG|tiff|svg)$/,
loader: 'file-loader?name=/[path]/[name].[ext]',
include: path.resolve(__dirname, "content", "images"),
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff&name=./fonts/[name].[ext]' },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader?name=./fonts/[name].[ext]' },
{
test: require.resolve('adal-angular/lib/adal'),
loader: 'expose-loader?AuthenticationContext'
},
{
test: /\.js$/,
enforce: "pre",
loader: 'source-map-loader'
}
],
},
plugins: [
new webpack.DefinePlugin({
ADMIN_API_URL: JSON.stringify('http://localhost:41118/api/'),
API_URL: JSON.stringify('http://epdapi.tradesolution.no/'),
GLOBAL_ADMIN_URL: JSON.stringify('https://adminapi.tradesolution.no/')
}),
new HtmlWebpackPlugin({
template: './app/layout.html',
filename: 'index.html'
}),
extractCSS,
extractLESS,
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: './scripts/vendor.bundle.js' }),
new ExtractTextPlugin({ filename: './[name].bundle.css' }),
new AssetsPlugin({
filename: 'webpack.assets.json',
path: './public',
prettyPrint: true
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery',
"window.AuthenticationContext": "AuthenticationContext",
_: 'underscore'
}),
new CopyWebpackPlugin([
{from: './app/**/*.html', to: './'}
]),
new DashboardPlugin()
],
externals: [
{ xmlhttprequest: '{XMLHttpRequest:XMLHttpRequest}' }
],
}
From this picture you can see that the default bootstrap styles are overriding the styles written for the nav-bar.
What i have done so far is to implement all the other css files into one less file, like this:
#import "../tradesolution.css";
#import "../site.css";
#import "../nykladd.css";
#import "for";
#import "kladd.less";
#import "~bootstrap/less/bootstrap";
#import "~bootstrap/less/alerts.less";
#import "~bootstrap/less/mixins/buttons.less";
#import "~font-awesome/less/font-awesome.less";
Then the less file is compiled to css and loaded in the Ztyles.css , but regardless of where I put the imports, my styles are still overridden. I have also tried changing the order of the webpack rules and the order of extractCSS and extractLESS in plugins
I dont think my intended solution is good practice, so any approach to solving this issue is very welcome.
After a while i stumbled over a new css framework postcss they have all kinds of plugins, and with this configuration I got it to work:
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { modules: true, importLoaders: 1 },
loader: 'postcss-loader',
},
]
},
{ test: /\.less$/,
use: extractLESS.extract(
{fallback:'style-loader', use: ['css-loader', 'less-loader']}
)
},
Here are some resources that helped:
https://github.com/postcss/postcss
https://webdesign.tutsplus.com/tutorials/using-postcss-together-with-sass-stylus-or-less--cms-24591
https://github.com/Crunch/postcss-less

Webpack: wrong absolute path in compiled CSS

I'm migrating an Angular 1 project in order to be able to deploy everything with Webpack.
So far, I managed to configure almost everything but I'm having issues trying to export the static assets (fonts and images mostly).
I've configured the ExtractTextPlugin as below
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader','css-loader', {allChunks: true}) }
and in the compiled CSS the paths are replaced but the resulting absolute path is wrong. In fact the resulting path is /assetsweb/assets/.. while I expect it to be /assets/...
I cannot understand where the /assetsweb part is coming from.
Here's the Webpack configuration I'm using
var webpack = require("webpack");
var path = require("path");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
context: __dirname + "/src",
entry:{
web: "./web/wayonara.js",
mobile: "./mobile/wayonara.js"
},
output:{
path: __dirname + "/dist",
filename: "/[name]/bundle.js",
publicPath: "/assets"
},
plugins:[
new webpack.DefinePlugin({
ENV: JSON.stringify('dev')
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
EXIF: "exif-js",
"window.EXIF":"exif-js"
}),
new ExtractTextPlugin("/[name]/assets/css/bundle.css")
],
module:{
loaders: [
{
loader: "babel-loader",
test: /\.js?$/,
exclude: [/node_modules/, /bower_components/],
query: {
presets: ['es2015']
}
},
{ test: /\.html$/, loader: "html" },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader','css-loader', {allChunks: true}) },
{
test: /\.(jpg|jpeg|png|svg)$/,
loader: "file-loader?name=[path][name].[ext]"
},
{
test: /\.(woff|woff2|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?/,
loader: 'file-loader?name=[path][name].[ext]'
}
]
}
};
Can you help me? Thanks in advance,
Best,
Maurizio

Resources