How to bundle dynamic image path using webpack - reactjs

webpack works well with import syntax.
import image1 from '../public/assets/image1.png'
image1.png is bundled successfully.
But I want to pass the image src using props like below.
const paths = ['../public/assets/image1.png','../public/assets/image2.png']
const Parent = () => {
return (
<div>
<Child srcPath={path[0]} />
</div>
);
};
const Child = ({srcPath}) => {
return (
<img src={srcPath} />
)
}
webpack not bundle png files.
How do I let webpack bundle without import syntax?
My webpack version is 5.24.3 and this is my webpack.config.js
// webpack.config.js
module.exports = {
mode: "development",
entry: { index: path.resolve(__dirname, "src", "app.tsx") },
output: {
path: path.resolve(__dirname, "build"),
assetModuleFilename: "images/[hash][ext][query]",
},
resolve: { extensions: [".ts", ".tsx", ".js"] },
module: {
rules: [
{ test: /\.tsx?$/, loader: "ts-loader" },
{ test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "asset/resource" },
],
},
plugins: [
new HtmlWebpackPlugin({
template: "public/index.html",
}),
],
devServer: {
contentBase: path.join(__dirname, "build"),
host: "localhost",
port: port,
historyApiFallback: true,
hot: true,
},
};

Related

Cannot find module Error (React, TypeScript, Webpack)

Want to run app, but get the following error:
This is my project structure:
this is my app module
i use export and also export default are same:
app component
and the imports of the module:
My webpack :
const devSever = (isDev) => !isDev ? {} : {
devServer: {
open: true,
hot: true,
port: 7070,
contentBase: path.join(__dirname,'public')
}
};
const esLintPlugin = (isDev) => isDev ? [] : [new ESLintPlugin({ extensions: ['.ts', '.tsx ','.js']}) ]
module.exports = ({develop}) => ( {
mode: develop ? 'development': 'production',
devtool: develop ? 'inline-source-map' : false,
entry:{
app: './src/index.tsx',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
assetModuleFilename: 'assets/[hash][ext]' //may be hash
},
module: {
rules: [
{
test: /\.(ts|tsx|js)$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.(?:ico|gif|png|jpg|jpeg|svg)$/i,
type: 'asset/resource'
},
{
test: /\.(woff(2)?|eot|ttf|otf)$/i,
type: 'asset/resource'
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader,'css-loader']
}
]
},
resolve: {
extensions: ['.tsx','.ts','.js']
},
plugins: [
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/,
include: /dir/,
failOnError: true,
allowAsyncCycles: false,
cwd: process.cwd()
}),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'style.css'
}),
new CopyPlugin({
patterns: [{from: './public' }]
}),
new CleanWebpackPlugin({cleanStaleWebpackAssets: false}),
...esLintPlugin(develop)
],
...devSever(develop)
});
it's all work good only if there are not imports and if i write code only in one component
you check out tsconfig.json
{
"include": ["src/**/*"],
"compilerOptions": {
"rootDir": "./src"
}
}

Webpack 5 Aliases not resolving correctly

