SCSS sourcemaps not working with Webpack 3 + ExtractTextPlugin - javascript

I'm trying to enable sourcemaps for my SCSS in my app and have a really puzzling situation on my hands. Here's my config file:
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssets = require('optimize-css-assets-webpack-plugin');
let config = {
entry: './src/index.ts',
devtool: 'eval-source-map', // for choosing a style of source map
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist')
},
devServer: {
contentBase: path.resolve(__dirname, './dist'), // A directory or URL to serve HTML content from
historyApiFallback: true, // fallback to /index.html for SPA
inline: true,
open: false // open default browser on launch
},
module: {
rules: [
{
test: /\.ts$/, // files ending with .ts
exclude: /node_modules/, // exclude the node modules directory
use: 'ts-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["env"]
}
}
},
{
test: /\.scss$/, // files ending with .scss
use: ['css-hot-loader'].concat(
ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
// { loader: 'style-loader', options: { sourceMap: true } },
{ loader: 'css-loader', options: { sourceMap: true } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } },
],
})
)
},
{
test: /\.(png|svg|jpg|gif)$/, // for other file types
use: ['file-loader?name=[name].[ext]&outputPath=img/']
}
]
},
resolve: {
extensions: ['.ts', '.js']
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
new ExtractTextPlugin('styles.css') // call the ExtractTextPlugin and name our CSS file
]
};
module.exports = config;
if (process.env.NODE_ENV === 'production') {
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin(), // call the uglify plugin
new OptimizeCSSAssets() // call the CSS optimizer (for minification)
);
}
What's really strange is that here, everything in the terminal compiles fine but when I inspect an element, there's no sourcemap:
HOWEVER, if uncomment this line in my webpack.config file:
// { loader: 'style-loader', options: { sourceMap: true } },
and run npm start again, the sourcemaps work correctly!...
...but now the terminal throws an error, which apparently is because you aren't supposed to use style-loader inside of the ExtractTextPlugin, but rather only as a fallback. My app still works in this case, but I don't want that error! How can I enable the SCSS sourcemaps without including style-loader in my SCSS rules?

Related

Webpack doesn't emit css sourcemap (with sourcemap: true)

I can't make my webpack to emit css sourcemap. I've put sourcemap: true everywhere where possible, and no effect, and all the solutions online suggest either this or some other plugin configuration, but I don't have any other plugin, it's super simple webpack.config.js
This is my webpack.config.js:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var path = require("path");
module.exports = {
entry: "./main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
publicPath: "/",
sourceMapFilename: '[file].map'
},
devtool: 'source-map',
module: {
rules: [{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
presets: ["es2015"],
sourceMap: true
}
}
},
{
test: /\.scss$/,
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/',
sourceMap: true,
hmr: process.env.NODE_ENV === 'development',
},
},
{
loader: "css-loader",
options: {
sourceMap: true
}
},
{
loader: "sass-loader",
options: {
sourceMap: true
},
}
]
},
{
test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/,
use: [{
loader: 'url-loader',
options: {
name: 'images/[hash]-[name].[ext]'
}
}]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
sourceMap: true
}),
],
};
I need this source map in dev mode, but only two files get emited main.css and bundle.js.
For those who also struggle with this, the below webpack.config.js is a proper configuration for having style's sourcemap in dev mode. Bundle.js needs to be included when in dev mode, and custom.min.css needs to be added to the HTML document in production mode.
Edit: Unfortunately this can be also wrong. Right now without any change to webpack or node, the sourcemap is not generating :/ sometimes it works, and sometimes it doesn't. There is some bug in webpack, or in some plugins, either way it's a serious bug, but it's webpack so I am not surprised...
Edit 2: Now I see that the problem is only in Firefox, Chrome and Opera have the correct map.
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var path = require("path");
module.exports = {
entry: "./main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
publicPath: "/"
},
module: {
rules: [{
test: /\.js$/,
use: {
loader: "babel-loader",
options: { presets: ["es2015"] }
}
},
{
test: /\.scss$/,
use: [
{
loader: "style-loader" // creates style nodes from JS strings
},
{
loader: "css-loader" ,
options: {
sourceMap: true
}// translates CSS into CommonJS
},
{
loader: "sass-loader",
options: {
sourceMap: true
} // compiles Sass to CSS
}
]
},
{ test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/,
use: [{
loader: 'url-loader',
options: {
name: 'images/[hash]-[name].[ext]'
}
}] }
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '../css/custom.min.css'
})
]
};

AngularJS + webpack hot module replace ignores changes in app.controllers

