This question already has answers here:
Load images based on dynamic path in ReactJs
(4 answers)
Closed 5 years ago.
I want to have a global variable or something else so that i can easily change path if i need to. I would also like to have a different path when when i build it.
Is there a better way to import without using require?
const URL="./../../img";
//withURL doesn't work
export const logo1 = require(URL+ "/Global/logo1.png");
//this works but too long
export const logo2 = require("./../../img/Editorial/logo2.jpg");
Any idea? Is there a way in webpack that i can set this up?
Here is my webpack:
var webpack = require("webpack");
var path = require("path");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require("html-webpack-plugin");
var extractPlugin = new ExtractTextPlugin({
filename: "App.css"
});
module.exports = {
entry: './src/js/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['react', 'es2015']
}
}
]
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: ['css-loader']
})
},
{
test: /\.html$/,
use: ['html-loader']
},
{
test: /\.(png|jpg|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name:'[name].[ext]',
outputPath: 'img/'
}
}
]
}
],
},
plugins: [
extractPlugin,
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
This is something done through webpack with the url-loader plugin.
This plugin allows you to require a resource, like an image, and it returns a url for it.
import imageUrl from './url/image.png';
console.log(imageUrl) // "/public/path/0dcbbaa7013869e351f.png"
The url is the content hash of the resource, so that it can be long-term cached.
However, you also want that the path to the resource is generated on runtime. If you are using ES6 modules, you can't do that (well, you can using this syntax https://webpack.js.org/api/module-methods/#import-), but from your example, it seems you aren't since you use require. In that case, if you have correctly configured the url-loader, it seems your issue is with
const URL="./../../img";
export const logo1 = require(URL+ "/Global/logo1");
the path does not end on .png or some extension that has been defined in your webpack config. Did you try adding .jpg?
Related
I am using webpack and react js.
I am getting this error when i try to import image or font file inside my scss file.
I have tried many solutions but none of them solved my problem,
webpack.common.js
enter image description here
const path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
main: "./src/index.js",
vendor: "./src/vendor.js"
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: ["html-loader"]
},
{
test: /\.(ttf|svg|png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]",
outputPath: "imgs"
}
}
}
]
}
};
Here is another webpack.dev.js
module.exports = merge(common, {
mode: "development",
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist")
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/template.html"
})
],
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", //3. Inject styles into DOM
"css-loader", //2. Turns css into commonjs
"sass-loader" //1. Turns sass into css
]
}
]
}
});
ERROR in ./src/assets/index.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/lib/loader.js!./src/assets/index.scss)
Module not found: Error: Can't resolve '../../../src/assets/fonts/icomoon.ttf' in 'C:\Users\jamal\Documents\webpack-demo-app\src\assets'
# ./src/index.js
# multi (webpack)-dev-server/client?http://localhost:8080 ./src/index.js
You need to remember that the import actually takes "place" from the root index.scss file (the one that loads all the other partials). So the path you are using to fetch the asset is not accurate.
You need to use ./fonts/icomoon.ttf instead of ../fonts/icomoon.ttf
your file structure:
assets/
------/fonts
------/images
------/sass
------/---/partial1.scss // while the reference to the image is here
------/index.scss // the actual root of the reference call is here
Recently we found out that we have to use SSR for Our React Project.
I have checked with every method that I know and almost tested all methods that I've found on medium and other sites. And after a lot of work, I decided that we have to migrate to Next JS.
While the process of migrating everything is fine, but for the style sheets.
In the old version of our app, we used webpack to bundle our styles with the project and everything was fine.
This is the webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const port = process.env.PORT || 3000;
const extractSCSS = new ExtractTextPlugin('./[name].css');
// const UglifyJS = require('uglifyjs-webpack-plugin');
module.exports = {
mode: 'development',
output: {
filename: 'bundle.[hash].js',
publicPath: '/'
},
devtool: 'source-map',
module: {
rules: [
// First Rule
{
test: /\.(js)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
// Second Rule
{
test: /\.scss$/,
use: ['css-hot-loader'].concat(extractSCSS.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader?sourceMap',
options: { alias: { '../img': '../public/img' }, sourceMap: true }
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
}))
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
favicon: 'public/favicon.ico'
}),
extractSCSS,
],
devServer: {
host: 'localhost',
port: port,
historyApiFallback: true,
open: true
}
};
and after I migrated the app, my next.config.js looks like this:
// next.config.js
const withSass = require('#zeit/next-sass')
const withCSS = require('#zeit/next-css')
module.exports = withCSS( withSass(
{
webpack(config, options) {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000
}
}
},
)
return config
},
}
))
The problem is that everything renders correctly but there are no stylesheets in it and it doesn't contain any style. Is there anybody who could help me to solve this problem?
For just using CSS from node_modules you don't need this fancy config.
3 simple steps:
Install next-css plugin:
npm install --save #zeit/next-css
Create in your root directory next.config.js with the following content:
// next.config.js
const withCSS = require('#zeit/next-css')
module.exports = withCSS({
cssLoaderOptions: {
url: false
}
})
Now you should be able to import styleshets from node_modules like this:
import 'bootstrap-css-only/css/bootstrap.min.css';
Note: Using Next v 8+
Background:
I spent a few hours trying to simply import a CSS installed as a node_module and the various solutions are mostly hacky workarounds, but as shown above, there is a simple solution.
It was provided by one of the core team members: https://spectrum.chat/next-js/general/ignoring-folders-files-specifically-fonts~4f68cfd5-d576-46b8-adc8-86e9d7ea0b1f
This is not a real answer but CSS in Next.js is just SUCKS! I find myself constantly struggle to make it work so what I decided is to follow their docs and simply use:
const App = () => {
return (
{style}
<div/>
);
}
let style = (<style jsx>
{`
.someClass {}
`}
</style> )
export default App;
This way you can have CSS as you might have in regular HTML without any external imports
source
You don't need both withCSS & withSass plugins.
If you are using Sass the withSass plugin will compile it to CSS.
Just make sure you add the path to the CSS file in your _document.js file inside the Head component like this:
<Head>
<link rel="stylesheet" href="/_next/static/style.css" />
</Head>
For importing css you can use Head component of the nextJS.
import Head from 'next/head';
<Head>
<link rel="stylesheet" href="path of the css" />
</Head>
I'm trying to set up a developer environment for React but I'm getting some issues with webpack pathing. Usually, a quick google solves issues like these but I haven't seen anyone with the same problem, which probably means I'm an idiot and is messing something up.
So, I followed a tutorial and I have a dev-folder and a output-folder. In output I have output.js, where I want webpack to output all my stuff. So, according to the guide, I should run ./node_modules/.bin/webpack and it should work with the config I have, but it's showing the wrong filepath. I want it to go to react-test/output/output.js but it's throwing in a /dev, making it react-test/dev/output/output.js. My webpack.config.js looks like this:
var webpack = require("webpack");
var path = require("path");
var DEV = path.resolve(__dirname, "dev");
var OUTPUT = path.resolve(__dirname, "output");
var config = {
entry: DEV + "/index.jsx",
output: {
path: OUTPUT,
filename: "output.js"
},
module: {
loaders: [{
include: DEV,
loader: "babel-loader"
}]
}
};
module.exports = config;
I can't see where dev is getting added.
I would modify the file to the following:
var path = require('path');
module.exports = {
entry: path.join(__dirname, '/dev/index.js'),
output: {
path: path.join(__dirname, '/output'),
filename: 'output.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015']
}
}
]
}
};
You don't need to require webpack in this file, but you do need to tell the module loader what to test. The presets I included are assuming you are using ReactJS and ES6, you may need to change them as appropriate.
webpack.config
var path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: './dev/index.js',
output: {
path: path.resolve(__dirname, 'output'),
filename: 'output.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
},
devServer: {
historyApiFallback: true
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/Index.html' // Copy Index.html with script tag refrencing output.js in Output folder
})
]
}
Try to set context option to react-test directory.
And set DEV and OUTPUT paths realtive to it:
var DEV = path.resolve(__dirname, "./dev");
var OUTPUT = path.resolve(__dirname, "./output");
var config = {
context: path.resolve(__dirname, './'),
entry: DEV + "/index.jsx",
output: {
path: OUTPUT,
filename: "output.js"
},
...
I am trying to use react-datetime on my react-on-rails app. To make the datetime work out of the box, I need to import the CSS mentioned on their GH page.
On my app, I copy/paste the CSS into a file I named DateTime.css:
...
import DateTime from 'react-datetime';
import '../../schedules/stylesheets/DateTime.css';
...
export default class AddDate extends React.Component {
But it gives me this error:
VM45976:1 Uncaught Error: Module parse failed: /Users/some/path/to/my/project/App/components/schedules/stylesheets/DateTime.css Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| .rdt {
| position: relative;
| }
It seems like the CSS loader is not working. I tried this on pure react app (create-react-app) and it worked. It broke when I did it inside react_on_rails.
This is my webpack config atm (standard out-of-the-box react_on_rails):
const webpack = require('webpack');
const { resolve } = require('path');
const ManifestPlugin = require('webpack-manifest-plugin');
const webpackConfigLoader = require('react-on-rails/webpackConfigLoader');
const configPath = resolve('..', 'config');
const { devBuild, manifest, webpackOutputPath, webpackPublicOutputDir } =
webpackConfigLoader(configPath);
const config = {
context: resolve(__dirname),
entry: {
'webpack-bundle': [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
'./app/bundles/App/startup/registration',
],
},
output: {
// Name comes from the entry section.
filename: '[name]-[hash].js',
// Leading slash is necessary
publicPath: `/${webpackPublicOutputDir}`,
path: webpackOutputPath,
},
resolve: {
extensions: ['.js', '.jsx'],
},
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'development', // use 'development' unless process.env.NODE_ENV is defined
DEBUG: false,
}),
new ManifestPlugin({ fileName: manifest, writeToFileEmit: true }),
],
module: {
rules: [
{
test: require.resolve('react'),
use: {
loader: 'imports-loader',
options: {
shim: 'es5-shim/es5-shim',
sham: 'es5-shim/es5-sham',
},
},
},
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: 'css-loader',
exclude: /node_modules/,
},
],
],
},
};
module.exports = config;
if (devBuild) {
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map';
} else {
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}
I am very new in webpack, and not sure how to I can add loaders to make it work, how can I apply the DateTime.css file that I have to be applied to react-datetime?
EDIT: added css-loader (also updated the webpack above). It is no longer complaining that I don't have the correct loader, but the CSS does not work.
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: 'css-loader',
exclude: /node_modules/,
},
],
There are 2 conceptually different ways to approach this.
1. Using CSS modules.
This way your CSS will end up bundled with your JS and as soon as webpack loads that JS module/bundle it will automatically append CSS style element into the head.
In my project I have this rule to do exactly that (note that we use both css-loader and style-loader):
{
test: /\.css$/,
use: ['style-loader', {
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
}
}]
}
More on css-loader modules at this link.
2. Using ExtractTextPlugin. This way all your CSS will be extracted into a separate file. The configuration requires 2 things: a plugin and loaders configuration created by the plugin:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
// Add this to your webpack plugins array
new ExtractTextPlugin('styles.css')
And add this to your rules:
{
test: /\.css$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader']
})
}
This will create one single styles.css file and put all CSS you import from JS into that file.
My app.js requires react.
I am following the following instructions to split the app and react code: https://webpack.github.io/docs/code-splitting.html#split-app-and-vendor-code.
Unfortunately, webpack generate app.bundle.js and vendors.bundle.js; both contains react.js library, which is not desired.
I am expecting webpack to generate a small app.bundle.js(which does not contains react) and a large vendor.js(which contains react), according to the link post above.
My webpack configure file:
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: {
app: "./app.js",
vendors: ['react']
},
output: {
filename: '[name].bundle.js' // Notice we use a variable
},
plugin: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendors", /* filename= */"vendor.js")
],
module: {
preLoaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'source-map'
}
],
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loaders: [
'react-hot',
'babel?presets[]=stage-0,presets[]=react,presets[]=es2015'
]
}
]
}
};
My app.js file:
// Import React and JS
var React = require('react')
React.render(
React.createElement('h1', null, 'Hello, world!'),
document.getElementById('example')
);
Any suggestion is highly appreciated.
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendors", /* filename= */"vendor.js")
]
Use plugins, not plugin.