Webpack, "hot-reload" or "live-reload" sass? - sass

Is there a way to get webpack to "recompile" sass and reload your page on the fly?
I've been searching around but have not found an example.
Here is what I've got:
My folder structure
-app
---public
------dist
---------index.html
---------sass
------------webpack.scss
It seems like my sass only recompiles when I run webpack but it doesn't recompile when I am running the webpack-dev-server
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
module.exports = {
entry: {
app: './app/main.js',
//All 3rd party source
vendor: ['react', 'redux', 'lodash']
},
output: {
path: path.join(__dirname, 'app', 'public', 'dist'),
publicPath: '/app/public/dist/',
filename: 'app.js'
},
module: {
loaders: [
{ test: /\.js$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
{ test: /.jsx?$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.css/, loader: ExtractTextPlugin.extract('css') },
{ test: /\.scss$/, loader: ExtractTextPlugin.extract('!css!sass?sourceMap') }
]
},
sassLoader: {
includePaths: [ path.resolve(__dirname, './app/public/sass/')]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js", Infinity),
new ExtractTextPlugin('./css/style.css',{
allChunks: true
})
],
debug: true,
//watch: true
};

Related

Webpack add query string to bundle for cache-busting

so in my index.html, I have this line to include the webpack bundle
<script src="/dist/bundle.js"></script>
And my webpack config looks like this:
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: "./src/main.js",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
options: { presets: ["#babel/env"] }
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
resolve: { extensions: ["*", ".js", ".jsx"] },
output: {
path: path.resolve(__dirname, "dist/"),
publicPath: "/dist/",
filename: "bundle.js"
},
devServer: {
contentBase: path.join(__dirname, "public/"),
port: 3000,
publicPath: "http://localhost:3000/dist/",
hotOnly: true
},
plugins: [new webpack.HotModuleReplacementPlugin()]
};
How could I modify this, to add a query string (?v=some_nr) to the bundle when I run webpack --mode production. I can copy the index.html to dist/index.html or some other location, if needed, I'll be moving it to the webroot automatically anyway afterwards.

Browser debugger not working with Webpack 2 and webpack-dev-server

I've spent last few hours to set up a new project utilizing Webpack 2 and Babel 6.
The problem I have is non working debugger (any browser). Breakpoints are simply ignored. Using debugger; works fine but browser does not breaks execution exactly in that line.
webpack.config.js:
const path = require("path");
module.exports = {
entry: path.resolve(__dirname, "src", "index.js"),
output: {
filename: "app.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}]
},
devServer: {
contentBase: path.resolve(__dirname, "dist")
}
};
.babel.rc:
{
"presets": [
"latest"
]
}
I'm running the whole thing with webpack-dev-server -d
devtool: "source-map", option in webpack config should solve your problem.
entry: ['babel-polyfill', './src/index.jsx'],
output: {
filename: 'js/bundle.[hash].js',
path: path.resolve(__dirname, 'build'),
publicPath: '/'
},
resolve: {
extensions: ['.js', '.jsx'],
alias: {
config: path.join(__dirname, `config/${env}.configuration.js`)
}
},
**devtool: "source-map",**
module: {
rules: [
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: 'jQuery'
}
]
},

Webpack runs, Elixir throws errors - undefined is not a function

After hours of pulling my hair out, I finally got webpack to run on an existing project, that I'm trying to port to Laravel.
When I run webpack it compiles now...
...but when I run gulp in the root, which executes Elixir, I get this error message:
node_modules/webpack/lib/NullFactory.js:9 undefined is not a function
My webpack.config.js looks like this:
var path = require('path');
var webpack = require('webpack');
var debug = process.env.NODE_ENV !== "production";
module.exports = {
devtool: 'source-map',
entry: debug ? [
'webpack-hot-middleware/client',
'./resources/assets/js/client/index'
] : [
'./resources/assets/js/client/index'
],
output: {
path: path.join(__dirname, 'public/js'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: debug ? [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': "'production'"
}
}),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false,warnings: false })
],
resolve: {
root: [
path.resolve('./resources/assets/js/client')
],
alias: {
},
},
module: {
loaders: [
// js
{
test: /\.js$/,
loaders: ['babel'],
include: path.join(__dirname, 'resources/assets/js/client')
},
// CSS
{
test: /\.styl$/,
include: path.join(__dirname, 'resources/assets/js/client'),
loader: 'style-loader!css-loader!stylus-loader'
},
{
test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'
},
{
test: /\.json?$/,
loader: 'json'
},
{ test: /\.html$/, loader: "html" }
/* {
test: /\.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
cacheDirectory: true,
presets: ['react', 'es2015']
}
}*/
]
}
};
Ok, I have very outdated version of Node... upgrading fixed it.