I've just updated my project from webpack 3 to 5 and now none of my imports/aliases are working anywhere.
Webpack is in the root directory.
webpack.config.js Below:
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
var mode = process.env.NODE_ENV || 'development';
const config = {
entry: {
main: path.resolve(__dirname, 'src/index.js'),
Dashboard: path.resolve(__dirname, 'src/shared/pages/dashboard/index.js'),
Driver: path.resolve(__dirname, 'src/shared/pages/driver/index.js'),
Drivers: path.resolve(__dirname, 'src/shared/pages/drivers/index.js'),
FAQ: path.resolve(__dirname, 'src/shared/pages/faq/index.js'),
Home: path.resolve(__dirname, 'src/shared/pages/home/index.js'),
Job: path.resolve(__dirname, 'src/shared/pages/job/index.js'),
Jobs: path.resolve(__dirname, 'src/shared/pages/jobs/index.js'),
Signin: path.resolve(__dirname, 'src/shared/pages/signin/index.js')
} ,
// performance: {
// hints: "error"
// },
output: {
filename: '[name].[contenthash].js'
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor:{
test: /[\\/]node_modules[\\/]/,
name(module){
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
return `npm.${packageName.replace('#', '')}`;
}
}
}
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.s(a|c)ss$/,
use: [ 'style-loader', 'css-loader','sass-loader'],
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
use: 'url-loader?limit=100000'
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'bundle.scss'}
),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
],
resolve: {
alias: {
shared: path.resolve(__dirname, 'src/shared/'),
client: path.resolve(__dirname, 'src/client/'),
server: path.resolve(__dirname, 'src/server/'),
sass: path.resolve(__dirname, 'src/sass/')
},
extensions: ['.js', '.sass', '.scss']
},
devtool: (mode === 'development') ? 'inline-source-map' : false,
mode: mode,
devServer: {
disableHostCheck: true,
historyApiFallback: true,
inline: true,
contentBase: path.join(__dirname, "dist"),
publicPath: '/provider/',
hot: true,
proxy: {
'/api/**': {
target: 'http://localhost:3333/',
secure: false,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
};
module.exports = config;
Example Import that isn't working:
import { meFromToken } from 'shared/actions/user'
Change that fixes it:
import {meFromToken} from '../../actions/user'
What am I doing wrong? I don't want to refactor all our imports because the aliases aren't resolving properly.
You'd need to add the same config for tsconfig.json or jsconfig.json
Eg:
{
"compilerOptions": {
"baseUrl": ".",
"module": "commonjs",
"paths": {
"#shared/*": ["./src/shared/*"]
}
}
}

Webpack in React can't load the 3D model with a GLTF extension, shows 404 not found

I'm trying to load the 3D model with the .gltf extension in React with Typescript. The files in folder with 3D model are .gltf, .png and .bin files. The tools used for this task are webpack and useGLTFLoader from drei library. I've tried different tools. Mainly from three.js library with no effect. Error is showing that the 3D model is not found 404 (shown below) and nothing appears in place where 3D model should be placed.
GET http://localhost:3000/assets/models/Duck/glTF/Duck.gltf 404 (Not Found)
My component for rendering the 3D model is shown below:
import React, { Suspense } from 'react';
import { Canvas } from 'react-three-fiber';
import { useGLTFLoader } from 'drei';
const DuckModel = () => {
const gltf = useGLTFLoader('../../assets/models/Duck/glTF/Duck.gltf', true);
return <primitive object={gltf.scene} dispose={null} />;
};
export const ThreeDimensionComponent = () => {
return (
<>
<Canvas camera={{ position: [0, 0, 10], fov: 70 }}>
<Suspense fallback={null}>
<mesh position={[0, 250, 0]}>
<DuckModel />
</mesh>
</Suspense>
</Canvas>
</>
);
};
And below I share my webpack config.
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const root = __dirname;
const gsapPath = '/node_modules/gsap/src/uncompressed/';
module.exports = {
devtool: 'source-map',
mode: 'development',
entry: path.join(__dirname, 'src', 'index.tsx'),
watch: true,
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
sourceMapFilename: '[name].js.map'
},
module: {
rules: [
{
test: /\.(tsx|ts)$/,
use: ['babel-loader', 'ts-loader', 'tslint-loader']
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')()],
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /\.(png|jp(e*)g|svg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8000,
sourceMap: true
}
}
]
},
{
test: /\.(ttf|eot|woff|woff2)$/,
use: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]',
sourceMap: true
}
}
},
{
test: /\.(glb|gltf)$/,
use: [
{
loader: 'file-loader'
// options: {
// outputPath: 'assets/models'
// }
}
]
},
{
test: /\.(bin)$/,
use: [
{
loader: 'file-loader'
}
]
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
modules: ['node_modules', path.resolve(__dirname, 'src')],
alias: {
TweenLite: 'gsap',
CSSPlugin: 'gsap',
Draggable: path.join(root, gsapPath + 'utils/Draggable.js'),
ScrollToPlugin: path.join(root, gsapPath + 'plugins/ScrollToPlugin.js')
}
},
devServer: {
historyApiFallback: true,
contentBase: './dist',
inline: true,
host: 'localhost',
port: 3000
},
plugins: [
new CleanWebpackPlugin({ verbose: true }),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html')
}),
new webpack.ProvidePlugin({
TweenMax: 'gsap'
}),
new CopyWebpackPlugin({
patterns: [{ from: 'src/assets' }]
})
]
};
My webpack.config.js file is in the root directory for the project. The assets folder is in the src folder. Lastly the file with React code is in src/components/ThreeDimensionComponent/ThreeDimensionComponent.tsx (so path for it is correct).
You either need to import the model and use the url you get from that (url-loader), or put it into the public folder. Your path points nowhere in the bundled output.
One more thing, it's #react-three/drei and useGLTF(url).
Here is a working example with a loaded 3D model in case anyone needed it. I marked an answer from hpalu as correct because it helped me to solve this problem.
I needed to use Suspense with a fallback that isn't an HTML element but instead is a component from react-three-fiber.
The post that also has helped me to solve the bug:
https://spectrum.chat/react-three-fiber/general/hello-im-trying-to-use-the-texture-loader-with-suspense~a9671405-3b8a-4486-a319-cad820347ddc?m=MTU4NDExMzIyMTMwOA==
Here is React component:
import { useGLTF } from '#react-three/drei';
import React, { Suspense } from 'react';
import { Canvas } from 'react-three-fiber';
const DuckModel = () => {
const gltf = useGLTF('./models/Duck/glTF/Duck.gltf', true);
return <primitive object={gltf.scene} dispose={null} />;
};
export const ThreeDimensionComponent = () => {
return (
<>
<Canvas camera={{ position: [0, 0, 3], fov: 80 }}>
<ambientLight intensity={0.3} />
<Suspense
fallback={
<mesh>
<boxBufferGeometry args={[1, 1, 1]} />
<meshStandardMaterial />
</mesh>
}
>
<DuckModel />
</Suspense>
</Canvas>
</>
);
};
And here is the webpack config for this example:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const gsapPath = '/node_modules/gsap/src/uncompressed/';
module.exports = {
devtool: 'source-map',
mode: 'development',
entry: path.join(__dirname, 'src', 'index.tsx'),
watch: true,
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
sourceMapFilename: '[name].js.map',
publicPath: '/'
},
module: {
rules: [
{
test: /\.(tsx|ts)$/,
use: ['babel-loader', 'ts-loader', 'tslint-loader']
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')()],
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /\.(png|jp(e*)g|svg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8000,
sourceMap: true
}
}
]
},
{
test: /\.(ttf|eot|woff|woff2)$/,
use: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]'
// sourceMap: true
}
}
},
{
test: /\.(glb|gltf)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'assets/models',
sourceMap: true
}
}
]
},
{
test: /\.(bin)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'assets/models',
sourceMap: true
}
}
]
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
modules: ['node_modules', path.resolve(__dirname, 'src')],
alias: {
TweenLite: 'gsap',
CSSPlugin: 'gsap',
Draggable: path.join(__dirname, gsapPath + 'utils/Draggable.js'),
ScrollToPlugin: path.join(__dirname, gsapPath + 'plugins/ScrollToPlugin.js')
}
},
devServer: {
historyApiFallback: true,
contentBase: './dist',
inline: true,
host: 'localhost',
port: 3000
},
plugins: [
new CleanWebpackPlugin({ verbose: true }),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html')
}),
new webpack.ProvidePlugin({
TweenMax: 'gsap'
}),
new CopyWebpackPlugin({
patterns: [{ from: 'src/assets' }]
})
]
};

