Following is my folder structure & Files for React project which is working fine but I am unable to add CSS through SCSS via Webpack using extract-text-webpack-plugin. Let me know what I am doing wrong with the configuration.
Folder Structure -
Webpack.config.js File -
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
template: './app/index.html',
filename: 'index.html',
inject: 'body'
});
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ExtractTextPluginConfig = new ExtractTextPlugin('main.css',{
allChunks: true
});
module.exports = {
entry: './app/app.jsx',
output: {
path: path.resolve('dist'),
filename: 'bundle.js'
},
devtool: 'source-map',
module: {
loaders: [
{test: /.js$/, loader: 'babel-loader', exclude: /node_modules/},
{test: /.jsx$/, loader: 'babel-loader', exclude: /node_modules/},
{test: /\.scss$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader")}
]
},
plugins: [HtmlWebpackPluginConfig, ExtractTextPluginConfig]
};
Package.json -
{
"name": "reactyarn",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --hot"
},
"devDependencies": {
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^3.0.0",
"html-webpack-plugin": "^2.29.0",
"sass-loader": "^6.0.6",
"style-loader": "^0.18.2",
"webpack": "^3.3.0",
"webpack-dev-server": "^2.5.1"
},
"dependencies": {
"path": "^0.12.7",
"react": "^15.6.1",
"react-dom": "^15.6.1"
}
}
FYI -
I am not getting any JS error in console, so I believe its only the configuration which is not working.
You appear to be missing one of the loaders (sass-loader) and setting them up in your modules incorrectly.
Try the example below:
module.exports = {
entry: './app/app.jsx',
output: {
path: path.resolve('dist'),
filename: 'bundle.js'
},
devtool: 'source-map',
module: {
loaders: [
{test: /.js$/, loader: 'babel-loader', exclude: /node_modules/},
{test: /.jsx$/, loader: 'babel-loader', exclude: /node_modules/},
{test: /\.scss$/, loaders: ['style-loader', 'css-loader', 'sass-loader'] // <-- this is new
]
},
sassLoader: {
includePaths: [path.resolve(__dirname, 'relative/path/to/scss')]
}, // <--- this is new
plugins: [HtmlWebpackPluginConfig, ExtractTextPluginConfig]
};
By using ExtractPlugin.extract you're referencing the means to do this in Webpack 2 (using rules and use) but your Webpack config file appears to be geared toward Webpack 1.
Related
I've made bundle.js and bundle.css to use in my web app,
My package.json looks like this:
"dependencies": {
"bootstrap": "^4.5.3",
"jquery": "^3.5.1",
"popper.js": "^1.16.1"
},
"devDependencies": {
"#babel/core": "^7.12.10",
"#babel/plugin-proposal-object-rest-spread": "^7.12.1",
"#babel/preset-env": "^7.12.11",
"babel-loader": "^8.2.2",
"css-loader": "^5.0.1",
"file-loader": "^6.2.0",
"mini-css-extract-plugin": "^1.3.3",
"node-sass": "^5.0.0",
"sass-loader": "^10.1.0",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^5.11.0",
"webpack-cli": "^4.2.0"
},
My webpack.config.js:
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = (env, argv) => {
return {
//Define entry point
entry: ['./src/index.js', './src/css/index.scss'],
//Define output point
output: {
path: path.resolve(__dirname, 'wwwroot/dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.s[c|a]ss$/,
include: path.resolve(__dirname, 'src'),
use: [
'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env"],
plugins: ['#babel/plugin-proposal-object-rest-spread']
}
},
]
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
new MiniCssExtractPlugin({
filename: 'bundle.css'
})
]
};
};
My src structure is like this:
src
index.js:
import 'jquery';
import 'bootstrap';
import './js/login';
import './js/helpers';
index.scss:
#import 'bootstrap';
#import 'util.scss';
#import 'login.scss';
#import 'site.css';
I am getting this error in console:
Console
bundle.js
Everything else is working fine, i have no problem with javascript, but it bugs me that i don't know how to fix this error.
PS:
I am new to web development in general, started using webpack yesterday, the idea was to use only bundle.js and bundle.css in my html without adding jquery and bootstrap tags for them separately
Try to set the option esModule to false for MiniCssExtractPlugin
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false,
},
},
'css-loader',
'sass-loader'
]
Don't use 'style-loader' along with mini-css-extract-plugin, modify your rule to match the below:
{
test: /\.s[c|a]ss$/,
include: path.resolve(__dirname, 'src'),
use: [
//'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
You can find more details here: https://github.com/webpack-contrib/mini-css-extract-plugin/issues/613
Similar to #Dina's answer but without MiniCssExtractPlugin :
use: [
{
loader: "style-loader",
options: {
esModule: false,
},
},
"css-loader",
"sass-loader",
]
I've created webpack config to my VueJS project. I want to separate styles from javascript code. I've used mini-css-extract-plugin but finally I receive only bundle.js file. What's wrong with this config and where is a mistake? Is there any missing loader. My config is below:
import path from 'path';
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import VueLoaderPlugin from 'vue-loader/lib/plugin';
import UglifyJsPlugin from 'uglifyjs-webpack-plugin';
import CleanWebpackPlugin from 'clean-webpack-plugin';
const devMode = process.env.NODE_ENV !== 'production';
const prodPlugins = [
new UglifyJsPlugin(),
new MiniCssExtractPlugin({
filename: "css/style.css"
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true
})
];
const basicPlugins = [
new CleanWebpackPlugin('dist'),
new VueLoaderPlugin()
];
const config = {
entry: {
bundle: './src/main.js'
},
output: {
filename: 'js/[name].js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' },
{
test: /\.css$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader'
]
},
{ test: /\.(scss|sass)$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'vue-style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
js: 'babel-loader',
}
}
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
plugins: !process.env.NODE_ENV || !devMode ? basicPlugins : basicPlugins.concat(prodPlugins)
};
module.exports = config;
My file package.json
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"watch": "webpack --watch --mode development --hot",
"dev": "webpack-dev-server --mode development --progress --hot --open",
"build": "webpack --mode production --progress"
},
"author": "",
"license": "MIT",
"devDependencies": {
"autoprefixer-loader": "^3.2.0",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-register": "^6.26.0",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^0.28.11",
"cssnano": "^3.10.0",
"eslint": "^4.19.1",
"eslint-watch": "^3.1.4",
"mini-css-extract-plugin": "^0.4.0",
"node-sass": "^4.9.0",
"optimize-css-assets-webpack-plugin": "^4.0.1",
"sass-loader": "^7.0.1",
"sass-resources-loader": "^1.3.3",
"style-loader": "^0.21.0",
"uglifyjs-webpack-plugin": "^1.2.5",
"vue-loader": "^15.0.10",
"vue-style-loader": "^4.1.0",
"vue-template-compiler": "^2.5.16",
"webpack": "^4.8.3",
"webpack-cli": "^2.1.3",
"webpack-dev-server": "^3.1.4"
},
"dependencies": {
"axios": "^0.18.0",
"material-design-icons": "^3.0.1",
"vue": "^2.5.16",
"vue-router": "^3.0.1",
"vuetify": "^1.0.17"
}
}
Note that any imported file is subject to tree shaking. This means if you use something like css-loader in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode.
Blockquote
in your package.json, add:
"sideEffects": [
'.scss'
]
In Webpack 4, you can add "sideEffects: true" to the loader to prevent the compiler from dropping the CSS file output by MiniCssExtractPlugin.loader (See Webpack Tree Shaking Guide). This works with Angular + TypeScript (using "module:" "ES2015" in tsconfig). I imagine it would work for your set up as well.
{
test: /\.scss$/,
include: [
helpers.root('src', 'assets')
],
sideEffects: true,
use: [
MiniCssExtractPlugin.loader,
{loader: 'css-loader'},
{loader: 'resolve-url-loader'}, // Angular only
{loader: 'sass-loader'},
]
},
Check that you have set the NODE_ENV environment variable.
In your config the extracting of css to separate files (MiniCssExtractPlugin) will only occur when building for production, in other words, when NODE_ENV is set to 'production'. When building for development style-loader is being used which will inject the css within a tag.
I'm using a pretty new JS dev environment (here for details) and according to this documentation React is pretty easy to implement into other JS frameworks.
In my index.js file which is at the root of my directory, I have the following code:
import React, { Component } from "react";
import ReactDOM from "react-dom";
function Button() {
return <button id="btn">Say Hello</button>;
}
ReactDOM.render(
<Button />,
document.getElementById('container'),
function() {
$('#btn').click(function() {
alert('Hello!');
});
}
);
and when i go to run fly server I get the following error:
ERROR in ./index.js Module parse failed: Unexpected token (8:9) You
may need an appropriate loader to handle this file type. | | function
Button() { | return Say Hello; | } |
Here is my package.json file:
{
"name": "fly-example",
"version": "1.0.0",
"description": "fly example app",
"main": "index.js",
"dependencies": {
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"css-loader": "^0.28.11",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"style-loader": "^0.21.0",
"webpack": "^4.6.0",
"webpack-cli": "^2.0.14",
"webpack-dev-server": "^3.1.3"
},
"scripts": {
"test": "mocha"
},
"repository": {
"type": "git",
"url": "none"
},
"keywords": [
"fly",
"app"
],
and my webpack.config:
const path = require("path");
const webpack = require("webpack");
const bundlePath = path.resolve(__dirname, "dist/");
module.exports = {
entry: "./index.js",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
options: { presets: ['env'] }
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},
resolve: { extensions: ['*', '.js', '.jsx'] },
output: {
publicPath: bundlePath,
filename: "bundle.js"
},
devServer: {
contentBase: path.join(__dirname,'public'),
port: 3000,
publicPath: "http://localhost:3000/dist"
},
plugins: [ new webpack.HotModuleReplacementPlugin() ]
};
.babelrc file:
{
"presets": ["env", "react"]
}
Still fairly new to React, but I love building apps in it, but I really want to learn how to integrate it into other JS frameworks so I can use it more broadly.
Is there something I'm missing in the package.json file or the webpack.config? I have done quite a bit of looking around but haven't found much.
Thanks for your help in advance!
Try specifying babel-loader under use.loader. See below:
const path = require("path");
const webpack = require("webpack");
const bundlePath = path.resolve(__dirname, "dist/");
module.exports = {
entry: "./index.js",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
}
options: { presets: ['env'] }
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},
resolve: { extensions: ['*', '.js', '.jsx'] },
output: {
publicPath: bundlePath,
filename: "bundle.js"
},
devServer: {
contentBase: path.join(__dirname,'public'),
port: 3000,
publicPath: "http://localhost:3000/dist"
},
plugins: [ new webpack.HotModuleReplacementPlugin() ]
};
Instead of writing the webpack configuration by yourself, I'd recommend using create-react-app, it is simpler. Also make sure you import jquery.
Try and let me know if this works !
I'm using babel-core ^5.4.7 and babel-loader ^5.1.2 with webpack. I'm also using mobx ^3.3.1 and mobx-react ^4.3.3 version. Now my problem is when I'm trying to build my project by hitting npm run watch:webpack it throws unknown option: package.json.presets
here my package.json
"devDependencies": {
"babel-core": "^5.4.7",
"babel-eslint": "^3.1.9",
"babel-loader": "^5.1.2",
"babel-plugin-react-transform": "^1.1.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-1": "^6.24.1",
....
"webpack": "^1.9.6",
"webpack-dev-middleware": "^1.2.0",
"webpack-hot-middleware": "^2.0.0"
},
"dependencies": {
"mobx": "^3.3.1",
"mobx-react": "^4.3.3",
"prop-types": "^15.6.0",
"react": "16.0.0",
"react-dnd-html5-backend": "^2.5.4",
"react-dom": "16.0.0",
....
},
"babel": {
"presets": ["es2015", "react", "stage-1"],
"plugins": ["transform-decorators-legacy"]
}
and here my webpack.config.dev.js
var path = require('path');
var webpack = require('webpack');
var src = path.join(__dirname, 'engine');
var dest = path.join(__dirname, 'assets/builder');
module.exports = {
devtool: 'cheap-module-source-map',
entry: [
src + '/index.jsx'
],
output: {
path: dest,
filename: 'bundle.js',
publicPath: '/assets/builder/'
},
resolve: {
extensions: ['', '.json', '.js', '.jsx'],
modulesDirectories: ['node_modules', 'bower_components', src]
},
plugins: [
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
'process.env': {
'FREE': process.argv.indexOf('--free') !== -1 ? JSON.stringify("free"): JSON.stringify("pro")
}
}),
],
module: {
loaders: [
{test: /\.jsx?$/, loaders: ['babel?stage=0'], include: src},
{test: /\.js?$/, loaders: ['babel?stage=0'], include: src},
{test: /\.less$/, loader: 'style!css!less'},
{test: /\.css$/, loader: 'style!css'},
{test: /\.jpe?g$|\.gif$|\.png$/, loader: "url-loader"},
{test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff"},
{test: /\.ttf?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=font/ttf"},
{test: /\.(eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader"}
]
}
};
Here my mobx store with decorator #observable
export default class ElementStore {
#observable path = null,
#observable visible = false,
#observable list = sortElementsByName(elements),
handle(handlerName, {path}) {
switch (handlerName) {
case HIDE_ELEMENTS:
// do something..
break;
case SHOW_ELEMENTS:
// do something..
break;
}
}
}
And the error message is
ERROR in ./engine/index.jsx
Module build failed: ReferenceError: [BABEL] /Users/iftekhersunny/Documents/code/quix/src/lib_quix/engine/index.jsx: Unknown option: /Users/iftekhersunny/Documents/code/quix/src/lib_quix/package.json.presets
Why the presets is the unknown option???
presets is a config flag for Babel 6.x, and you're trying to use it with Babel 5. Babel 5 is super old, just use Babel 6.
Firstly remove babel option from package.json file and create a .babelrc file in root of the project.
.babelrc file
{
"presets": ["es2015", "react","stage-1"],
"plugins": [
"transform-decorators-legacy"
]
}
hope it works
I've just noticed that when I inspect any element in Chrome or Firefox dev tools the attributes assigned to that element always point to same line, which is either the end of the source file (when I open static index.html) or, if I run my app by webpack-dev-server, beginning of the file.
My webpack.config.js:
var webpack = require('webpack');
var autoprefixer = require('autoprefixer');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
devtool: 'source-map',
module: {
loaders: [
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
loader: ['css-loader?sourceMap', 'postcss-loader', 'sass-loader?sourceMap']
})
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
loader: ['css-loader?sourceMap']
})
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
},
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./app/static/js/app.js'
],
output: {
filename: './app/dist/js/bundle.js',
//publicPath: './', // adding back will break webpack-dev-server!
},
watch: false,
plugins: [
new ExtractTextPlugin('./app/dist/css/main.css'),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
host: 'localhost',
//hot: true, // adding back will break webpack-dev-server!
port: 8080,
inline: true,
stats: '_errors-only',
contentBase: './'
}
};
My package.json:
{
"name": "new-admin",
"version": "1.0.0",
"description": "",
"main": "0.44132ff81411f73136a6.hot-update.js",
"dependencies": {
"autoprefixer": "^6.5.3",
"bootstrap-loader": "^2.0.0-beta.15",
"bootstrap": "^3.3.7",
"css-loader": "^0.26.0",
"file-loader": "^0.9.0",
"jquery": "^3.1.1",
"postcss": "^5.2.5",
"postcss-loader": "^1.1.1",
"sass-loader": "^4.0.2",
"url-loader": "^0.5.7",
"webpack-dev-server": "^1.16.2",
"webpack-uglify-js-plugin": "^1.1.9"
},
"devDependencies": {
"postcss-load-config": "^1.0.0",
"postcss-loader": "^1.1.1"
},
"scripts": {},
"author": "",
"license": "ISC"
}