I have implemented the Webpack HMR to my AngularJS 1.7.2 project.
If I change something in the .js files and save I have the update hot without refresh.
However, everything resides under app.controller or anything else made by AngularJS, is doesn't working.
For example:
module.exports = app => {
console.log(1); // will be hot updated
app.controller("myCtrl", () => console.log(2)); // will not update in case I change the 2 to 3, or something else.
}
This is the webpack.config.js file:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = (env, argv) => {
return {
entry: './src/webpack.entry.js',
output: {
filename: 'bundle.js',
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, './www')
},
plugins: [
// new HtmlWebpackPlugin({
// template: "./src/index.html"
// }),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: path.resolve(__dirname, './www'),
hot: true,
inline: true
},
// devtool: argv.mode == "development" ? 'inline-source-map' : false,
module: {
rules: [
{
test: /\.(html)$/,
exclude: /node_modules/,
use: {
loader: 'html-loader',
options: {
attrs: [':data-src']
}
}
},
{
test: /\.(woff(2)?|ttf|eot|svg|jpg|jpeg|png|jpg|gif)$/,
exclude: /node_modules/,
use: [
{
loader: 'file-loader',
options: {}
}
]
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
'style-loader',
'css-loader',
]
},
// {
// test: /\.scss$/,
// exclude: /node_modules/,
// use: [
// 'sass-loader'
// ]
// }
]
},
optimization: {
minimize: false
}
};
}
And I would like to provide with the webpack.entry.js file too:
// angularjs app first initialization
var app = require('./app/app');
// ionic core css
require('./assets/css/ionic.bundle.css');
// app scripts
require('./app/index')(app);
// screens scripts
require('./screens/index')(app);
// assets
require('./assets/css/custom-both.css');
// NOTE: without this, it fully reloads the webpage instead of making it hot reload - even when the config sets with hot:true
if (module.hot) {
module.hot.accept();
}

Click to open PDF - You may need an appropriate loader to handle this file type

I'm trying to import a PDF into a .js file in order to have a Click to open pdf into my render.
Importing
import myFile from './assets/files/myfile.pdf';
Rendering
render() {
return (
...
<a href={myFile}>
<span>Click to open PDF</span>
</a>
...
)}
Error
myProject.bundle.js:88481 ./assets/files/myfile.pdf 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
Webpack.config.js
I tried several PDF loader without success, the webpack below uses url-loader.
const path = require('path'),
webpack = require('webpack'),
CleanWebpackPlugin = require('clean-webpack-plugin'),
HtmlWebpackPlugin = require('html-webpack-plugin'),
ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractPlugin = new ExtractTextPlugin({ filename: './assets/css/app.css' });
const config = {
mode: 'production',
// absolute path for project root with the 'src' folder
context: path.resolve(__dirname, 'src'),
entry: ['babel-polyfill', './main.js'],
// entry: {
// // relative path declaration
// app: './main.js'
// },
output: {
// absolute path declaration
path: path.resolve(__dirname, 'dist'),
filename: 'myProject.bundle.js',
publicPath: '/'
},
module: {
rules: [
// ************
// * SEE HERE *
// ************
{ test: /\.pdf$/, use: 'url-loader' },
// babel-loader with 'env' preset
{ test: /\.jsx?$/, include: /src/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ['env', 'es2015', 'react', 'stage-0'] } } },
// html-loader
{ test: /\.html$/, use: ['html-loader'] },
// sass-loader with sourceMap activated
{
test: /\.scss$/,
include: [path.resolve(__dirname, 'src', 'assets', 'scss')],
use: extractPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
],
fallback: 'style-loader'
})
},
// file-loader(for images)
{ test: /\.(jpg|png|gif|svg)$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: './assets/images/' } } ] },
// file-loader(for fonts)
{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: ['file-loader'] },
]
},
plugins: [
// cleaning up only 'dist' folder
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: 'index.html'
}),
// extract-text-webpack-plugin instance
extractPlugin
],
};
module.exports = config;
Note: I'm testing this on localhost if that makes any difference.
SOLUTION
The problem came from the fact that I wasn't restarting the dev server by running npm run startdev after making some changes.
Include it in the file loader, as you do with images:
{ test: /\.(jpg|png|gif|svg|pdf)$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: './assets/images/' } } ] },
Note that I have added |pdf after the SVG declaration. Webpack should then process the file as it does with images.
config.module.rules.push({
test: /\.pdf$/,
use: {
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
},
},
});
// vue.config.js configureWebpack
config.module
.rule('pdf')
.test(/\.pdf$/)
.use('pdf')
.loader('file-loader')
.end();
config.module
.rule('pdf')
.test(/\.pdf$/)
.use('file-loader?name=[path][name].[ext]')
.loader('file-loader')
.end();