Webpack SCSS and autoprefixer do not work together

Having the following webpack configuration for assets compiling I can't get autoprefixer to work. The extracted css does not get the needed prefixes.
var webpack = require('webpack'),
precss = require('precss'),
autoprefixer = require('autoprefixer'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
path = require('path');
const sassLoaders = [
'css-loader!autoprefixer-loader?browsers=last 2 version',
'postcss-loader',
'sass-loader?indentedSyntax=sass&includePaths[]=' + path.resolve(__dirname, '.')
]
const config = {
entry: {
//nsb: ['./js/nsb']
dashboard: ['./js/dashboard']
},
module: {
loaders: [
{
test: /\.sass$/,
loader: ExtractTextPlugin.extract('style-loader', sassLoaders.join('!'))
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('css!sass')
},
{
test: /\.docs\.css$/,
loader: "style-loader!css-loader!postcss-loader?pack=cleaner"
},
{
test: /\.css$/,
loader: "style-loader!css-loader!postcss-loader"
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }
]
},
postcss: function () {
return {
defaults: [precss, autoprefixer],
cleaner: [autoprefixer({ browsers: [] })]
};
},
output: {
filename: '[name].js',
path: path.join(__dirname, './build'),
publicPath: '/bundles/dashboard/build/'
},
amd: {jQuery: true},
plugins: [
new ExtractTextPlugin('[name].css'),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js', Infinity)
],
/* postcss: [
autoprefixer({
browsers: ['last 2 versions']
})
],
*/
resolve: {
alias: {
jquery: 'node_modules/jquery/dist/jquery.js',
magnificPopup: 'node_modules/maginific-popup/dist/jquery.magnific-popup.js' //JQuery Plugin
},
modulesDirectories: ['./js', 'node_modules'],
extensions: ['', '.js', '.sass'],
root: [path.join(__dirname, './')]
}
}
module.exports = config;
The css-loader comes with it's own autoprefixer config you will need to disable this in order for your config to work. So wherever you have css-loader you need to do add to disable the css-loader autoprefixer.
css-loader?-autoprefixer
More info can found here & here
So your config will look like this
var webpack = require('webpack'),
precss = require('precss'),
autoprefixer = require('autoprefixer'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
path = require('path');
const sassLoaders = [
'css-loader?-autoprefixer!autoprefixer-loader?browsers=last 2 version',
'postcss-loader',
'sass-loader?indentedSyntax=sass&includePaths[]=' + path.resolve(__dirname, '.')
]
const config = {
entry: {
//nsb: ['./js/nsb']
dashboard: ['./js/dashboard']
},
module: {
loaders: [
{
test: /\.sass$/,
loader: ExtractTextPlugin.extract('style-loader', sassLoaders.join('!'))
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('css!sass')
},
{
test: /\.docs\.css$/,
loader: "style-loader!css-loader?-autoprefixer!postcss-loader?pack=cleaner"
},
{
test: /\.css$/,
loader: "style-loader!css-loader?-autoprefixer!postcss-loader"
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }
]
},
postcss: function () {
return {
defaults: [precss, autoprefixer],
cleaner: [autoprefixer({ browsers: [] })]
};
},
output: {
filename: '[name].js',
path: path.join(__dirname, './build'),
publicPath: '/bundles/dashboard/build/'
},
amd: {jQuery: true},
plugins: [
new ExtractTextPlugin('[name].css'),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js', Infinity)
],
/* postcss: [
autoprefixer({
browsers: ['last 2 versions']
})
],
*/
resolve: {
alias: {
jquery: 'node_modules/jquery/dist/jquery.js',
magnificPopup: 'node_modules/maginific-popup/dist/jquery.magnific-popup.js' //JQuery Plugin
},
modulesDirectories: ['./js', 'node_modules'],
extensions: ['', '.js', '.sass'],
root: [path.join(__dirname, './')]
}
}
module.exports = config;
Also, I think you can remove the autoprefixer-loader that you have inside your sassLoaders since you are using PostCSS with autoprefixer.
You could try the following code, notice the addition of "?-autoprefixer" between css-loader and postcss-loader.
var webpack = require('webpack'),
precss = require('precss'),
autoprefixer = require('autoprefixer'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
path = require('path');
const sassLoaders = [
'css-loader!autoprefixer-loader?browsers=last 2 version',
'postcss-loader',
'sass-loader?indentedSyntax=sass&includePaths[]=' + path.resolve(__dirname,
'.')
]
const config = {
entry: {
//nsb: ['./js/nsb']
dashboard: ['./js/dashboard']
},
module: {
loaders: [
{
test: /\.sass$/,
loader: ExtractTextPlugin.extract('style-loader', sassLoaders.join('!'))
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('css!sass')
},
{
test: /\.docs\.css$/,
loader: "style-loader!css-loader?-autoprefixer!postcss-loader?pack=cleaner"
},
{
test: /\.css$/,
loader: "style-loader!css-loader?-autoprefixer!postcss-loader"
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }
]
},
postcss: function () {
return {
defaults: [precss, autoprefixer],
cleaner: [autoprefixer({ browsers: [] })]
};
},
output: {
filename: '[name].js',
path: path.join(__dirname, './build'),
publicPath: '/bundles/dashboard/build/'
},
amd: {jQuery: true},
plugins: [
new ExtractTextPlugin('[name].css'),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js', Infinity)
],
/* postcss: [
autoprefixer({
browsers: ['last 2 versions']
})
],
*/
resolve: {
alias: {
jquery: 'node_modules/jquery/dist/jquery.js',
magnificPopup: 'node_modules/maginific-popup/dist/jquery.magnific-popup.js' //JQuery Plugin
},
modulesDirectories: ['./js', 'node_modules'],
extensions: ['', '.js', '.sass'],
root: [path.join(__dirname, './')]
}
}
module.exports = config;
One more note: In my project's root directory I also have a postcss.config.js with the following content:
module.exports = {
parser: 'postcss-scss',
plugins: [
require('autoprefixer'),
]
}

Is it possible to load SASS in Webpack without bundling fonts BUT with source maps?

I don't want to bundle fonts and images but i need sourceMaps
I have this config (irrelevant parts ommited):
output: {
path: './build/',
publicPath: 'http://localhost:3000/',
filename: '[name].js'
},
module: {
loaders: [
{ test: /\.scss$/, loaders: ['style','css?-url,sourceMap', 'sass?sourceMap'] }
]
}
With this config I get multiple errors in Chrome:
Failed to decode downloaded font: http://localhost:3000/
(index):1 OTS parsing error: invalid version tag
I read a lot of answers and some solutions for similar problem:
1. get rid off 'sourceMap' - it works, and fonts are correctly displayed BUT ... no sourceMaps
2. change publicPath to URL - done it
I cannot find any solution that allows me load fonts outside bundle AND have CSS with sourceMaps...
I just figured it out. The key to solution is ExtractTextPlugin that makes normal link tags instead of 'blobs' and all fonts work super, css are external (even better when they are large), source maps work. Here is my full config if anyone interested:
var path = require('path');
var webpack = require('webpack')
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: {
demo: ['./demo/index.ts', 'webpack-dev-server/client?http://localhost:3000'],
lib: ['./src/js/index.js']
},
output: {
path: './build/',
publicPath: '/',
filename: '[name].js'
},
debug: true,
devtool: 'source-map',
resolve: {
extensions: ['', '.ts', '.js']
},
module: {
loaders: [
{ test: /\.tsx?$/, loader: 'ts' },
{ test: /\.coffee$/, loader: 'coffee' },
{ test: /\.(png|jpg)$/, loader: 'url' },
{ test: /\.jsx?$/, loader: 'babel', query: { presets: ['es2015'] }, exclude: /node_modules/, },
{ test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css?sourceMap!sass?sourceMap') },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style', 'css?sourceMap') },
{ test: /\.(ttf|eot|svg|woff(2)?)(\?[\s\S]+)?$/, loader: 'url' }
]
},
devServer: {
contentBase: './demo'
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
new ExtractTextPlugin("[name].css", { allChunks: true })
]
};

Resources