Migrating from Webpack v4 to v5. Styling not picked up - javascript

I've migrated Webpack to v5 in my React project and none of my .scss files are picked up when I run it
I've followed this guide on migrating webpack https://webpack.js.org/migrate/5/ updated all plugins and loaders (all of them are MAJOR updates) that I use in development mode, updated configuration file to accommodate new versions but none of the styles are applied
My package.json:
"devDependencies": {
...
"clean-webpack-plugin": "^4.0.0",
"compression-webpack-plugin": "^10.0.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
...
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^6.2.6",
"html-webpack-plugin": "^5.5.0",
...
"mini-css-extract-plugin": "^2.6.1",
...
"node-sass": "^4.14.1",
"optimize-css-assets-webpack-plugin": "^6.0.1",
"react-hot-loader": "^4.13.0",
"sass-loader": "^13.1.0",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.6",
"ts-loader": "^9.4.1",
"webpack": "^5.74.0",
"webpack-bundle-analyzer": "^4.6.1",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"
}
"sideEffects": [
"*.css",
"*.scss"
]
}
My webpack.config.json:
module.exports = {
mode: 'development',
entry: './src/index.tsx',
output: {
publicPath: '/',
path: outPath,
filename: 'bundle.js',
globalObject: 'this'
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: [
/(node_modules)/,
/\.test.tsx?$/,
/\.spec.tsx?$/
],
use: [
{loader: 'react-hot-loader/webpack'},
{
loader: 'ts-loader',
options: {
transpileOnly: true,
allowTsInNodeModules: false,
onlyCompileBundledFiles: true
}
}
]
},
{
test: /\.(css|scss)$/,
use: [
{loader: 'style-loader'},
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
}
]
}
]
}
};
This is how I import styles in my modules:
const styles = require('./index.scss')
<div className={styles['some-class']}>
When I was on previous webpack version everything worked fine, but as soon as I upgraded webpack and all the webpack related packages, styling is no longer applied.
Any help is highly appreciated

Since you're using require and not import, you have to specify default:
const styles = require('./index.scss').default;

Related

