Scss extraction with webpack - javascript

I am trying to use ExtractTextPlugin to extract and convert my scss to css and move it to src folder along with client.min.js , but currently getting the following issue when building webpack.config.js file:
ERROR in ./scss/styles.js
Module not found: Error: Cannot resolve module 'main.scss' in C:\Users\ajoku\Desktop\Web Projects\learn2node\http\scss
# ./scss/styles.js 3:0-20
My webpack.config.js file :
"use strict";
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
let ExtractTextPlugin = require('extract-text-webpack-plugin');
let extractSCSS = new ExtractTextPlugin('./scss/main.scss',{allChunks: true});
module.exports = {
context: path.join(__dirname, "http"),
devtool: debug ? "inline-sourcemap" : null,
entry: {
js:"./react/client.js",
scss: "./scss/styles.js",},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy']
}},
{test: /\.scss$/i, loader: ExtractTextPlugin.extract('css!scss')},
]
},
output: {
path: "./src/",
filename: "client.min.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
plugins: [
new ExtractTextPlugin('main.css', {
allChunks: true
})
]
};
My styles.js file
require("main.scss");
My scss files are located in http/scss along with styles.js file
What could be causing the problem?Thank you for your time.

This is possible with sass-loader and extract-text-webpack-plugin
webpack.config
module.exports = {
module: {
{
test: /\.scss$/,
include: path.resolve(__dirname, 'http/scss'),
loader: ExtractTextPlugin.extract('style', 'css?modules&localIdentName=[name]-[local]!autoprefixer!sass')
}
}
plugins: [
new ExtractTextPlugin('[name]-[hash].min.css')
]
}
package.json
"devDependencies": {
"autoprefixer-loader": "^3.1.0",
"css-loader": "^0.23.0",
"node-sass": "^3.4.2",
"sass-loader": "^3.1.2",
"extract-text-webpack-plugin": "^0.9.1",
"style-loader": "^0.13.0"
}

Related

Why PWA can be installed only in dev mode?

I'm trying to integrate PWA in my react project, when i run using webpack-dev-server i can see the PWA app that i can install in my computer, but when i build the project with webpack and try to run it, i can't do it anymore
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const { styles } = require("#ckeditor/ckeditor5-dev-utils");
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const BUILD_DIR = path.resolve(__dirname, "public");
const APP_DIR = path.resolve(__dirname, "src");
const envs = require('./config/envs').getEnv;
const plugins = require('./webpack-plugins');
module.exports = (env) => {
console.log("OUTPUT: env", env)
const config = envs(env.NODE_ENV);
const mode = env.production ? 'production' : 'development';
return {
mode,
entry: `${APP_DIR}/index.js`,
output: {
filename: "js/bundle.js",
path: BUILD_DIR,
publicPath: "/"
},
node: {
net: "empty",
tls: "empty",
dns: "empty",
fs: "empty"
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
exclude: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
"babel-loader",
{
loader: "eslint-loader",
options: {
failOnError: true,
emitError: true,
emitWarning: true
}
}
]
},
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: "graphql-tag/loader"
},
{
test: /\.(jpg|png|gif|svg|pdf|ico)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name]-[hash:8].[ext]"
}
}
],
exclude: [
/\.(js|jsx|mjs)$/,
/\.html$/,
/\.json$/,
/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
/ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/
]
},
{
test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
use: ["raw-loader"]
},
{
test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
use: [
{
loader: "style-loader",
options: {
singleton: true
}
},
{
loader: "postcss-loader",
options: styles.getPostCssConfig({
themeImporter: {
themePath: require.resolve("#ckeditor/ckeditor5-theme-lark")
},
minify: true
})
}
]
}
]
},
devServer: {
historyApiFallback: true,
watchContentBase: true,
contentBase: "./public"
},
resolve: {
extensions: [".js"],
alias: {
src: path.resolve(__dirname, "src"),
shared: path.resolve(__dirname, "src", "shared"),
config: path.resolve(__dirname, "config"),
screens: path.resolve(__dirname, "src", "screens"),
package: path.resolve(__dirname, "package.json")
}
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new MomentLocalesPlugin({
localesToKeep: ['es-us', 'fr', 'es'],
}),
new webpack.DefinePlugin({
CONFIG: JSON.stringify(config),
}),
plugins.manifest,
plugins.sw
]
}
};
the Scripts on package.json
"build:local": "webpack --env.NODE_ENV=local --env.production --progress",
"start": "node server.js",
"dev": "webpack-dev-server --inline --watch --host 0.0.0.0 --env.NODE_ENV=local --env.development --progress"
Webpack packages used :
"webpack": "4.19.1",
"webpack-cli": "^2.0.15",
"webpack-dev-server": "^3.1.3",
"webpack-manifest-plugin": "^2.2.0"
PS: I tried both --env.production and --env.development in the build but neither worked
Any lead would be appreciated !
Making the app HTTPS fixed it, many thanks #Mathias

