I have been trying to use external css on my React project. I am using webpack with babel. I have configured css, js and jsx loaders on my project. As a matter of fact my project is able to compiled successfully yet I couldn't able to style applied on my html.
Here is my style-header.css file:
.LogoMargin {
margin-top: 10px;
margin-left: 10px;
}
Here is my jsx file in which I want to use css style
import React,{Component} from 'react';
import { withStyles } from 'material-ui/styles';
import TextField from 'material-ui/TextField';
import logo from '../resources/images/logo.png';
import '../resources/style/style-header.css';
class Header extends Component {
render () {
return(
<div>
<span>
<img className="LogoMargin" src={logo} height="60" width="200" alt="logo" />
</span>
<TextField
id="search"
label="Search"
type="search"
/>
</div>
)
}
}
export default Header;
Here webpack config file:
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + "/app/index.js",
output: {
path: __dirname + "/build",
filename: "bundle.js"
},
module: {
loaders: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.css$/,
exclude: /node_modules/,
loader: 'css-loader'
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
},
},
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + "/index.tmpl.html"
}),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
historyApiFallback: true,
inline: true,
stats: {colors: true},
hot: true
}
}
Add style loader for handling css as well.
Because you didn't provide webpack version, I cannot provide any code, but I'm sure you will figure out how to use it.
https://github.com/webpack-contrib/style-loader
You should add "style-loader" for your webpack configuration. You can provide it in array as the following. Also, I have an example in this repo:
https://github.com/burakhanalkan/simple-react-materialui-app-starter/blob/master/webpack.config.js
{
test: /\.css$/,
use: [
"style-loader",
"css-loader"
]
},
Well I was able to solve this problem as proposed by answers to use style-loader and also I made some changes to my webpack config file which are as follow:
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" ,
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}}
]
But I wonder when I set up react environment using Create React App I was able to use styles without using css module loader.
Related
This question already has answers here:
How do I reference a local image in React?
(28 answers)
Closed 6 months ago.
This post was edited and submitted for review 6 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I'm trying to set up a React project using WebPack by myself without using create-react-app or any other starters. I'm having trouble getting local images to load.
webpack.config.js
//webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: "./src/index.tsx",
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js'
},
devServer: {
port: 8080
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'ts-loader'
},
{
test: /\.(png|svg|jpg|jpeg|gif|webp)$/i,
type: 'asset/resource',
},
]
},
resolve:
{
extensions: [ '.tsx', '.ts', '.js' ],
},
plugins:[
new HtmlWebpackPlugin({
template: path.join(__dirname,'/src/index.html')
})
]
}
folder structure
index.tsx
//_index.js_
import React from "react";
import ReactDOM from "react-dom";
import HeroSwiper from "./components/HeroSwiper";
import LP from "./assets/img/LP.jpg";
import "./styles.css";
const App = () => {
return (
<div className="wrapper">
<img src={LP} alt="Slide 1" />
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
I'm getting a TS2307: Cannot find module './assets/img/LP.jpg' or its corresponding type declarations.
Use import method to import image then assign it to src of image tag
import LP from "./assets/img/LP.jpg";
...
<img src={LP} />
I am developing a npm package and use there webpack 5.
This is my config
const path = require('path') // resolve path
module.exports = {
mode: 'development',
resolve: {
extensions: ['.js', '.jsx'], // we can import without typing '.js or .jsx'
},
entry: {
index: path.join(__dirname, 'src/index.jsx'),
},
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index.js', // for production use [contenthash], for developement use [hash]
library: {
type: 'module',
},
environment: { module: true },
},
experiments: {
outputModule: true,
},
devtool: 'eval',
module: {
rules: [
{
test: /\.(css|scss|sass)$/,
use: [
{
loader: 'style-loader', // creates style nodes from JS strings
},
{
loader: 'css-loader', // translates CSS into CommonJS
},
{
loader: 'sass-loader', // compiles Sass to CSS
},
],
},
{
test: /\.(js|jsx)$/,
exclude: /nodeModules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.(png|svg|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
exclude:
/images/ /* dont want svg images from image folder to be included */,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'fonts/',
name: '[name][hash].[ext]',
},
},
],
},
],
},
externals: {
react: 'React',
'react-dom': 'ReactDOM',
},
plugins: [],
}
When I want to import components from this library I get this error:
Failed to resolve import "React" from "..my-package/dist/index.js". Does the file exist?
I think this has something to do with externals react and react-dom. But when I remove the externals from webpack config I get the error that react should be only installed once when using react hooks.
In my main application I am using vite for bundeling but I tried it also with create-react-app and have the same problem.
My Library Component:
import React, { useState } from 'react'
const App = () => {
const [counter, setCounter] = useState(0)
return <div>{counter}</div>
}
export default App
This is how I am using it with npm-link:
import React from "react";
import Test from "my-package";
const App = () => {
return <Test />;
};
export default App;
Here is the repo with the code https://github.com/guitar9/webpack-bug
I am trying to use koajs and reactjs to make a boilerplate application, to use later as a starting point for projects.
I am trying to use webpack as a means to compile my react jsx files, but I am getting this error:
ERROR in ./src/js/index.js 5:16
Module parse failed: Unexpected token (5:16)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import App from "./components/App";
|
> ReactDOM.render(<App />, document.getElementById('app'));
const path = require('path');
module.exports = {
mode: "development",
entry: './src/js/index.js',
loader: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}
}
]
},
output: {
path: path.join(__dirname, '/src/js'),
filename: 'index_bundle.js'
}
}
index.js:
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
ReactDOM.render(<App />, document.getElementById('app'));
module.exports = {
mode: "development",
entry: './src/js/index.js',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}
}
]
},
output: {
path: path.join(__dirname, '/src/js'),
filename: 'index_bundle.js'
}
}
I have a VueJS 2 application in which I'm trying to load specific components depending on different flags in a config JSON file.
My file structure is as follows:
root
config.json
> src
>> client
>>> components
>>>> dashboard
>>>>> MenuBarBrand.vue
> product
>> product01
>>> client
>>>> components
>>>>> branding
>>>>>> MenuBrand.vue
>> product02
>>> client
>>>> components
>>>>> branding
>>>>>> MenuBrand.vue
At the moment I've tried 2 different methods:
Using the webpack import syntax in my MenuBarBrand component:
<template>
<b-navbar-brand href="/dashboard">
<MenuBrand />
</b-navbar-brand>
</template>
<script>
import config from '../../../../config.json';
const MenuBrand = import(`../../../../product/${config.product}/components/branding/MenuBrand`);
export default {
name: 'MenuBarBrand',
components: {
'MenuBrand',
},
}
</script>
which results in the following error:
or the Vue Async Components local registration syntax:
<template>
<b-navbar-brand href="/dashboard">
<MenuBrand />
</b-navbar-brand>
</template>
<script>
import config from '../../../../config.json';
export default {
name: 'MenuBarBrand',
components: {
'MenuBrand': () => import(`../../../../product/${config.product}/components/branding/MenuBrand`)
},
}
</script>
which results in the following error:
Are there any clear errors that I'm making or are there any specific babel/webpack plugins needed to enable this functionality?
Edit: Adding my loader configuration based on a comment I received:
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: [
'vue-style-loader',
'css-loader',
'sass-loader',
],
sass: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax',
],
},
},
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
},
},
{
test: /\.css$/,
loader: 'style-loader!css-loader',
},
{
test: /\.(ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader?name=fonts/[name].[ext]',
},
],
},
I solved this through an alternate method.
In the webpack config I pull in my product flag and create a path:
const config = require('./config.json');
const fs = require('fs');
const path = require('path');
const productPath = path.resolve(__dirname, 'product', config.product);
Then I set up an alias in the webpack config using this path:
resolve: {
alias: {
menuBrandingPath: productPath,
},
extensions: ['*', '.js', '.vue', '.json'],
},
This path is then used in my Vue component to import the proper component:
<template>
<MenuBrand />
</template>
<script>
import MenuBrand from 'menuBrandingPath/client/components/branding/MenuBrand'; // menuBrandingPath is an alias in the webpack config
export default {
name: 'MenuBar',
components: {
MenuBrand,
},
}
</script>
I've intentionally left out error checking with fs and the fallback path I used to make this example easier to understand. Hopefully it helps someone! :)
You need to use the vue-loader webpack plugin to process the .vue-files in your webpack setup. That enables the () => import(...) syntax.
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
(other loaders....)
]
},
Or, using requireinstead in your original example:
<template>
<b-navbar-brand href="/dashboard">
<MenuBrand />
</b-navbar-brand>
</template>
<script>
import config from '../../../../config.json';
const MenuBrand = require(`../../../../product/${config.product}/components/branding/MenuBrand`);
export default {
name: 'MenuBarBrand',
components: {
'MenuBrand',
},
}
</script>
I am trying to extract SCSS to CSS on my react.js app using webpack plugin: extract-text-webpack-plugin. I am not getting any errors but i can't see any style on my page when i compile. In the following code i am simply trying to change the color of hello world rendered on the screen from black to red. Here are my files:
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
devtool: 'inline-source-map',
entry: [
'webpack-dev-server/client?http://127.0.0.1:8080/',
'webpack/hot/only-dev-server',
'./src/index.js',
'./sass/styles.scss'
],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
resolve: {
modules: ['node_modules', 'src'],
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: ['react-hot-loader', 'babel-loader']
},
{ // regular css files
test: /\.css$/,
loader: ExtractTextPlugin.extract({
loader: 'css-loader?importLoaders=1',
}),
},
{ // sass / scss loader for webpack
test: /\.(sass|scss)$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader'])
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new ExtractTextPlugin("styles.css")
]
};
styles.scss
$color : red;
.hello{
font-color: $color;
text-align: center;
}
app.js
import React from 'react';
export default class App extends React.Component {
render() {
return (
<div>
<h1 className = "hello">Hello World</h1>
</div>);
}
}
index.js
import React from 'react';
import { render } from 'react-dom';
import App from './components/app';
render ( <App />, document.getElementById('app'));
What i'm I missing?
you're missing style-loader from your loader chain.
from the sass-loader docs:
Chain the sass-loader with the css-loader and the style-loader to immediately apply all styles to the DOM.
// webpack.config.js
module.exports = {
...
module: {
rules: [{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
}]
}
};
you need import styles.scss in code index.js
import 'yourlink/styles.scss'