why doesn't my react app load fonts when using `type: 'asset/resource`? (loading fonts in a css file.)

I'm having an issue with my webpack application not loading fonts with type: 'asset/resource' honestly, it won't load many things that use asset/resource type but sticking to one issue :)
Here's my webpack.config.js file
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
module.exports = {
entry: path.join(__dirname, './react-client/src', 'index.jsx'),
output: {
path: path.resolve(__dirname, './react-client/dist'),
filename: 'index_bundle.js',
},
plugins: [
new HtmlWebpackPlugin({
title: 'Project-Atelier',
filename: 'index.html',
template: './react-client/src/index.html',
}),
new MiniCssExtractPlugin(),
],
mode: 'development',
module: {
rules: [
{
test: /\.(js|jsx)?/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.html$/i,
loader: 'html-loader',
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
loader: 'url-loader',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
};
And my css file where I'm trying to import the font (the font I'm importing is indeed in the current folder. I placed it there to test.)
#font-face {
font-family: 'Roboto-Regular';
src: url('./Roboto-Black.ttf') format('truetype');
}
body {
font-family: 'Roboto-Regular';
font-size: 3rem;
}
Here's some details on my dependencies. All should be up to date.
// package.json
...
"dependencies": {
"axios": "^0.26.1",
"prop-types": "^15.8.1",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"styled-components": "^5.3.5",
"uniqid": "^5.4.0",
"url-loader": "^4.1.1"
},
"devDependencies": {
"#babel/core": "^7.17.8",
"#babel/plugin-transform-runtime": "^7.17.0",
"#babel/preset-env": "^7.16.11",
"#babel/preset-react": "^7.16.7",
"#testing-library/dom": "^8.12.0",
"babel-loader": "^8.2.4",
"css-loader": "^6.7.1",
"eslint": "^8.12.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^4.4.0",
"express": "^4.17.3",
"html-loader": "^3.1.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^27.5.1",
"mini-css-extract-plugin": "^2.6.0",
"nodemon": "^2.0.15",
"webpack": "^5.71.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
}
...
I'm thinking it has something to do with babel but I could be wrong. EVERYTHING is working but importing fonts.I even tried changing css within the file I'm showing and changes worked. But not for fonts. An interesting observation I found is that I can't even add images with webpack using type: 'asset/resource' I have to use use: 'url-loader'
Been at this for a couple hours and still looking for answers.
Here's the error!
Error output from webpack.
Figured out my problem... in module.rules for babel-loader
on the line that has test: /\.(js|jsx)?/ rewriting it as test: /\.(js|jsx)$/ fixed the issue. It was just a single character that messed it up ? when it should have been a $.

JSX causing Errors with Jest and Enzyme

When I run the code below I get a repeated error trying to use enzyme with jest on the first JSX component <. So far, I haven't been able to find anything on this occurring with React and not React-Native. So I have followed many tutorials I have found, listened to all the advice, but to no avail.
What could the problem be? Sorry for so much code, but it is all needed for context.
Dependencies:
"dependencies": {
"#babel/core": "^7.8.3",
"#babel/plugin-proposal-class-properties": "^7.8.3",
"#babel/preset-env": "^7.8.3",
"#babel/preset-react": "^7.8.3",
"autoprefixer": "^9.7.4",
"babel-jest": "^25.1.0",
"babel-loader": "^8.0.6",
"css-loader": "^3.4.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"eslint": "^6.8.0",
"eslint-config-jest-enzyme": "^7.1.2",
"eslint-plugin-jest": "^23.7.0",
"jest": "^25.1.0",
"mini-css-extract-plugin": "^0.9.0",
"moment": "^2.24.0",
"postcss-loader": "^3.0.0",
"postcss-nested": "^4.2.1",
"puppeteer": "^2.1.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-highlighter": "^0.4.3",
"react-redux": "^7.1.3",
"react-router-dom": "^5.1.2",
"react-test-renderer": "^16.12.0",
"redux": "^4.0.5",
"style-loader": "^1.1.3",
"tailwindcss": "^1.1.4",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10"
},
"devDependencies": {
"babel-eslint": "^10.0.3",
"eslint": "^6.1.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-loader": "^3.0.3",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.18.0",
"eslint-plugin-react-hooks": "^1.7.0",
"webpack-dev-server": "^3.10.1",
"write-file-webpack-plugin": "^4.5.1"
}
Test:
{
import React from 'react';
import Enzyme, { shallow, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Button from '../src/components/utility/Button';
Enzyme.configure({ adapter: new Adapter() });
describe('<Button /> Testing', () => {
it('renders Button without crashing', () => shallow(<Button />));
});
}
webpack.config.js:
const path = require('path');
const { HotModuleReplacementPlugin } = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const WriteFilePlugin = require('write-file-webpack-plugin');
module.exports = (env, argv) => ({
entry: ['#babel/polyfill', path.join(__dirname, 'src', 'index.js')],
plugins: [
new MiniCssExtractPlugin({
filename: '[name].bundle.css',
chunkFilename: '[id].css',
}),
new WriteFilePlugin({
// Write only files that have ".css" extension.
test: /\.css$/,
useHashIndex: true,
}),
new HotModuleReplacementPlugin(),
],
devServer: {
open: true,
clientLogLevel: 'silent',
contentBase: './dist',
historyApiFallback: true,
hot: true,
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/,
use: [{
loader: 'babel-loader',
options: {
presets: [
['#babel/preset-env', {
targets: {
node: '10',
},
}],
'#babel/preset-react',
],
plugins: ['#babel/plugin-proposal-class-properties'],
},
}, {
loader: 'eslint-loader',
options: {
fix: true,
},
}],
},
{
test: /\.css$/i,
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/,
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: argv.mode === 'development',
},
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
});
I ended up figuring out what the issue was. We didn't have our babel setup in a way that Enzyme would use it. This can be done through a .babelrc file which in hindsight is probably better to use. At present I resolved it by adding configuration for babel into the package.json. I'm sure there's a better way to do this, probably with a .babelrc since Enzyme looks for that by default from what I could find.
"babel": {
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-transform-runtime"
]
},

Syntax Error on dynamic import() using webpack and babel

I'm attempting to use a dynamic import to plug our server-generated config.js file into our production build of our app.
I attempt to use it in this way:
import('./config').then(function(config){
//create a global config variable
config = config;
})
(for now)
When I run webpack, I get the following error
Module build failed: SyntaxError: Unexpected token, expected { (1:6)
Research has led me to believe that this has something to do with babel-loader perhaps not playing nice with dynamic import, but I thought that had already been "solved" with a newer version.
Solutions seem to potentially have been to install Syntax Dynamic Import or maybe babel-plugin-dynamic-import-node, but it's not clear to me which one or why.
Relevant bits of my package.json:
{
"name": "app",
"version": "0.0.1",
"private": true,
"scripts": {
"build": "node config/webpack/build.js",
},
"dependencies": {
"amdi18n-loader": "^0.6.2",
"async": "^2.6.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.2",
"babel-loader": "^7.1.4",
"babel-plugin-istanbul": "^4.1.6",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-2": "^6.24.1",
"babel-register": "^6.26.0",
"chalk": "^2.3.0",
"css-loader": "^0.28.10",
"file-loader": "^1.1.6",
"html-webpack-plugin": "^3.2.0",
"less": "^3.0.1",
"less-loader": "^4.0.6",
"promise-polyfill": "^7.1.0",
"raw-loader": "^0.5.1",
"style-loader": "^0.20.2",
"webpack": "^4.5.0"
},
"devDependencies": {
"autoprefixer": "^7.2.3",
"chromedriver": "^2.34.0",
"copy-webpack-plugin": "^4.3.0",
"cross-env": "^5.1.1",
"cross-spawn": "^5.1.0",
"eslint": "^4.13.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-html": "^4.0.1",
"friendly-errors-webpack-plugin": "^1.6.1",
"inject-loader": "^3.0.1",
"madge": "^2.0.0",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.9",
"rimraf": "^2.6.2",
"semver": "^5.4.1",
"shelljs": "^0.7.8",
"source-map-support": "*",
"uglifyjs-webpack-plugin": "^1.1.4",
"url-loader": "^0.6.2",
"uuid": "^3.1.0",
"webpack-bundle-analyzer": "^2.9.1",
"webpack-cli": "^2.0.14",
"webpack-dev-server": "^3.1.3",
"webpack-merge": "^4.1.1"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
}
}
We split our webpack.conf.js into webpack.base.conf
'use strict';
const path = require('path');
const utils = require('./utils');
const config = require('../');
function resolve(dir) {
return path.join(__dirname, '../..', dir);
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
});
module.exports = {
context: path.resolve(__dirname, '../../'),
entry: {
app: './public/js/ide.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
resolve: {
extensions: ['.js', '.json', '.less'],
alias: {
'#': resolve('public/js'),
},
modules: ['less', 'node_modules']
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('public/js'), resolve('test')],
exclude: [
path.resolve(__dirname, "public/js/config.js")
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
},
{
test: /\.hbs$/,
use: ['raw-loader']
}
]
},
node: {
setImmediate: false,
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
};
...and webpack.prod.conf.js
const webpackConfig = merge(baseWebpackConfig, {
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'public/html/ide.html'
: config.build.index,
template: 'public/html/ide.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.ModuleConcatenationPlugin(),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../../public/fonts'),
to: config.build.assetsFonts,
},
{
from: path.resolve(__dirname, '../../public/img'),
to: config.build.assetsImg,
}
])
]
});
In 1, a user indicated that babel-loader should "just work" with dynamic imports now, so I'm not sure what I'm missing. Something out of date? Something weird in my config?
There are a couple of things you need to do.
First, like some people in the comments mentioned, you need to use a different variable name for your config. Also, if you use import this way, the object you get is a ES6 exported object, so your data will be in default
import('./config').then(function(localConfig){
//create a global config variable
config = localConfig.default;
})
Next, the error you are getting is the result of babel not using the correct preset. You need to be at least on stage-2 for this to work.
{
test: /\.js$/,
loader: 'babel-loader',
options: {
presets: ['es2015','stage-2']
}
include: [resolve('public/js'), resolve('test')],
exclude: [
path.resolve(__dirname, "public/js/config.js")
],
},
This will solve your error, but is still not what you want. All that is happening now is that webpack will split your config file into its own chunk, making a new http request on runtime to get this file. But it will not use the config file that is on the server, but the generated chunk from the build.
To load the actual config that you have on the server on runtime, you need to make a normal http request in your app.
Here is a good stackoverflow answer about this.
https://stackoverflow.com/a/36725115/9083959

webpack cannot find module "fs"

I have a project that's using webpack and electron. I updated my app to use the latest version of electron as it was using electron-prebuilt. Since updating to the latest version I am now unable to compile my app due to this error. I've tried some suggestions from other SO posts which suggest editing webpack.config and added
node: {
fs: 'empty'
},
I still get the same fs not found error. I also tried to set the target to electron, however when I do that I get a string of errors and none of my modules load, is there a workaround available for this issue? I'm not sure if this is a webpack related issue or an electron issue.
Here's my webpack.config
var webpack = require('webpack');
//Loaders & Webpack config
module.exports = {
entry: {
app: ['webpack/hot/dev-server', './app/app.js'],
},
output: {
path: './app/dist',
filename: 'bundle.js',
publicPath: 'http://localhost:8080/dist/'
},
devServer: {
contentBase: './app',
publicPath: 'http://localhost:8080/dist/'
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['react', 'es2015']
}
},
{ test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.png$/,
loader: "file-loader"
},
{
test: /\.jpg$/,
loader: "file-loader"
}
]
},
node: {
fs: 'empty'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.IgnorePlugin(new RegExp("^(fs|ipc)$"))
],
}
package.json
{
"name": "factory",
"productName": "Factory",
"description": "",
"author": ,
"version": "0.1.0",
"main": "main.js",
"devDependencies": {
"babel-core": "^6.8.0",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"bootstrap": "^4.0.0-alpha.4",
"bootstrap-css": "^4.0.0-alpha.5",
"bootstrap-sass": "^3.3.7",
"css-loader": "^0.23.1",
"electron-packager": "^5.2.1",
"electron-rebuild": "^1.1.3",
"exports-loader": "^0.6.4",
"file-loader": "^0.8.5",
"imports-loader": "^0.7.1",
"node-libs-browser": "^1.0.0",
"node-sass": "^4.5.2",
"resolve-url-loader": "^2.0.2",
"sass-loader": "^6.0.3",
"style-loader": "^0.13.2",
"url-loader": "^0.5.8",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.14.1"
},
"scripts": {
"start": "./node_modules/.bin/electron .",
"watch": "./node_modules/.bin/webpack-dev-server",
"build": "electron-packager ./ --platform=darwin,win32 --arch=x64 --prune --overwrite"
},
"dependencies": {
"dragula": "^3.7.2",
"electron-prebuilt": "^0.37.2",
"electron-tabs": "^0.6.0",
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-onclickout": "^2.0.4",
"react-router": "^2.4.0",
"redux": "^3.6.0"
}
}
Set target: 'electron-main' in your Webpack configuration.
I had a similar issue when working on NWjs with webworkers. First, make sure you set the right target option to "node-webkit", "webworker", "node", etc. Then, annotate the module like this:
externals:{
"fs": "commonjs fs"
}
This will tell webpack to load it as a module, as opposed to assuming the dependency is already in the environment.
webpack nwjs

Can't export reducer with Babel

This is most likely some typo but I've been trying to fix it for the last hour and came up with nothing.
I have a file called app/reducers/index.js:
export viewportSize from "./viewportSize";
app/reducers/viewportSize.js is simply:
export default function viewportSize (state = {}) {
return state;
}
And in app/app.js I do:
import reducers from "./reducers";
Babel is giving me back this error
ERROR in ./app/reducers/index.js
1:8 error Parsing error: Unexpected token viewportSize
I have other import and export in the project but this one doesn't want to work.
This is my .babelrc file:
{
"presets": ["es2015", "react", "stage-2"]
}
Update
These are my dependencies
"devDependencies": {
"babel-core": "6.5.2",
"babel-loader": "6.2.3",
"babel-preset-es2015": "6.5.0",
"babel-preset-react": "6.5.0",
"babel-preset-stage-2": "6.5.0",
"eslint": "2.2.0",
"eslint-loader": "1.3.0",
"eslint-plugin-react": "4.1.0",
"file-loader": "0.8.5",
"react-hot-loader": "1.3.0",
"webpack": "1.12.14",
"webpack-dev-server": "1.14.1"
},
"dependencies": {
"babel-preset-stage-0": "6.5.0",
"immutable": "3.7.6",
"react": "0.14.7",
"react-dom": "0.14.7",
"react-redux": "4.4.0",
"react-router": "2.0.0",
"react-router-redux": "4.0.0",
"redux": "3.3.1"
}
Update
This is my webpack config file
var webpack = require("webpack");
module.exports = {
context: __dirname + "/app",
entry: {
javascript: "./app.js",
html: "./index.html",
css: "./style.css",
},
output: {
filename: "app.js",
path: __dirname + "/dist",
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
include: __dirname,
loaders: ["react-hot", "babel-loader", "eslint-loader"],
},
{
test: /\.html$/,
loader: "file?name=[name].[ext]",
},
{
test: /\.css$/,
loader: "file?name=[name].[ext]",
},
],
},
};

Categories

Resources