keep folder structure of source files in webpack

I have one .html page(index.html) and one entry point(index.js) and I want that dist folder keeps folder structure of my source files.
./webpack.config.js
./src/index/index.html
./src/index/index.js
./src/index/script1.js
./src/index/style1.scss
./src/assets/imgs/bg.jpg
I manage to write a webpack config file that works as I want but only when I use 'npm run build' and webpack give me a final build version.'
if I use 'npm run dev' then dev server opens a page that shows directories list.
How can I solve my problem?
this is my webpack.config.js
const webpack = require("webpack");
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
optimization: {
minimize: false
},
entry: {'index': './src/index/index.js'},
output: {
filename: '[name]/[name].js',
path: path.resolve(__dirname, './dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development',
reloadAll: true,
},
},
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development',
reloadAll: true,
},
},
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.html$/,
exclude: /node_modules/,
use: [
{
loader: 'html-loader',
options: {
minimize: false,
publicPath: './'
}
}
]
},
{
test: /\.(png|jpg|jpeg)$/,
exclude: /node_modules/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/imgs/',
publicPath: '../assets/imgs/'
}
}
]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name]/[name].css",
chunkFilename: '[id].css',
ignoreOrder: false
}),
new HtmlWebpackPlugin({
filename: 'index/index.html',
inject: true,
chunks: ['index'],
template: './src/index/index.html'
}),
new CleanWebpackPlugin()
]
};
package.json :
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
I want dist folder to be like this :
./dist/index/index.html
./dist/index/index.js --> final .js bundle
./dist/index/index.css --> final .css bundle
./dist/assets/imgs/bg.jpg

Exclude some css files in webpack

I'm facing a problem with webpack. My project has the following structure.
Folder structure:
src
js
app.js // For importing app.scss file
vendor.js // For importing vendor.scss file
scss
app.scss // Our custom styles
vendor.scss // Require all vendor styles from node_modules
package.json
postcss.config.js
webpack.config.js
Inside scss folder there are 2 files app.scss & vendor.scss. app.scss file contains all our custom styles, vendor.scss file contains all vendor styles such as bootstrap library styles.
After webpack command:
npm run dev
Webpack import these scss files through JavaScript files and add vendor prefixes via postcss-loader and output on a dist
folder.
But I don't want to add vendor prefixes on vendor.scss file because the vendor library already has vendor prefixes. So is there a way to exclude vendor.scss file from postcss-loader.
Full Code:
src/js/app.js:
import '../scss/app.scss'
src/js/vendor.js:
import '../scss/vendor.scss'
src/scss/app.scss:
// Our custom styles
.app {
display: flex;
}
src/scss/vendor.scss:
// Vendor Styles
.container {
display: flex;
}
#import '~bootstrap/scss/bootstrap';
package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development --progress true --colors"
},
"author": "",
"license": "MIT",
"dependencies": {
"bootstrap": "^4.2.1"
},
"devDependencies": {
"#babel/core": "^7.2.2",
"#babel/preset-env": "^7.3.1",
"autoprefixer": "^9.4.6",
"babel-loader": "^8.0.5",
"css-loader": "^2.1.0",
"filemanager-webpack-plugin": "^2.0.5",
"mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.11.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^7.1.0",
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1"
}
}
postcss.config.js:
module.exports={
plugins: [
require('autoprefixer')({
'browsers': [
'>= 1%',
'last 1 major version',
'not dead',
'Chrome >= 45',
'Firefox >= 38',
'Edge >= 12',
'Explorer >= 10',
'iOS >= 9',
'Safari >= 9',
'Android >= 4.4',
'Opera >= 30'
],
cascade: true
})
]
};
webpack.config.js:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
module.exports = function() {
return ({
entry: {
'vendor': './src/js/vendor.js',
'app': './src/js/app.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[chunkhash].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}, {
loader: 'css-loader',
}, // translates CSS into CommonJS
{
loader: 'postcss-loader',
}, // Add vendor prefixes on build css file
{
loader: 'sass-loader',
} // compiles Sass to CSS
]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css'
}),
// Before Build
new FileManagerPlugin({
onStart: {
delete: [
'dist',
],
}
}),
]
});
};
Zip file.
So you want vendor prefixes don't add on Webpack generated vendor.css file.
Remember Webpack parse loader array on reverse order. You could add exclude property on the object of postcss-loader with the regular expression.
webpack.config.js:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
module.exports = function() {
return ({
entry: {
'vendor': './src/js/vendor.js',
'app': './src/js/app.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[chunkhash].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.s(c|a)ss$/,
use: {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},// Take scss file and split into a separate css file
},
{
test: /\.s(c|a)ss$/,
use: {
loader: 'css-loader',
},// Interprets scss #import and url() like import/require()
},
{
test: /\.s(c|a)ss$/,
exclude: [/vendor/],
use: {
loader: 'postcss-loader',
},
}, // PostCSS turns your SCSS file into a JS object & converts that object back to a SCSS file
{
test: /\.s(c|a)ss$/,
use: {
loader: 'sass-loader',
},// look for scss file through sass-loader, compile scss into css code
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css'
}),
// Before Build
new FileManagerPlugin({
onStart: {
delete: [
'dist',
],
}
}),
]
});
};