On starting Styleguidedist server it fails with Module parse failed: Unexpected token

Im trying to start my style guide server but it keeps throwing following error:
I believe this occurs when the babel loaders are not configured for jsx files. But this isnt true as I am able to start my project without errors. But when I try to start the style guide I end up with this.
Here is my styleguide config file
module.exports = {
title: 'Component Library',
webpackConfig: Object.assign(
{},
require("./config/webpack/webpack.dev.config.js"),
{
/* Custom config options if required */
}
),
components: "source/components/**/*.jsx",
template: {
head: {
links: [
{
rel: "stylesheet",
href:
"https://fonts.googleapis.com/css?family=Poppins:400,400i,600,600i,700,700i&display=swap"
}
]
}
},
theme: {
fontFamily: {
base: '"Poppins", sans-serif'
}
},
styles: function styles(theme) {
return {
Playground: {
preview: {
backgroundColor: '#29292e'
},
},
Code: {
code: {
fontSize: 14,
},
},
};
},
};
Here is my webpack config
var webpack = require('webpack');
var path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// const InterpolateHtmlPlugin = require('interpolate-html-plugin');
const WebpackAssetsManifest = require('webpack-manifest-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const reactLoadablePlugin = require('react-loadable/webpack')
.ReactLoadablePlugin;
const workboxPlugin = require('workbox-webpack-plugin');
module.exports = (env) => ({
mode: 'development',
entry: path.join(__dirname, '../../index.js'),
output: {
filename: '[name].bundle.[hash].js',
chunkFilename: '[name].bundle.[hash].js',
path: path.join(__dirname, '../../../build'),
publicPath: '/'
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
// cacheGroupKey here is `commons` as the key of the cacheGroup
name(module, chunks, cacheGroupKey) {
const moduleFileName = module
.identifier()
.split('/')
.reduceRight(item => item);
const allChunksNames = chunks.map(item => item.name).join('~');
return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`;
},
chunks: 'all'
}
}
}
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: path.resolve(__dirname, 'node_modules'),
loader: 'babel-loader'
},
{
test: /\.svg(\?.*)?$/, // match img.svg and img.svg?param=value
use: [
'url-loader', // or file-loader or svg-url-loader
'svg-transform-loader'
]
},
{
test: /\.png(\?.*)?$/, // match img.svg and img.svg?param=value
use: [
'url-loader', // or file-loader or svg-url-loader
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
javascriptEnabled: true
}
}
]
},
{
test: /\.(sa|sc|c)ss$/,
exclude: path.resolve(__dirname, 'node_modules'),
use: [
'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
resolve: {
extensions: ['.js', '.jsx']
},
plugins: [
new webpack.EnvironmentPlugin({
APP_ENVIRONMENT: process.env.APP_ENVIRONMENT,
API_KEY: process.env.API_KEY,
AUTH_DOMAIN: process.AUTH_DOMAIN,
DB_URL: process.env.DB_URL,
PROJECT_ID: process.env.PROJECT_ID
}),
new CleanWebpackPlugin({
path: path.join(__dirname, '../../../build')
}),
new WebpackAssetsManifest({
fileName: 'asset-manifest.json'
}),
new HtmlWebpackPlugin({
title: '<<app>>',
template: 'main.html',
minify: {
collapseWhitespace: false,
removeComments: true,
useShortDoctype: false
}
}),
new MiniCssExtractPlugin({
filename: 'style.[contenthash].css'
}),
new CopyPlugin([
{
from: 'public',
to: 'public'
}
]),
new ProgressBarPlugin({
format: ' build [:bar] ' + ':percent' + ' (:elapsed seconds)' + ' :msg'
}),
new reactLoadablePlugin({
filename: './react-loadable.json'
}),
new workboxPlugin.InjectManifest({
swSrc: path.join(__dirname, '../../public/service-worker.js')
})
],
devServer: {
contentBase: path.join(__dirname, '/'),
filename: 'main.html',
compress: true,
port: 3000,
historyApiFallback: true,
disableHostCheck: true,
useLocalIp: true,
host: '0.0.0.0'
},
devtool: 'eval-source-map'
});
The problem was with the webpack file I was exporting the webpack configurations as a function.
Earlier:
module.exports = (env) => ({
....your webpack configurations
})
Instead of exporting everything as a function I exported it as
Now:
module.exports = {
....your webpack configurations
}
But can someone tell me why the earlier implementation didnt work?

Enable source maps in Webpack

I have a problems with souce maps. They are generated but apparently not used.
I use webpack-dev-server, react hot module replacement and Webpack v3.x if that is important.
Inside of my webpack-config i use devtool: 'source-map' and I run my script like this:
"webpack": "cross-env NODE_ENV=development webpack-dev-server -d --config webpack.config.js"
Example of error that I get
When I click on this client?e36c:157 it doesn't take me to source code but:
If I remove devtools from webpack.config and -d tag from script I get the same output
**webpack.config.js**
const path = require('path')
const webpack = require('webpack')
const publicPath = path.resolve(__dirname, './src/client')
const buildPath = path.resolve(__dirname, './src')
// const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
const Write = require('write-file-webpack-plugin')
process.noDeprecation = true
module.exports = {
devtool: 'source-map',
performance: {
hints: false,
},
devServer: {
hot: true,
port: 3001,
host: 'localhost',
/* Needed only if using Browsersync */
headers: { 'Access-Control-Allow-Origin': '*', },
proxy: {
'**': {
target: 'http://localhost:3000',
secure: false,
changeOrigin: true,
},
},
},
context: publicPath,
entry: {
bundle: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:3001',
'webpack/hot/only-dev-server',
'script-loader!jquery/dist/jquery.min.js',
'script-loader!tether/dist/js/tether.min.js',
'script-loader!bootstrap/dist/js/bootstrap.min.js',
'./app.js',
],
},
output: {
path: path.join(buildPath, 'dist'),
filename: '[name].js',
publicPath: 'http://localhost:3001/',
},
resolve: {
extensions: [ '.js', '.jsx', ],
alias: {
// Container
Container: path.resolve(__dirname, 'src/client/scenes/Container.jsx'),
// Components
FormComponent: path.resolve(
__dirname,
'src/client/scenes/feature/components/FormComponent.jsx'
),
Feature: path.resolve(__dirname, 'src/client/scenes/feature/Feature.jsx'),
TitleComponent: path.resolve(
__dirname,
'src/client/scenes/home/components/TitleComponent.jsx'
),
Home: path.resolve(__dirname, 'src/client/scenes/home/Home.jsx'),
Navigation: path.resolve(__dirname, 'src/client/scenes/shared/navigation/Navigation.jsx'),
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules|dist|build/,
loader: 'babel-loader',
options: {
babelrc: true,
},
},
{
test: /\.local\.(css|scss)$/,
use: [
'style-loader',
'css-loader?sourceMap&modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'postcss-loader?sourceMap',
'sass-loader?sourceMap',
{
loader: 'sass-resources-loader',
options: {
resources: [
path.resolve(__dirname, './src/client/styles/scss/variables.scss'),
],
},
},
],
},
{
test: /^((?!\.local).)+\.(css|scss)$/,
use: [
'style-loader',
'css-loader?sourceMap',
'postcss-loader?sourceMap',
'sass-loader?sourceMap',
],
},
{
test: /\.(gif|png|jpg)$/,
/* We can specify custom publicPath if needed */
loader: 'url-loader',
},
],
},
plugins: [
new Write(),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
}),
],
}

Resources