Webpack css-loader is not importing CSS - javascript

I have Server rendered my create-react-app by reading this tutorial.
And now, I cannot import CSS files in .js files!
Tried using style-loader, css-loader, extract-text-webpack-plugin, mini-css-extract-plugin, tried tweaking webpack configuration, but nothing helped.
NO StackOverflow answer helped. So this question. 😅
This is my package.json:
{
...
"scripts": {
"dev:build-server": "NODE_ENV=development webpack --config webpack.server.js --mode=development -w",
"dev:start": "nodemon ./server-build/index.js",
"dev": "npm-run-all --parallel build dev:*",
"start": "serve --single ./build",
"client": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"now-build": "react-scripts build && mv build dist",
"deploy": "npm run build && now ./build -A ../now.json --public --name=kumarabhirup"
},
...
}
This is webpack.server.js
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin');
// const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: './server/index.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: path.resolve('server-build'),
filename: 'index.js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
},
{
test: /\.css$/,
// use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader'] NOT WORKED
use: ExtractTextPlugin.extract('style-loader', 'css-loader') // NOT WORKING
},
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader"
]
}
]
},
plugins: [
new webpack.EnvironmentPlugin({...process.env}),
new ExtractTextPlugin('[name].css') // TRIED THIS TOO
// new MiniCssExtractPlugin({ TRIED THIS
// filename: 'style.css',
// })
]
};
Error it throws at me when I, import 'react-circular-progressbar/dist/styles.css',
/Users/iqubex/Sites/kumarabhirup/kumarabhirup/node_modules/react-circular-progressbar/dist/styles.css:7
.CircularProgressbar {
^
SyntaxError: Unexpected token .
at new Script (vm.js:83:7)
at createScript (vm.js:267:10)
at Object.runInThisContext (vm.js:319:10)
at Module._compile (internal/modules/cjs/loader.js:686:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:734:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Module.require (internal/modules/cjs/loader.js:659:17)
at require (internal/modules/cjs/helpers.js:22:18)
[nodemon] app crashed - waiting for file changes before starting...
All that I expect is the working of imported CSS files. Please help 🙌🏻

#gopigorantala is right.
Change the loader to one of these, it should work:
use: ['style-loader', 'css-loader']
or
use: [MiniCssExtractPlugin.loader, 'css-loader']
You probably won't need to use ExtractTextPlugin. Just use MiniCssExtractPlugin. It'll work.
The style-loader loads the styles into DOM with <style> at runtime, and MiniCssExtractPlugin extract them to a separate file. So you don't need to use both of them.

Related

webpack-dev-server doesn't update HTML auto?

I'm using webpack-dev-server with webpack v5 and for a reason when I made changes in my CSS and js it updated on time as expected but for HTML files I have to refresh my browser manually to see the new complied version .
src
|-index.html
|-index.js
webpack.config.js
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
output: {
clean: true,
filename: "bundel.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new htmlWebpackPlugin({
filename: "index.html",
template: path.resolve(__dirname, "src", "index.html"),
}),
],
};
my package.json devDependencies
"devDependencies": {
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
}
I start my server with npx webpack serve --open
I added CSS file and its relative CSS loaders for testing and removed it after I make sure it work and just HTML is the problem
you can replicate the problem when you change the index.html content
The problem is webpack-dev-server doesn't watch HTML files by default
so I found two solutions for this :
The first solution is built-in throw devServer by adding watchFiles:
devServer: {
watchFiles: ["src/*.html"],
hot: true,
},
The second solution using an external plugin called browser-sync-webpack-plugin
Try to use the DevServer option to reload the page and compress all.
Instead of running npx webpack serve --open run npm run start using this script config:
"scripts": {
"start": "webpack-dev-server",
"build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
And try to use this base config for your webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// Default settings
mode:'development',
devtool:'inline-source-map',
entry:{
main: path.join(__dirname,'src','index.js')
},
output:{
filename:'index.js',
path: path.resolve(__dirname,'dist'),
clean:true,
},
// Loaders
module:{
// JavaScript
rules:[
{
test: /\.js$/i,
use:{
loader:'babel-loader',
options:{
"presets":['#babel/preset-react']
}}
},
// Css
{
test: /\.css$/i, use:['style-loader','css-loader']
}
]
},
// Plugins
plugins:[
new HtmlWebpackPlugin({
template: path.join(__dirname,'public','index.html') ,
filename:'index.html'
})
],
// DevServer
devServer:{
port:8080,
open:true,
compress:true,
hot:true,
liveReload:true,
}
};