nyc with webpack 4 using .tmp folder

I am currently using:
"mocha": "^5.2.0"
"mocha-webpack": "^2.0.0-beta.0"
"webpack": "^4.19.1"
"nyc": "^13.0.1"
and for some reason, I'm getting weird source files.
.tmp/mocha-webpack/1537879911832/webpack:/src
| 61.18 | 29.63 | 64.29 | 61.18 | |
db.js
I'm wondering how this is generated because exclude doesn't work
"nyc": {
"exclude": [
"./tmp/**/*"
],
}
Here's my webpack file
var nodeExternals = require("webpack-node-externals")
const path = require("path")
const webpack = require("webpack")
const webpackConfig = {
mode: "none",
context: path.resolve(__dirname),
resolve: {
extensions: [".js"],
alias: {
"#": path.join(__dirname, "../src"),
}
},
output: {
// use absolute paths in sourcemaps (important for debugging via IDE)
devtoolModuleFilenameTemplate: "[absolute-resource-path]",
devtoolFallbackModuleFilenameTemplate: "[absolute-resource-path]?[hash]"
},
devtool: "inline-cheap-module-source-map",
plugins: [
new webpack.NamedModulesPlugin()
],
target: "node", // webpack should compile node compatible code
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
}
module.exports = webpackConfig
I got it working by reading this manual: https://github.com/vuejs/vue-test-utils-mocha-webpack-example
The main trick was to install babel-plugin-istanbul and update .babelrc file:
"env": {
"test": {
"plugins": ["istanbul"]
}
}
And package.json looks like:
"nyc": {
"exclude": [
"**/tests/**/*.js",
".tmp/**/*.js",
"webpack.config.js"
]
}
And the webpack.config.js looks like:
var path = require('path')
var webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: './src/main.js',
output: {
// use absolute paths in sourcemaps (important for debugging via IDE)
devtoolModuleFilenameTemplate: '[absolute-resource-path]',
devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]',
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': path.resolve(__dirname, 'src')
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
devServer: {
historyApiFallback: true,
noInfo: true
},
performance: {
hints: false
},
devtool: 'inline-cheap-module-source-map',
externals: ["fs", nodeExternals()],
mode: 'development',
plugins: [
new webpack.NamedModulesPlugin()
]
}

Webpack + React16 + Javascript ES6 "Unexpected token" error

I know this question was asked about thousand times, but I didn't find any solution that works. I'm still getting the same error. Here are my config files:
package.json:
{
"scripts": {
"start": "webpack-dev-server",
"build": "webpack"
},
"dependencies": {
"jquery": "^3.2.1",
"react": "^16.1.1",
"react-dom": "^16.1.1"
},
"devDependencies": {
"babel": "^6.23.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"clean-webpack-plugin": "^0.1.17",
"css-loader": "^0.28.7",
"html-webpack-plugin": "^2.30.1",
"style-loader": "^0.19.0",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.4"
}
}
webpack.config.js:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './src/app/app.jsx',
devtool: 'source-map',
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
],
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: "babel-loader",
query:
{
presets: ['es2015', 'react']
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/app/index.html'
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.bundle.js'
}
};
app.jsx:
import React from "react"
React.render(<h1>hello world</h1>, document.getElementById("root-component"));
Webpack throws the following error:
ERROR in ./src/app/app.jsx
Module parse failed: Unexpected token (3:13)
You may need an appropriate loader to handle this file type.
| import React from "react"
|
| React.render(<h1>hello world</h1>, document.getElementById("root-component"));
I tried multiple solutions (like adding .babelrc file with presets), nothing works. Any help?
Your webpack.config.js is incorrect as per webpack v3.
You need to add another entry into the rules array just like you are doing for loading CSS.
Moreover query should be renamed options.
See Webpack Documentation for more info on migrating from v2 to v3
The fixed webpack.config.js is as follows:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './src/app/app.jsx',
devtool: 'source-map',
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: ['es2015', 'react']
}
}
]
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/app/index.html'
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.bundle.js'
}
};
Before:
ERROR in ./src/app/app.jsx
Module parse failed: Unexpected token (3:13)
Ater (bundle correctly created):
app.bundle.js 424 kB 0 [emitted] [big] main
app.bundle.js.map 499 kB 0 [emitted] main

Categories