Compile scss with webpack for an Angular App

I'm using webpack 3 for my angular app. I have some issues with compiling my scss files. Here is full webpack config file:
const path = require('path')
const autoprefixer = require('autoprefixer')
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const config = {
context: __dirname + '/src',
entry: {
app: './index.js',
vendor: [
'angular',
'angular-animate',
'angular-bootstrap',
'angular-route',
'animate',
'bootstrap',
'bootstrap-filestyle',
'jquery',
'ng-file-upload',
'ng-parallax'
]
},
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'app'),
publicPath: path.join(__dirname, 'app')
},
resolve: {
extensions: ['.js', '.jsx', '.scss']
},
module: {
loaders: [
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader',
'css?minimize!postcss!sass')
},
{
test: /\.(eot|woff|woff2|ttf|svg)(\?\S*)?$/,
loader: 'file?name=fonts/[name].[ext]'
},
{
test: /\.(jpg|jpeg|gif|png|svg)$/,
loader: 'file?name=images/[name].[ext]'
}
],
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
},
{
test: /\.svg$/,
loader: 'url-loader'
},
{
test: /\.php$/,
loader: 'file-loader?name=[name].[ext]'
},
{
test: /\.zip$/,
loader: 'file-loader?name=[name].[ext]'
},
{
test: /(\.png|\.jpg|\.gif)$/,
loader: 'file-loader?name=[path][name].[ext]'
}
]
},
plugins: [
new ExtractTextPlugin('./bundle.css'),
new CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.bundle.js'
}),
new UglifyJSPlugin({})
// new ExtractTextPlugin({
// filename: '[name].min.css'
// })
]
}
module.exports = config
After running webpack i've got this error:
ERROR in ./assets/sass/main.scss
Module parse failed: /home/git/project/src/public/src/assets/sass/main.scss Unexpected token (1:13)
You may need an appropriate loader to handle this file type.
| $header-color: #ffffff;
| $admin-panel-height: 40px;
|
# ./index.js 3:0-34
Also i tried to use this loader: https://github.com/webpack-contrib/sass-loader
After webpack build there no errors appeared, but css file also was not created in /app folder.
file main.scss imports in index.js:
import './assets/sass/main.scss'
Can anyone give me an advice how can i build and watch scss files with webpack 3 ?
You have used some of the loader configs that suppose to be for webpack 1.
That section of the config:
loaders: [
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader',
'css?minimize!postcss!sass')
},
{
test: /\.(eot|woff|woff2|ttf|svg)(\?\S*)?$/,
loader: 'file?name=fonts/[name].[ext]'
},
{
test: /\.(jpg|jpeg|gif|png|svg)$/,
loader: 'file?name=images/[name].[ext]'
}
],
There are breaking changes when you move to Webpack 2 (or 3).
One of them was module.loaders => module.rules.
You will need to convert that section to the new structure.
In addition, ExtractTextPlugin changes it config style as well, please read it README.

How to uglify javascript using webpack

Here is my webpack config:
var path = require('path');
var webpack = require('webpack');
var CompressionPlugin = require("compression-webpack-plugin");
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './index.js',
output: {
path: __dirname,
filename: 'public_html/assets/js/bundle.js'
},
resolveLoader: {
modules: ["node_modules"]
},
module: {
rules: [
{
enforce: 'pre',
test: /\.tag$/,
exclude: /node_modules/,
loader: 'riotjs-loader',
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [
'es2015',
],
"babelrc": false
}
},
{
test: /\.css$/,
use: [
{
loader: "css-loader",
options: {
modules: false
}
}
]
}
]
},
plugins: [
new webpack.LoaderOptionsPlugin({debug: true}),
new UglifyJSPlugin(),
new webpack.ProvidePlugin({
riot: 'riot'
}),
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.(js|html)$/,
threshold: 10240,
minRatio: 0.8
})
]
}
This completely uglifies the bundle js but the problem is global variables references are lost. I mean the properties of global object DataMixin are lost.
For example, inside index.html I have:
<script>
window.onload = function () {
DataMixin.get_data_page_load(); //DataMixin defined in other js file
};
</script>
After uglifying, I get error:
Cannot read property 'get_data_page_load' of undefined
How do I fix this? I am using webpack 2.
For webpack 2 you don't need to install the external uglify plugin.
In your webpack config replace this new UglifyJSPlugin(), with the following:
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
minimize: true,
compressor: {
warnings: false,
},
}),
Removing presets fixed it but also had to remove arrow functions from my code.
Here is the solution I found: http://www.rootscopeblog.com/blog/post?=uglifying-riotjs-files-using-webpack-2

Categories