I already read SO damn much tutorials, tickets etc, and i just cannot resolve it...
I have a React project with webpack. And i try to use .scss files for styling.
So i have this webpack.config.js:
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
devServer: {
contentBase: "./src"
},
entry: [
'babel-polyfill',
'./src/app'
],
output: {
publicPath: '/',
filename: 'app.bundle.js'
},
devtool: 'source-map',
module: {
loaders: [
//Babel
{
test: /\.js$/,
include: path.join(__dirname, 'src'),
loader: 'babel-loader',
query: {
presets: ["es2015", "react"],
}
},
//Sass
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('css!sass')
}
]
},
plugins: [
new ExtractTextPlugin('src/style.css', {
allChunks: true
})
],
debug: true
};
And a App.scssFile in src/:
body {
margin: 20px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h1 {
color: pink;
}
h2 {
color: greenyellow;
}
Than in my index.html I include the css file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Aline</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="style.css"/>
</head>
<body >
<div id="content"></div>
<script src="../app.bundle.js"></script>
</body>
</html>
Than i call webpack-dev-server --inline --hot --quiet.
Than chrome always tells me it cannot find the css file, and it seems webpack just doesnt care about my scss file....
my package.json dependencies would be:
"devDependencies": {
"babel-core": "6.17.0",
"babel-loader": "6.2.5",
"babel-plugin-transform-runtime": "6.15.0",
"babel-preset-es2015": "6.16.0",
"babel-preset-react": "6.16.0",
"babel-runtime": "6.11.6",
"css-loader": "0.25.0",
"extract-text-webpack-plugin": "1.0.1",
"node-sass": "3.10.1",
"sass-loader": "4.0.2",
"style-loader": "0.13.1",
"webpack": "1.13.2",
"webpack-dev-server": "1.16.2"
},
Got the answer on Twitter by a webpack develeoper itself! It was my own stupidity. I am still learning about webpack etc, and I forgot how webpack is working.
It builds a tree out of dependencies, so logically it needs know the scss files in some way... so i told my enter point (app.js) per require about my scss file, and TADA. There it goes.
I havent thought about that, because all the tutorials using the ExtractTextPlugin explain it collects all the scss files and makes a single css out of it. So I was like "oh it collects all my scss files out of my folders. Nice!" But yeah... nah xD it collects it from the tree not the disk :p
Related
I am learning webpack to start out my react projects without create-react-app. Everything seems to work fine but when I open the console after npm run dev, I see the error message: Uncaught TypeError: Failed to resolve module specifier "react-dom/client". Relative references must start with either "/", "./", or "../".
Below are my project files.
webpack-react
├── dist
├── package-lock.json
├── package.json
├── public
│ └── index.html
├── src
│ ├── App.js
│ └── index.js
├── webpack.config.js
└── .babelrc
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="../src/index.js"></script>
</body>
</html>
App.js
function App() {
return (
<div>
<h1>Welcome to webpack</h1>
</div>
);
}
export default App;
index.js
import ReactDOM from "react-dom/client";
import App from "./App";
const root = document.querySelector("#root");
ReactDOM.createRoot(root).render(<App />);
.babelrc
{
"presets": [
"#babel/preset-env",
["#babel/preset-react", { "runtime": "automatic" }]
]
}
webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: process.env.NODE_ENV || "development",
entry: "./src/index.js",
output: {
filename: "bundle.[hash].js",
path: path.resolve(__dirname, "dist"),
},
resolve: {
extensions: [".js", "jsx", ".css"],
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: {
minimize: true,
},
},
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({ template: "./public/index.html" }),
],
devServer: {
host: "localhost",
port: process.env.PORT || 3000,
open: true,
},
};
package.json
{
"name": "webpack-react",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack --mode production --progress"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.18.2",
"#babel/preset-env": "^7.18.2",
"#babel/preset-react": "^7.17.12",
"babel-loader": "^8.2.5",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.7.1",
"html-loader": "^3.1.0",
"html-webpack-plugin": "^5.5.0",
"style-loader": "^3.3.1",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.0"
},
"dependencies": {
"react": "^18.1.0",
"react-dom": "^18.1.0"
}
}
I find it weird that react files are rendered despite the message..
I believe the error comes from this line
<script type="module" src="../src/index.js"></script>
Since you are using Webpack to bundle, the injection is handled by Webpack.
Remove that line, the app should still work and the error should disappear.
I am learning webpack js; following an example where the trainer loads an html page from src folder to a destination (dist) folder. I am trying the same thing but on Webpack5. I have created a config folder and running the below webpack.dev.js from config folder.
Webpack.dv.js
const path = require("path");
module.exports = {
entry: {
main: ["./src/main.js"]
},
mode: "development",
output: {
filename: "[name]-bundle.js",
path: path.resolve(__dirname, "../dist"),
publicPath: "/"
},
devServer: {
contentBase: "dist",
overlay: true
},
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
}
]
},
{
test: /\.html$/i,
use: [
{
loader: "file-loader",
options: {
name: "[name].html"
}
},
{
loader: "extract-loader"
},
{
loader: "html-loader",
}
]
}
]
}
};
Upon yarn serve --config=config/webpack.dev.js command, I get the following error,
./src/index.html 39 bytes [built] [code generated] [1 error]
ERROR in ./src/index.html
Module build failed (from ./node_modules/extract-loader/lib/extractLoader.js):
SyntaxError: unknown: Unexpected token (3:61)
1 | // Imports
2 | import ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___ from "../node_modules/html-loader/dist/runtime/getUrl.js";
> 3 | var ___HTML_LOADER_IMPORT_0___ = new URL("./main-bundle.js", import.meta.url);
| ^
4 | // Module
5 | var ___HTML_LOADER_REPLACEMENT_0___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___);
6 | var code = "<!DOCTYPE html>\n<html>\n <head>\n <title>Testing Webpack with Yarn!</title>\n </head>\n <body>\n <div class=\"profile\">\n <h1>Hello World!</h1>\n </div>\n <script src=\"" + ___HTML_LOADER_REPLACEMENT_0___ + "\"></script>\n </body>\n</html>";
at Parser.pp$5.raise (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:4454:13)
at Parser.pp.unexpected (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:1761:8)
at Parser.pp$3.parseExprAtom (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:3627:50)
at Parser.pp$3.parseExprSubscripts (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:3494:19)
So I played around with the Script tag in the HTML file (given below),
<!DOCTYPE html>
<html>
<head>
<title>Testing Webpack with Yarn!</title>
</head>
<body>
<div class="profile">
<h1>Hello World!</h1>
</div>
<script src="main-bundle.js"></script>
</body>
</html>
Turns out if I remove the <script> tag, the project builds fine but nothing is copied over to dist folder. Can someone please point out as to what is wrong with the above configurations? What am I missing or what can I do to make this work? Also please point out why is it a good or bad idea to load an index.html from a src?
package.json:
{
"name": "name-this-anything",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack serve --config=config/webpack.dev.js"
},
"devDependencies": {
"css-loader": "^5.2.5",
"extract-loader": "^5.1.0",
"file-loader": "^6.2.0",
"html-loader": "^2.1.2",
"style-loader": "^2.0.0",
"webpack": "^5.37.1",
"webpack-cli": "^4.7.0",
"webpack-dev-middleware": "^4.3.0",
"webpack-dev-server": "^3.11.2"
}
}
Thanks!
I'm currently working on integrating React with Grails (2.3.11). It seems however that even the most basic setup is giving me a hard time. I've set up my file and folder structure that I have done before with past projects but my bundle.js file just doesn't seem to be want to be found. I keep getting a 404 no matter how many different times I change the path.
This is basically what happens all the time!
My package.json file:
{
"name": "react_test",
"version": "1.0.0",
"description": "Grails with React",
"main": "index.js",
"license": "MIT",
"dependencies": {
"axios": "^0.18.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"redux": "^4.0.0",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"redux-logger": "^3.0.6",
"webpack": "^4.12.0",
"webpack-cli": "^3.0.8"
},
}
My root.gsp file that is supposed to pick up the bundle.js file and render the react code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Grails with React</title>
<script src="../../../src/react/public/bundle.js"></script>
</head>
<body>
<div id="root">
<p>React broke down</p>
</div>
</body>
</html>
My Webpack file:
var webpack = require('webpack')
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/react/public');
var APP_DIR = path.resolve(__dirname, 'src/react/app');
var config = {
entry: APP_DIR + '/main.jsx',
mode : 'development',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module : {
rules : [
{
test : [/\.jsx?$/, /\.js?$/],
exclude: /node_modules/,
include: APP_DIR,
loader : 'babel-loader',
query: {
presets: ['react', 'env']
}
}
]
},
devtool: 'source-map',
resolve: {
extensions: [".js", '.jsx', '*']
}
};
module.exports = config;
Finally here's my simple starting file:
import React from 'react';
import {render} from 'react-dom';
class App extends React.Component {
render () {
return <p> Hello, World!</p>;
}
}
render(<App/>, document.getElementById('root'));
If it helps, here's my folder structure!
Any advice or help you can throw my away is greatly appreciated! I'd be willing to experiment! Thank you!
After a lot of experimentation I discovered what needed to be done. Because this is a Grails application it has be written very specifically and has to be outputted in the correct folder.
Change the script line into this:
<g:javascript src="bundle.js"></g:javascript>
Then make sure to output the bundle.js file in the web-app/js folder. This is a must. So change your webpack to this:
var BUILD_DIR = path.resolve(__dirname, 'web-app/js');
That solved it!
I recently upgraded from Webpack 3 to 4. It's now throwing an error:
Module parse failed: Unexpected character '#' You may need an
appropriate loader to handle this file type. | #import
'./scss/variables.scss'; | | * { # ./src/index.js 1:0-22
In my styles.scss file, I am doing the following:
#import 'scss/variables.scss';
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
In my index.js file, I am only doing the following:
import './style.scss';
In my webpack.dev.js, all I changed was an addition of mode: 'development':
const StyleLintPlugin = require('stylelint-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const Dotenv = require('dotenv-webpack');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'public/bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: ['babel-loader', 'eslint-loader']
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader'])
}
]
},
plugins: [
new StyleLintPlugin({
configFile: '.stylelintrc',
context: 'src',
files: '**/*.scss',
failOnError: false,
quiet: false,
syntax: 'scss'
}),
new ExtractTextPlugin('public/style.css'),
new Dotenv()
]
};
I don't know what change from Webpack 3 to 4 has caused this error.
The issue I'm having is very similar to the issue posted here: Webpack 4 Module parse failed: Unexpected character '#' (1:0)
I have been through all related stackoverflow questions and none of them helped.
Here are the relevant dependencies in my package.json:
"babel-loader": "^7.1.4",
"css-loader": "^0.28.11",
"eslint-loader": "^1.9.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"node-sass": "^4.9.0",
"sass-loader": "^6.0.7",
"style-loader": "^0.20.3",
"stylelint-webpack-plugin": "^0.10.5",
"uglifyjs-webpack-plugin": "^1.2.5",
"webpack": "^4.8.3",
"webpack-cli": "^2.1.4"
Here are the relevant scripts in my package.json file, for reference in the comments:
"scripts": {
"watch": "./node_modules/.bin/webpack --mode development --watch --progress",
"build": "./node_modules/.bin/webpack --mode production"
},
The problem was the script I was using to run Webpack did not specify the config file. This is what it should look like:
"scripts": {
"watch": "./node_modules/.bin/webpack --watch --config webpack.dev.js",
},
I believe this was generating the #import problem because it was not loading the css-loader as without specifying the config file like above, it uses a default Webpack development config which does not include the css-loader.
As I mentioned in a comment on your question there's an open issue with Webpack 4 compatibility: https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/701
A fix for now is to install the alpha version of the library. I've done a small setup just now to test this and it works with webpack 4.
Install the alpha version npm i -D extract-text-webpack-plugin#next --save. Then install css-loader, sass-loader and node-sass.
Then in the webpack config file:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
...
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader'
},
exclude: /node_modules/,
include: path.join(__dirname, 'src')
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader'])
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css'),
]
This correctly worked for me, and also concatenated multiple scss files that were using #import statements.
In package.json it should look like
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"webpack": "^4.8.3"
Edit: Just as a side note, apparently mini-css-extract-plugin works fine with webpack 4.
This worked for me: Replace your webpack styling config to the below code
module: {
rules: [
{
test: /\.(css|sass|scss)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
}
]
}
I hope this resolves your issue thanks
I am using webpack with ReactJS and trying to figure out how to using normalize.css after npm installing it (https://necolas.github.io/normalize.css/).
Is the normalize.css applied right away after npm installing it? How would I make edits to it if I wanted to?
You can use the npm-installed normalize.css in the following way with React:
import React from 'react';
import ReactDOM from 'react-dom';
import 'normalize.css'; // Note this
const root = document.getElementById('root');
ReactDOM.render(<h1>Hello, World!</h1>, root);
The result will be:
Notice that the text has been styled by normalize.css.
To get it working, you need something similar to the following setup:
1) Add the Javascript from above to index.js
2) Add normalize.css (and friends) to package.json:
{
"dependencies": {
"normalize.css": "^5.0.0",
"react": "^16.3.2",
"react-dom": "^16.3.2"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.11",
"style-loader": "^0.21.0",
"webpack-dev-server": "^3.1.4",
"webpack": "^4.8.3"
}
}
3) Use the correct loaders in webpack.config.js:
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
options: { presets: ['env', 'react'] }
},
{
test: /\.css$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }]
}
]
}
};
4) Add an index.html file to see the results:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="root"></div>
<script src="main.js"></script>
</body>
</html>
4) Install everything
npm install
5) Start the Webpack devserver:
./node_modules/.bin/webpack-dev-server --open
NOTE: I am using version 5.0.0 of normalize.css. If you use version 6.0.0 or higher, the font will be different. All the opinionated rules were removed from normalize.css in that version.
Update 17/5/2018: Updated to use Webpack 4 and React 16.
Adding: If you are using WebPack 4 and you cannot import normalize.less, try normalize.css.
#import "../node_modules/normalize.css/normalize.css";
And my rules:
module: {
rules: [{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader,
"css-loader"
]
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"less-loader"
]
}
]
};
in index.css:
#import "~normalize.css/normalize.css";
Once you import or require it will be included by Webpack unless you set it not to. For example:
Note: I’m using Webpack 2.
module: {
rules: [ // from 'loaders' to 'rules'
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.sass$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style-loader',
loader: ['style-loader','sass-loader']
})
}
]
}
The exclude property will take care of that.
Example:
// public/assets/style.scss
#import 'substyle1';
#import 'substyle1';
body {
background-color: red;
}
// src/index.js -> entry file
import '../public/assets/style.scss';
// Webpack will know that you are importing your SCSS / SASS file
Hope this helps.
First, install or download normalize.css from GitHub.I would recommend download it.Then, There are then 2 main ways to make use of it.
Approach 1: use normalize.css as a starting point for your own project’s base CSS, customising the values to match the design’s requirements.
Approach 2: include normalize.css untouched and build upon it, overriding the defaults later in your CSS if necessary.
i.e Just put these downloaded files into the project folder and add link to it by link tag
link rel="stylesheet" type="text/css" href="normalize.css"
NOTE href content should point to the folder where normalize is stored.