Invoking bundle.js built via webpack from create react app

I have created a bundle.js file with webpack from my create-react-app project as it sits with the below config:
const path = require("path")
const UglifyJsPlugin = require("uglifyjs-webpack-plugin")
const glob = require("glob")
module.exports = {
entry: {
"bundle.js": glob.sync("build/static/?(js|css)/*.?(js|css)").map(f => path.resolve(__dirname, f)),
},
output: {
filename: "release/bundle.min.js",
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [new UglifyJsPlugin()],
}
And, this is my index.html
<html>
<body id="root">
<script src="path-to-bundle.min.js"></script>
</html>
But, I dont see anything mounted inside #root. Basically the script does not fire. I tried the var and EntryPoint webpack config as well. In that case, EntryPoint is always an empty object.
UPDATE:
Package.json
"start": "react-scripts start",
"test": "react-scripts test",
"eject": "react-scripts eject",
"build": "npm run build:react && npm run build:bundle",
"build:react": "react-scripts build",
"build:bundle": "webpack --config webpack.config.js"

How to put React in production mode?

I tried using the solution from here but the icon is still read indicating dev mode.
Here is my current file with updates from the answer below:
const path = require('path');
const SRC_DIR = path.join(__dirname, '/client-react/src');
const DIST_DIR = path.join(__dirname, '/client-react/dist');
const webpack = require('webpack')
module.exports = {
entry: `${SRC_DIR}/index.jsx`,
output: {
filename: 'bundle.js',
path: DIST_DIR
},
plugins: [
new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')} })
],
module: {
loaders: [
{
test: /\.jsx?/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
plugins: ["transform-object-rest-spread", "transform-class-properties"],
presets: ['react', 'es2015']
}
}
]
}
};
If you use Webpack 4, you don't need to change webpack.config.js. It remains the same in both development and production modes.
The only thing needed is in your package.json:
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
Having this, to create a development bundle:
npm run dev
Production bundle:
npm run build
When you want to build your app in production mode, you should use webpack production shortcut. Like this:
webpack -p
This will enable webpack optimize options to minify your JS. See more detailed explanation of webpack flags on this SO answer.
Webpack plugins need to be put under the plugins key in module.exports.
https://webpack.github.io/docs/using-plugins.html#built-in-plugins
Try this:
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
]
}
Had the same error so to fix it I did this:
package.json
"scripts": {
"build": "NODE_ENV=production webpack --progress --colors",
"start": "NODE_ENV=development webpack-dev-server --progress --colors"
}
webpack.config.js
const env = process.env.NODE_ENV
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env)
})
]
}
It should work for sure.
Here I have some configuration that you can try to optimize your build.
This worked for me: run npm run build followed by npm install -g serve and serve -s build

Can't Set NODE_ENV to production with webpack

