I'm trying to introduce Sass-loader to an existing project so as to be able to use Sass in my React components. I've set this up successfully before in my own boiler plates and had no issues but for some reason with the current configuration it doesn't seem to play. It doesn't give any errors but rather doesn't do anything with my .scss file i'm trying to import.
I can see that there is some loaders in the cssLoaders config for Webpack which could be the culprit but I am only targeting .scss/ .sass files with the rule
test: /\.s(a|c)ss$/
so I wouldn't have thought this would affect it at all.
I have webpack setup with a common file and one for development. Here are both those files:
webpack.common.js
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ErrorOverlayPlugin = require('error-overlay-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
require('babel-polyfill');
const Dotenv = require('dotenv-webpack');
module.exports = {
entry: {
main: ['babel-polyfill', './src/index.js']
},
output: {
filename: '[name].[hash].js',
path: path.resolve('./dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: ['node_modules'],
use: [{ loader: 'babel-loader' }]
},
{
test: /\.s(a|c)ss$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
outputPath: 'images/'
}
}
]
},
{
test: /\.(woff(2)?|ttf|eot|otf)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
}
]
},
plugins: [
new ErrorOverlayPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebPackPlugin({
template: 'index.html'
}),
new Dotenv(),
new CleanWebpackPlugin(['dist'])
]
};
And here is webpack.dev.js
const path = require('path');
const webpack = require('webpack');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const paths = require('../paths');
module.exports = require('./webpack.config.base')({
bail: false,
devtool: 'cheap-module-eval-source-map',
stats: 'errors-only',
performance: {
hints: false
},
entry: {
main: [
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appPolyfillsJs,
require.resolve('react-error-overlay'),
paths.appIndexJs
]
},
output: {
pathinfo: true,
filename: 'static/js/[name].js',
chunkFilename: 'static/js/[name].chunk.js',
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath)
},
// Load the CSS in a style tag in development
cssLoaders: [
{
loader: require.resolve('style-loader'),
options: {
sourceMap: true
}
},
{
loader: require.resolve('css-loader'),
options: {
modules: false,
sourceMap: true,
importLoaders: 1
}
},
{
loader: require.resolve('postcss-loader'),
options: { sourceMap: true }
}
],
babelQuery: {
cacheDirectory: true
},
plugins: [].concat([
new ProgressBarPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/,
failOnError: true
})
])
});
The part that I have added to the configuration is in webpack.common:
{
test: /\.s(a|c)ss$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
I then just import it in the module like so:
import React, { PureComponent } from 'react';
import './test.scss';
...
Can anyone spot why the configuration is wrong?
The sass-loader requires node-sass and webpack as peerDependency.
Make sure node-sass is installed and edit the loader webpack.dev.js like so:
{
loader: "sass-loader",
options: {
includePaths: ["absolute/path/a", "absolute/path/b"]
}
}
Related
I am trying to use compute machine provided by the cortexjs. https://cortexjs.io/compute-engine
I saved this dependency using
npm i #cortex-js/compute-engine
After I ran npm start, I am getting this error:
ERROR in ./node_modules/#cortex-js/compute-engine/dist/compute-engine.min.js 2:1360
Module parse failed: Unexpected token (2:1360)
You may need an appropriate loader to handle this file type.
Following is my webpack file:
var webpack = require('webpack');
const HtmlWebPackPlugin = require("html-webpack-plugin");
var path = require('path');
module.exports = {
// output: {
// path: path.resolve(__dirname, 'dist'),
// filename: 'main.js',
// publicPath: '/'
// },
mode : 'production',
devServer: {
historyApiFallback: true,
},
devtool: "source-map",
module: {
rules: [
{
test: /\.(png|jpg|woff|woff2|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
{
test: /\.css$/,
loader: 'style-loader'
},
{
test: /\.css$/,
loader: 'css-loader',
options: {
import: true,
},
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
Please can someone suggest which loader should I add to webpack.config file to make this work.
I have webpack set up to process my single file Vue components, but it seems to ignore the <style> block. Here is my full config file:
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const webpack = require('webpack');
const path = require('path');
module.exports = {
watch: true,
mode: 'development',
entry: path.resolve(__dirname + '/src/webpack-entry.js'),
output: {
path: path.resolve(__dirname + '/assets/'),
filename: 'vue.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
{ loader: 'css-loader', options: { sourceMap: true } },
{
loader: 'sass-loader',
options: {
sourceMap: true,
additionalData: `
#import "./src/scss/_variables.scss";
`
}
}
]
}
]
},
optimization: {
minimize: false
},
plugins: [
new VueLoaderPlugin()
]
};
The generated .js files work fine. They just don't have the scoped style. I want to say it's a webpack configuration problem as I'm not super versed in webpack configuration. Let me know if there is any context that needs to be added or described.
After migrating my CSS files to SCSS, I can see FOUC for my layout elements at the first load (After each reloads of page).
I guess it has something to do with my webpack config so I tried to fix the problem by using mini-css-extract-plugin, but I can still see the problem.
Here is the content of my webpack.config.js file:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const path = require('path');
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,{
loader: "css-loader"
}, {
loader: "sass-loader",
}
]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
{
test: /(\.(?:le|c)ss)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: false,
},
},
{
loader: 'less-loader',
options: {
sourceMap: false,
javascriptEnabled: true,
},
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
},
]
}
]
},
output: {
publicPath: "/"
},
devServer: {
historyApiFallback: true,
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin(),
new MomentLocalesPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.AggressiveMergingPlugin()
],
resolve: {
alias: {
"#ant-design/icons/lib/dist$": path.resolve(__dirname, "./src/icons.js")
}
}
};
The problem wasn't because of Webpack. It was because of me being stupid :)
I imported the CSS file inside of a child component, so when I reload the page, it first shows the layout without any styles and then loads the child component and gives the layout a proper style. So basically, the only thing I did to fix the problem was to import the style in the layout component.
import '../style.scsc'
I have posted my Webpack configs below for a production environment. I am attempting to use background-image: url(../img/chevron-thin-right.svg); in one of my SCSS files but it is being resolved to background-image: url([object Module]) and therefore not working. I am trying to port a purely SCSS and HTML project into a react app being bundled by Webpack so this above approach used to work. Any fixes would be greatly appreciated.
webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const outputDirectory = 'dist';
module.exports = {
entry: './src/client/index.js',
output: {
path: path.join(__dirname, outputDirectory),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
title: 'Production',
template: './public/index.html',
favicon: './public/favicon.ico',
hash: true,
filename: 'index.html'
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.(jpg|png|woff|woff2|eot|ttf)$/,
use: {
loader: 'file-loader?limit=100000&name=images/[name].[ext]'
}
},
{
test: /\.svg$/,
use: [
"babel-loader",
{
loader: "react-svg-loader",
options: {
svgo: {
plugins: [
{
removeTitle: true,
removeComments: true
}
],
floatPrecision: 2
}
}
}
]
}
]
}
};
webpack.prod.js
const merge = require('webpack-merge');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const common = require('./webpack.common.js');
const path = require('path');
const autoprefixer = require('autoprefixer');
module.exports = {};
module.exports = merge(common, {
mode: 'production',
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
}
}
}
},
plugins: [
new CleanWebpackPlugin(['dist']),
new MiniCssExtractPlugin({
filename: '[name].css'
})
],
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: true,
root: path.resolve(__dirname),
},
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer({
'browsers': ['last 2 versions', 'ie >= 10'],
}),
],
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
outputStyle: 'compressed',
sourceMap: true,
includePaths: [
'./src/client/style/scss',
],
},
}
]
}
]
}
});
In case anybody else is looking for an answer I was able to solve it. It was due to not loading the associated SVG through the url-loader. Another problem arose when adding svg back in because my inline SVGs I wanted to use as React components were running into errors as they were now going through the url-loader instead of my react-svg-loader.
Below is the working webpack.common.js and webpack.prod.js stayed the same. The solution was to differentiate my inline and external SVGs by turning all inline extensions from .svg to .inline.svg and adjusting webpack config accordingly
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const outputDirectory = 'dist';
module.exports = {
entry: './src/client/index.js',
output: {
path: path.join(__dirname, outputDirectory),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
title: 'Production',
template: './public/index.html',
favicon: './public/favicon.ico',
hash: true,
filename: 'index.html'
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
exclude: /\.inline.svg$/,
use: {
loader: 'url-loader?limit=1000&name=images/[name].[ext]'
}
},
{
test: /\.inline.svg$/,
use: [
"babel-loader",
{
loader: "react-svg-loader",
options: {
svgo: {
plugins: [
{
removeTitle: true,
removeComments: true
}
],
floatPrecision: 2
}
}
}
]
}
]
}
};
I am using Webpack 2 for building my Angular (4) app. I have it working, but I am trying to figure out how to generate sourcemaps for my scss. In my components I load my scss with styleUrls Adding the options: { sourceMap: true } is not working. I do not want to extract the styles for components, because then the ViewEncapsulation is not working anymore. The .global.scss I use are needed everywhere, so I do extract these and this part works fine. Can someone tell me how to generate my sourcemaps (is it even possible with Angular)? Below is my webpack.config.js .
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const path = require('path');
module.exports = {
devtool: 'inline-source-map',
devServer: {
port: 3000,
contentBase: '/www',
inline: true
},
entry: {
polyfills: './src/polyfills.ts',
vendor: './src/vendor.ts',
app: './src/bootstrap.ts'
},
output: {
path: path.join(__dirname, '../www/'),
filename: '[name].bundle.js'
},
resolve: {
modules: [ path.join(__dirname, 'node_modules') ],
extensions: ['.js', '.ts', '.html']
},
module: {
loaders: [{
test: /\.ts$/,
exclude: /node_modules/,
use: ['awesome-typescript-loader', 'angular2-template-loader']
}, {
test: /\.html$/,
use: 'html-loader'
},{
test: /\.global\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use:[{
loader: 'css-loader',
options: {
sourceMap: true
}
}, {
loader: 'postcss-loader'
}, {
loader: 'sass-loader',
options: {
sourceMap: true,
}
}]
}),
}, {
test: /\.scss$/,
use: [ {
loader: "raw-loader"
}, {
loader: 'resolve-url-loader'
}, {
loader: 'postcss-loader'
}, {
loader: "sass-loader", options: {
sourceMap: true
}
}],
exclude: /node_modules/
}, {
test: /.(png|woff(2)?|eot|ttf|svg)(\?[a-z0-9=\.]+)?$/,
use: 'url-loader'
}]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new ExtractTextPlugin('global-styles.css'),
new webpack.optimize.CommonsChunkPlugin({
name: 'polyfills',
chunks: ['polyfills']
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
chunks: ['vendor']
}),
new webpack.optimize.CommonsChunkPlugin({
name: ['polyfills', 'vendor'].reverse()
})
]
};