Rearrange style order in ccs bundle - css

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

Related

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)
}

Less module build failed in webpack after migrating from grunt

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

WebPack bundling breaks CSS

We have recently moved from Browserify to WebPack, while it has many nice plugins and optimisations, our (not so clean CSS) started to break.
I tracked the reason to a <style> block somehow inserted into the document.
A screenshot is attached, how to solve this?
Here is our webpack.conf.json
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
var BundleTracker = require('webpack-bundle-tracker');
module.exports = {
context: __dirname,
module: {
loaders: [{
loader: "babel-loader",
include: [
path.resolve(__dirname, "static/js")
],
test: /\.js?$/,
query: {
plugins: ['transform-runtime'],
presets: ['es2015', 'stage-0', 'react']
}
}, {
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}, {
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}, {
test: /\.(png|jpg|svg)?(\?v=\d+.\d+.\d+)?$/,
loader: 'url-loader?limit=8192'
}, {
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-woff'
}, {
test: /\.(ttf|otf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?|(jpg|gif)$/,
loader: 'file-loader'
}]
},
output: {
path: path.resolve('./static/bundles/'),
filename: "bundle.js"
},
plugins: [
new BundleTracker({
filename: './webpack-stats.json'
}),
new ExtractTextPlugin('bundle.css'),
new OptimizeCssAssetsPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery',
NProgress: 'nprogress',
toastr: 'toastr',
Cookies: 'js-cookie',
moment: 'moment'
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
minimize: true,
compress: true,
compressor: {
warnings: true
}
})
],
entry: [
// npm js
'./node_modules/select2/dist/js/select2.full.js',
'./node_modules/jquery-ticker/jquery.ticker.js',
'./node_modules/card/dist/jquery.card.js',
'./node_modules/jquery-ui/ui/widgets/datepicker.js',
'./node_modules/js-cookie/src/js.cookie.js',
'./node_modules/moment-timezone/builds/moment-timezone-with-data.js',
'./node_modules/intl-tel-input/build/js/intlTelInput.js',
'./node_modules/bootstrap-toggle/js/bootstrap-toggle.min.js',
// loader
'bootstrap-loader',
// run package
'./static/run.js',
// old javascript
'./static/js/profile.js',
'./static/js/main.js',
'./static/js/index_orders.js',
'./static/js/footer.js',
'./static/js/django_jquery_csrf_setup.js'
]
};

How to set material-css with webpack config?

Sorry to bother, because it could be a local problem. But it has been bothering me for days.
Here is my webpack config:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: 'dist/',
filename: 'build.js'
},
resolveLoader: {
root: path.join(__dirname, 'node_modules'),
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.js$/,
loader: 'babel?{"presets":["es2015"]}',
exclude: /node_modules/
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract(
"style-loader", "css-loader?sourceMap!postcss-loader")
},
{
test: /\.(jpg|png|gif)$/,
loader: "file-loader?name=images/[hash].[ext]"
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader?limit=10000&minetype=application/font-woff"
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "file-loader"
}
]
},
vue: {
loaders: {
css: ExtractTextPlugin.extract("css"),
}
},
plugins: [
new ExtractTextPlugin("style.css", {
allChunks: true,
disable: false
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
})
],
devtool: '#eval-source-map'
}
and my main.js:
import './libs/materialize/js/materialize.js'
import './libs/materialize/css/materialize.css'
Everything is fine, but when I check out the console of Chrome, it tells me this:
localhost/:13 GET http://localhost:3000/dist/dist/2751ee43015f9884c3642f103b7f70c9.woff2
localhost/:13 GET http://localhost:3000/dist/dist/ba3dcd8903e3d0af5de7792777f8ae0d.woff
localhost/:13 GET http://localhost:3000/dist/dist/df7b648ce5356ea1ebce435b3459fd60.ttf
Can you guys help me for this? Big thanks.
You must import define like this.
import 'materialize-css/dist/js/materialize.min.js'
import 'materialize-css/dist/css/materialize.min.css'

How to get svg from MDL working with webpack

Using a checkbox component form Material Design Lite, i.e.
https://getmdl.io/components/index.html#toggles-section/checkbox
the tickmark.svg is not shown properly when I use
import '../../node_modules/material-design-lite/src/material-design-lite.scss';
for bundling with npm and webpack. Instead of:
I get:
In the browser I find the following path to tickmark.svg which is the svg that is 'missing':
When using either one of these two alternatives it works as it should:
1) import '../../node_modules/material-design-lite/.tmp/material-design-lite.css';
2) import '../../node_modules/material-design-lite/material.min.css';
To compare, when using 2 I get following in the browser:
My webpack.config.js:
var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var Clean = require('clean-webpack-plugin');
var bootstrapPath = path.join(__dirname, 'node_modules/bootstrap/dist/css');
var sourcePath = path.join(__dirname, 'assets');
module.exports = {
devtool: 'eval-source-map',
context: __dirname,
entry: [
'./assets/js/index' // entry point of our app. .assets/js/index.js should require other js modules and dependencies it needs
],
output: {
path: path.resolve('./assets/bundles/'),
filename: '[name]-[hash].js',
}
,
node: {
console: true,
fs: 'empty'
}
,
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.BannerPlugin('Pqbq Banner!!!! todo'),
new HtmlWebpackPlugin({
template: __dirname + '/assets/index.tmpl.html'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new Clean(['assets/bundles'])
],
module: {
preloaders: [
{
test: /\.js/,
loader: 'eslint'
}
],
loaders: [
{
test: /\.js[x]?$/,
loader: 'babel',
exclude: /(node_modules|bower-components)/,
query: {
presets: ['es2015', 'stage-0']
}
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.js$/,
include: path.resolve(__dirname, 'node_modules/mapbox-gl/js/render/shaders.js'),
loader: 'transform/cacheable?brfs'
},
{
test: /\.js$/,
include: path.resolve(__dirname, 'node_modules/webworkify/index.js'),
loader: 'worker'
},
// {
// test: /\.css$/,
// loader: 'style!css?modules!postcss'
// },
{
test: /\.scss$/,
loaders: ['style', 'css?sourceMap', 'sass?sourceMap']
},
// {test: /\.(woff2?|svg)$/, loader: 'url?limit=10000'},
// {test: /\.(ttf|eot)$/, loader: 'file'},
{test: /\.css$/, loader: 'style-loader!css-loader'},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
{test: /\.(woff|woff2)$/, loader: 'url?prefix=font/&limit=5000'},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
// {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'},
{test: /\.svg$/, loader: 'url?limit=8192!svgo'},
]
}
,
postcss: [
require('autoprefixer')
],
resolve: {
modulesDirectories: ['node_modules', 'bower_components', bootstrapPath, sourcePath],
extensions: ['', '.js', '.jsx', '.css'],
alias: {
webworkify: 'webworkify-webpack',
'$': 'jquery',
'jQuery': 'jquery'
}
}
,
devServer: {
contentBase: './assets',
colors: true,
historyApiFallback: true,
inline: true,
hot: true
}
};
To fix this I had to override the $image_path variable by creating my own material.scss file. I grabbed this file:
https://github.com/google/material-design-lite/blob/master/src/material-design-lite.scss
and then added:
#import "./variables";
at the top.
In that file I added this line:
$image_path: '~material-design-lite/dist/images/' !default;

Resources