I'm using webpack 2.2.1 to build a react-redux app for production, but can't seem to set process.env.NODE_ENV to production.
Here is webpack.config.js:
var webpack = require('webpack');
var path = require('path');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require('html-webpack-plugin');
const VENDOR_LIBS = [
'axios', 'lodash', 'react', 'react-dom', 'react-redux',
'react-router', 'redux', 'redux-form', 'redux-thunk'
];
module.exports = {
entry: {
bundle: './src/index.js',
vendor: VENDOR_LIBS
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
use: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/,
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin('style.css'),
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
devServer: {
historyApiFallback: true,
contentBase: './'
}
};
And here are my scripts in package.json:
"scripts": {
"clean": "rimraf dist",
"build": "NODE_ENV=production npm run clean && webpack -p",
"serve": "webpack-dev-server"
}
When I run npm run build, my bundle.js is compiled but it's not for production. In my webpack.config.js, I replaced the option for the DefinePlugin to 'process.env.NODE_ENV': '"production"' and it worked. So I'm thinking there is something wrong with my package.json file, but I can't figure out what it is.
You are running two processes with your build command npm run clean and webpack -p. When you add NODE_ENV=production in front, it only applies to the current process. In you example, NODE_ENV=production npm run clean && webpack -p, only the clean command runs with the set environment variable.
When you add export NODE_ENV=production it will set it for all processes you start from that terminal. Keep this in mind because everything else you run from that same terminal window will have NODE_ENV=production set.
$ npm run build
> NODE_ENV=production npm run clean && webpack -p
...
$ echo $NODE_ENV
production
If you don't want to have NODE_ENV=production to stick for other processes, then add NODE_ENV=production in front of both processes:
NODE_ENV=production npm run clean && NODE_ENV=production webpack -p

Why does production build of React app (with Webpack and Babel) use wrong development env with HMR, which causes errors?

I'm trying to create a production build of my React project, but it picks the wrong configuration.
In the development version I'm using HMR (Hot Module Replacement). This is configured in .babelrc, under env > development > plugins.
When adding an extra node env > production it seems to be ignored. It's still using the development configuration with HMR, which causes an error:
Uncaught Error: locals[0] does not appear to be a module object with
Hot Module replacement API enabled. You should disable
react-transform-hmr in production by using env section in Babel
configuration. See the example in README: https://github.com/gaearon/react-transform-hmr
Of course I've checked that information, but everything seems right.
When I removed the HMR plugin from .babelrc's development config, it works, proving it is indeed using the development config instead of production.
Here's my files:
package.json
{
"name": "myproject",
"main": "index.js",
"scripts": {
"serve": "cross-env NODE_ENV=development webpack-dev-server --content-base bin/ --devtool eval --progress --colors --hot --inline",
"deploy": "cross-env NODE_ENV=production BABEL_ENV=production webpack -p --config webpack.production.config.js"
}
//dependencies omitted in this example
}
.babelrc
{
"presets": ["react", "es2015", "stage-0"],
"plugins": [
["transform-decorators-legacy"]
],
"env": {
"development": {
"plugins": [
["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}]
}]
]
},
"production": {
"plugins": []
}
}
}
As you can see in package.json > scripts > deploy, I'm even explicitly setting the BABEL_ENV to 'production'.
Why is this happening? How do I make sure the production build ignores the HMR plugins?
By the way, searching often leads to issue #5 on the React-transform-HMR Github page, which is a long thread without a clear solution.
Edit 2016.03.30: Adding the Babel part of my webpack config on request.
Edit 2016.04.06: Adding whole webpack file on request.
webpack.production.config.js
require('es6-promise').polyfill();
var path = require('path');
module.exports = {
entry: './main.jsx',
context: __dirname + path.sep + 'src',
output: {
path: path.resolve(__dirname, './bin'),
filename: 'index.js'
},
devServer: {
port: 3333
},
module: {
loaders: [
{
test: /\.js(x?)$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: [['transform-decorators-legacy']]
}
},
{
test: /\.css$/,
loader: "style!css"
},
{
test: /\.scss$/,
exclude: /(node_modules|bower_components)/,
loader: 'style-loader!css-loader!sass-loader?sourceMap'
}
]
}
};
The only thing that worked for me, is that I wrote -
process.env.NODE_ENV = 'production';
at the beginning of my webpack.config.prod.js file.
It seems that no matter what Babel keeps using the development section of the env value specified in .babelrc. What solved the problem for me, was to use name other than 'development' and set that as the value of BABEL_ENV.
"env": {
"dev": {
"plugins": [
]
},
"production": {
}
}
I use separate conf for development. In plugins I have:
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development'),
'BABEL_ENV': JSON.stringify('dev')
}
}),
& in shell means that it will run in the background, so maybe your variable declaration is not caught by the build stuff that happens at the same time. The good thing is that you can just prepend the command with the variable declarations.
You could simplify the commands like this:
"serve": "NODE_ENV=development webpack-dev-server --content-base bin/ --devtool eval --progress --colors --hot --inline",
"deploy": "NODE_ENV=production BABEL_ENV=production webpack -p --config webpack.production.config.js"
You can just use the babel-preset-react-hmre.
.babelrc
{
"presets": ["react", "es2015", "stage-0"],
"plugins": [
"transform-decorators-legacy"
],
"env": {
"development": {
"presets": ["react-hmre"]
}
}
}
webpack
{
test: /\.js(x?)$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react', 'stage-0'],
plugins: ['transform-decorators-legacy'],
env: {
development: {
presets: ['react-hmre']
}
}
}
}

Categories

Resources