Webpack-dev-server bundling React JS but not SCSS - reactjs

App was made by "create-react-app" command. Bundled (by webpack) JavaScript code is working properly in my React App, but it does not seem to get any styling from SASS. There are no errors in console or anywhere, it's just being ignored. To start webpack I am running "npm run start".
Repo just in case: https://github.com/ankeris/challengefriend
This is the code:
package.json
"scripts": {
"start": "webpack-dev-server --open --mode development --hot | react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"css-loader": "^1.0.0",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.9.3",
"sass-loader": "^7.1.0",
"style-loader": "^0.22.1",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve('dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import './styles/scss/index.scss';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

To make it worked, I followed this link it tells you how to add css preprocessor in react-create-app, here are the commands to run :
npm install --save node-sass-chokidar
npm install --save npm-run-all
then add these lines in your package.json (in the scripts section) :
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build-js": "react-scripts build",
"build": "npm-run-all build-css build-js",
in your file index.js replace import './styles/scss/index.scss'; by import './styles/scss/index.css';
Finally you can start your app by running npm start
As I said in comment, react-create-app uses its own webpack config, so your webpack.config.js is useless you can remove it from your project
If you really want to import the scss file, then you need to modify the default react-create-app webpack config, you need to run npm run eject to extract the config, then modify the files /config/webpack.config.{env}.js

It should be loaders because you are using Webpack 4.
Please add below rule in Webpack and try
{
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
}

Related

.less files not getting picked up by less-loader

I have created a react app using create-react-app and I am using less for css. My app builds correctly, but none of the less files are loaded in build/static folder
I am using customize-cra with react-app-rewired to add a loader for less files.
config-overrides.js file
const {
override,
addLessLoader
} = require('customize-cra');
const path = require('path');
module.exports = override(
addLessLoader({
paths: [path.resolve(__dirname, 'src/')],
javascriptEnabled: true,
sourceMap: true,
})
);
scripts in package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --passWithNoTests",
"eject": "react-scripts eject",
"release": "CI=true react-app-rewired test --coverage && npm run build && npm run package && npm run posttest",
},
dependencies
"less": "^4.1.1",
"less-loader": "^8.0.0",
"react-scripts": "4.0.2",
"webpack": "4.44.2",
"customize-cra": "^1.0.0"
The error that I was getting was
Module build failed (from ./node_modules/less-loader/dist/cjs.js): TypeError: this.getOptions is not a function
Referred this post and lowered the version of less-loader to 5.0.0 and it started working

Babel failing on Export default from even when enabled

In my React app, I am getting the following error during compilation:
Support for the experimental syntax 'exportDefaultFrom' isn't currently enabled:
1 | export default from './CustomIcon'
|
I have already installed a couple of babel packages, but it did not help. Here is a part of my package.json:
...
"devDependencies": {
"#babel/plugin-proposal-export-default-from": "^7.12.1",
"#babel/plugin-syntax-export-default-from": "^7.12.1",
"#babel/plugin-syntax-jsx": "^7.12.1",
"#babel/preset-react": "^7.12.7",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
...
And this is the content of my babel.config.json file:
{
"presets": ["#babel/preset-react"],
"plugins": [
"#babel/plugin-syntax-jsx",
"#babel/plugin-proposal-export-default-from"
]
}
What am I doing wrong? Why is my babel configuration ignored? Are there any other steps I need to do?
In case of using create-react-app (CRA), you can't simply add the babel.config.js like that since it has been wrapped by CRA.
But we can achieve that by using package react-app-rewired which is able to modify configuration of CRA.
Here are a few steps you would follow up:
Install deps:
yarn add -D react-app-rewired customize-cra
Add the configuration file at root dir config-overrides.js:
const { useBabelRc, override } = require('customize-cra');
module.exports = override(
useBabelRc(),
);
Test your script by switching to react-app-rewired in your package.json:
{
"start": "react-app-rewired start", // Replace `react-scripts`
"build": "react-app-rewired build",
"test": "react-app-rewired test",
}
That's it!

setting up lint-staged for jest

I have to try to set up a husky with lint-staged. Initially, I was trying to set up like the following but that does not work.
"lint-staged": {
"*.js": [
"prettier --write",
"eslint src/ --fix",
"npm run test",
"git add"
]
}
then I after some searching I changed my setting to the following but thats again reported diff error
"lint-staged": {
"*.js": [
"prettier --write",
"eslint src/ --fix",
"jest --bail --findRelatedTests",
"git add"
]
}
Error description
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation to specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
when I run npm run test in terminal it works fine. So why it is not working with `lint-staged. Am I doing something wrong here?
my package.json
{
"name": "myproject",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"react-redux": "^6.0.1",
"react-router-dom": "^5.0.0",
"react-scripts": "2.1.8",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"standard-http-error": "^2.0.1",
"styled-components": "^4.1.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^4.1.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-prettier": "^3.0.1",
"eslint-plugin-react": "^7.12.4",
"husky": "^1.3.1",
"install": "^0.12.2",
"lint-staged": "^8.1.5",
"prettier": "1.16.4"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"prettier --write",
"eslint src/ --fix",
"jest --bail --findRelatedTests",
"git add"
]
}
}
Your lint-staged glob pattern is only set to run on *.js files on root. You have to change it to **/*.js to include ALL *.js files in your project.
"lint-staged": {
"**/*.js": [
"prettier --write",
"eslint src/ --fix",
"jest --bail --findRelatedTests",
"git add"
]
}
Using a Create React App means that you have to test using the react-scripts because they have the babel configuration that jest alone is missing.
There is a work around to set husky lint-staged using react-scripts test and avoid ejecting and configuring your own babel and jest.
Use the package cross-env that will allow us to configure a CI environment variable in whatever environment we’re currently in.
Install using:
yarn add --dev cross-env
or
npm install cross-env --save-dev
Then on your package.json you should have something like this:
{
"scripts" {
...,
"lint": "eslint src --fix"
"test": "cross-env CI=true react-scripts test --env=jsdom",
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"**/*.js": [
"yarn lint",
"yarn test"
]
},
}
If you are using npm you can change yarn test for npm run test, same for lint.
Hope it helps ;).
Main source of this answer: here

How can I add the CopyWebpackPlugin to create-react-app without ejecting?

I am building a react application and I want to copy all image files from the source destination to the build destination. I am following some tutorials and so far managed to use react-app-wired and the CopyWebpackPlugin
I am getting no errors and no files are being copied.
This is my config-overrides.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = function override(config, env) {
if (!config.plugins) {
config.plugins = [];
}
config.plugins.push(
new CopyWebpackPlugin(
[
{
from: 'src/images',
to: 'public/images'
}
])
);
return config;
};
This is my package.json
{
"name": "public",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"copy-webpack-plugin": "^4.5.2",
"css-loader": "^1.0.0",
"prop-types": "^15.6.2",
"react": "^16.4.2",
"react-app-rewired": "^1.5.2",
"react-axios": "^2.0.0",
"react-dom": "^16.4.2",
"react-router-dom": "^4.3.1",
"react-scripts": "1.1.4",
"react-slick": "^0.23.1",
"slick-carousel": "^1.8.1",
"typeface-montserrat": "0.0.54",
"webfontloader": "^1.6.28"
},
"scripts": {
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-app-rewired start",
"start": "npm-run-all -p watch-css start-js",
"build-js": "react-app-rewired build",
"build": "npm-run-all build-css build-js",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"npm-run-all": "^4.1.3",
"style-loader": "^0.22.1"
}
}
My folder structure is
src/images
src/images/file.jpg
src/images/slider/1.png
src/images/slider/2.png
public/images (empty) so far
Assuming you just want to move files from -/src/<somewhere> to ./<somewhereElse> at build time.
You could just add an extra step to your build script in package.json. The step below is completely in your control and does not mess with any create-react-app scripts or configuration.
For example, I used the ncp package, but if you want more granular control, you can also create your own "step" with ncp or even with raw node fs api.
Here is a way to replicate what I did:
Setup
npx create-react-app img-upload
cd img-upload/
yarn add --dev ncp
Test Data
create src/images/ folder structure and put in files
ls -R src/images/
src/images/:
badge.jpg folder1
src/images/folder1:
applause.gif blank.png
Package.json
I only edited the part: "build": "ncp './src/images' './public/images' && react-scripts build",
{
"name": "img-upload",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-scripts": "1.1.5"
},
"scripts": {
"start": "react-scripts start",
"build": "ncp './src/images' './public/images' && react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"ncp": "^2.0.0"
}
}
Test:
Before running build:
ls public
favicon.ico index.html manifest.json
After running build: yarn build
ls public
favicon.ico images index.html manifest.json
ls -R public/images
public/images/:
badge.jpg folder1
public/images/folder1:
applause.gif blank.png
ls build
asset-manifest.json favicon.ico images index.html manifest.json service-worker.js static
ls -R build/images
build/images/:
badge.jpg folder1
build/images/folder1:
applause.gif blank.png
Suggestion
I am assuming you ultimately need these files in build directory. If so, you can just switch your build script.
"build": "react-scripts build && ncp './src/images' './build/images'",
That way you won't pollute your public folder, which you may want to keep in your source control.
It is definitely not recommended to modify the node_modules/react-scripts/config/webpack.config.dev.js file as this will break when this particular package is updated. Also most probably you would be having node_modules ignored in your version control system, meaning this config wont be shared across developers or backed up.
Although I haven't tried myself personally you could use something like this : https://github.com/timarney/react-app-rewired to override the Webpack config.
You can have a look at the tutorial here : https://medium.com/#timarney/but-i-dont-wanna-eject-3e3da5826e39
Mine worked like this:
const { override, addWebpackPlugin } = require('customize-cra');
module.exports = {
webpack: override(
addWebpackPlugin(
new CopyWebpackPlugin({
patterns: [
{ from: 'src/config', to: 'config' }
],
})
)
)
With that, I'm taking the contents of my config folder and creating an equal one in the build also called config.
I think the problem is because you are using webpack-dev-server together with copy-webpack-plugin. If that's true, the copy-webpack-plugin will copy files to virtual directory which webpack-dev-server works. So that, In this situation, you need to add one more plugin to make it happen
If you want webpack-dev-server to write files to the output directory
during development, you can force it with the
write-file-webpack-plugin.
import WriteFilePlugin from 'write-file-webpack-plugin';
webpack config:
config.plugins.push(
new CopyWebpackPlugin(
[
{
from: 'src/images',
to: 'public/images'
}
])
);
config.plugins.push(new WriteFilePlugin());
You can visit the official document for more information: https://webpack.js.org/plugins/copy-webpack-plugin/
Hope this works!

App threw an error when running [SyntaxError: Unexpected token import]

We have a running react app that i am asked to generate an electron for. After adding my Main.js file as explained Here . My electron threw the error above . After going through, i noticed that my electron does not the es6 and react terminologies in my index.js below
import React from 'react';
import ReactDOM from 'react-dom';
import Root from './_store/root';
ReactDOM.render(<Root/>, document.getElementById('root'));
When i change the import from the code above, electron threw another error invalid token > which i understand is from the <Root/> .
Below is how i run my electron
./node_modules/.bin/electron .
Part of my package.json is
"main": "src/index.js",
"scripts": {
"test": "npm run test:eslint && npm run test:unit",
"test:eslint": "webpack --config webpack.config.dev.js",
"test:unit": "mocha --compilers js:babel-core/register ./src/**/__tests__/*.js",
"test:watch": "npm test -- --watch",
"test:coverage": "babel-node ./node_modules/istanbul/lib/cli cover ./node_modules/mocha/bin/_mocha ./src/_common/__tests__/*.js",
"start": "node server.js",
"build": "npm run clean && npm run build:webpack",
"translate": "bash fetch-translation.sh"
}
My react app implemented in react , react-redux is working fine .
and my webpack.config
module.exports = {
devtool: 'eval',
entry: [
'./src',
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'app.js',
publicPath: '/',
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
],
module: {
loaders: [{
test: /\.js$/,
loader: 'babel-loader',
include: path.join(__dirname, 'src'),
}, {
test: /\.js$/,
loader: 'eslint-loader',
include: path.join(__dirname, 'src'),
}],
},
};
The only problem is my electron which i am trying to generate a desktop app with. Any help would be appreciated.
and my dependencies
"devDependencies": {
"babel-core": "^6.4.0",
"babel-eslint": "^5.0.0-beta6",
"babel-loader": "^6.2.1",
"babel-plugin-react-intl": "^2.0.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-function-bind": "^6.3.13",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-stage-0": "^6.3.13",
"eslint": "^1.10.3",
"eslint-config-airbnb": "^3.1.0",
"eslint-loader": "^1.2.0",
"eslint-plugin-react": "^3.15.0",
"expect": "^1.13.4",
"expect-jsx": "^2.2.2",
"express": "^4.13.3",
"istanbul": "^0.4.2",
"json-loader": "^0.5.4",
"mocha": "^2.3.4",
"react-addons-perf": "^0.14.6",
"react-addons-test-utils": "^0.14.6",
"webpack": "^1.12.11",
"webpack-dev-middleware": "^1.2.0",
"webpack-hot-middleware": "^2.6.0"
}
invalid token >
This problem is quite difficult to find without analysis of all your code.
I had similar error and it was because I didn't include here Electron.app/Contents/Resources/app/ package.json file. Error message was not helpful.
For my needs I created electron+react+redux+bootstrap3+sass boilerplate app. It has also integrated react hot loader, which works great (it runs your electron app and you add changes and this changes are instantly visible) and react part is in ES6 & ES7 and jsx . You could try to run it and compare with your code. Maybe you find reason.
Currently I add only configuration for os x release (because I don't have windows but I will be glad of any support )
https://github.com/uhlryk/my-electron-boilerplate
It is very fresh and could have some problems (as I said I welcome any contributions).
It turns out the error is in my package.js The
"main": "src/index.js",
"scripts": {
"test": "npm run test:eslint && npm run test:unit",
"test:eslint": "webpack --config webpack.config.dev.js",
"test:unit": "mocha --compilers js:babel-core/register ./src/**/__tests__/*.js",
"test:watch": "npm test -- --watch",
"test:coverage": "babel-node ./node_modules/istanbul/lib/cli cover ./node_modules/mocha/bin/_mocha ./src/_common/__tests__/*.js",
"start": "node server.js",
"build": "npm run clean && npm run build:webpack",
"translate": "bash fetch-translation.sh"
}
Change the main above to point to your electron file .like
"main": "src/electron.js",
"scripts": {
"test": "npm run test:eslint && npm run test:unit",
"test:eslint": "webpack --config webpack.config.dev.js",
"test:unit": "mocha --compilers js:babel-core/register ./src/**/__tests__/*.js",
"test:watch": "npm test -- --watch",
"test:coverage": "babel-node ./node_modules/istanbul/lib/cli cover ./node_modules/mocha/bin/_mocha ./src/_common/__tests__/*.js",
"start": "node server.js",
"build": "npm run clean && npm run build:webpack",
"translate": "bash fetch-translation.sh"
}
in my case . The electron.js is simply the electron js implementation below which is obtainable on the electron github page.
const electron = require('electron');
const app = electron.app; // Module to control application life.
const BrowserWindow = electron.BrowserWindow; // Module to create native browser window.
// Report crashes to our server.
electron.crashReporter.start();
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
var mainWindow = null;
// Quit when all windows are closed.
app.on('window-all-closed', function() {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform != 'darwin') {
app.quit();
}
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
// Create the browser window.
mainWindow = new BrowserWindow({width: 600, height: 500});
// and load the index.html of the app.
mainWindow.loadURL('file://' + __dirname + '/../public/index.html',{"userAgent":"Mobile"});
// Open the DevTools.
mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', function() {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
In this case your electron does not need to be aware of your es6 scripts as it would be handle by babel and rendered on your index.html. index.html is in return rendered on our electron

Resources