Few confusions and queries on webpack workflow on React - reactjs

I'm getting started with React 15. After going through tutorial and reading a few articles, I've come up with a few questions about the workflow. Here's how my index and webpack files look.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lugmety.com | The fastest, Most convenient way to order from the finest restaurants in Jeddah.</title>
<link rel="shortcut icon" href="assets/images/lugmety-favicon.png">
<link rel="stylesheet" href="assets/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<div id="app"></div>
<script src="assets/js/jquery.min.js"></script>
<script src="assetsjs/bootstrap.min.js"></script>
<script src="assets/js/scripts.js"></script>
<script src="/bundle.js"></script>
</body>
</html>
webpack.config.js
let webpack = require("webpack");
let path = require("path");
let DIST_DIR = path.resolve(__dirname,"dist");
let SRC_DIR = path.resolve(__dirname,"src");
let config = {
entry: SRC_DIR + "/index.js",
output: {
path: DIST_DIR + "/",
filename: "bundle.js",
publicPath: "/"
},
module:{
loaders:[
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.js?/,
include: SRC_DIR,
loader: "babel-loader",
query: {
presets:["react", "es2015", "stage-2"]
}
}
]
}
};
module.exports = config;
Here is my index.html file.
Does the compilation compile scripts like jquery.js, bootstrap.js and custom scripts for eg. script.js and include it in the compiled bundle.js?
In development, my images are located in src/assets/img/. I can't see the compiler copying assets into the dist folder.
From where do I set the relative paths for the CSS and JS files in index.html and the images within components? For eg. <img src="/assets/img/image.jpg"> OR <img src="/src/assets/img/image.jpg">
Thanks a lot for your time.

No in your case it won't be included in bundle.js because you are not using npm modules for bootstrap and jquery. You can try this way to include in your dev dependencies :
npm i -D bootstrap jquery
You don't need to copy assets to the dist folder. Webpack is a module bundler and everything you reference in your files will be included. You just need to specify a loader for that.For your reference :
How to copy static files to build directory with Webpack?
I don't really get the question but ofcourse you will set the path for css in the index.html for css you just have to import it with relative path. For example :
import App from './App'

Related

share react components and include with script tag instead package.json

I have 3 npm react projects: App1, App2, Shared.
Usecase 1.
In the moment I use npm with lerna and webpack5.
App1 and App1 loads the bundle for Shared in package.json: "shared-components": "file:../shared-components" and I can import components from Shared easy with:
import { Button, Headline } from 'shared-components'
and all works fine.
Usecase 2.
Now I have another simple html project(no npm, no react, just plain html and JavaScript):
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Titel </title>
</head>
<body>
<button>button</button>
<h1>h1</h1>
</body>
</html>
and want to replace button and h1 with micro react apps:
MicroApp1 is a single react project which imports the Button from Shared
MicroApp2 is a single react project which imports the Headline from Shared
The problem is now that both MicroApps have a large bundle which includes Shared.
The goal is to load the Shared project separately:
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Title</title>
</head>
<body>
<div id="app1-container"></div>
<div id="app2-container"></div>
<script type='text/javascript' src='bundle-of-shared'/>
<script type='text/javascript' src='bundle-of-app1'/>
<script type='text/javascript' src='bundle-of-app2'/>
</body>
</html>
I know about webpack external, dynamic imports and codesplitting but none can implement my use case.
The truth is not so simple as described, but rather: How To Gradually Introduce React.js in an Old Application...
Here the code piece from webpack.config of the Shared project:
entry: path.resolve(__dirname, './src/index.js'),
output: {
filename: "index.js",
path: path.resolve(__dirname, 'bundle'),
libraryTarget: "umd",
},
target: ['web', 'es5'],
module: {
rules: [
{
test: /\.(js|jsx|es6)$/,
use: {
loader: 'babel-loader'
},
exclude: path.resolve(__dirname, 'node_modules/')
},
Its works fine for Usecase1.
I could imagine to change the libraryTarget to use the bundle in a html script tag?

Can't load assets from public folder in development mode in webpack

I am new to webpack. I am trying to access my assets file outside of the src folder during development mode. The only solution I found in the internet is using copy-webpack-plugin. But I think that is for build. But since I am in development mode all things will load into memory. I might be wrong.
This is my file structure right now
File Sturcutre
And I am trying to access those file in index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="Fuse React - Material design admin template with pre-built apps and pages" />
<meta
name="keywords"
content="React,Redux,Material UI Next,Material,Material Design,Google Material Design,HTML,CSS,Firebase,Authentication,Material Redux Theme,Material Redux Template"
/>
<meta name="author" content="Withinpixels" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="theme-color" content="#000000" />
<base href
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<link href="%PUBLIC_URL%/assets/fonts/material-design-icons/MaterialIconsOutlined.css" rel="stylesheet" />
<!-- <link href="%PUBLIC_URL%/assets/fonts/material-design-icons/MaterialIcons.css" rel="stylesheet">-->
<!-- <link href="%PUBLIC_URL%/assets/fonts/material-design-icons/MaterialIconsRound.css" rel="stylesheet">-->
<!-- <link href="%PUBLIC_URL%/assets/fonts/material-design-icons/MaterialIconsSharp.css" rel="stylesheet">-->
<!-- <link href="%PUBLIC_URL%/assets/fonts/material-design-icons/MaterialIconsTwoTone.css" rel="stylesheet">-->
<link href="%PUBLIC_URL%/assets/fonts/meteocons/style.css" rel="stylesheet" />
<noscript id="jss-insertion-point"></noscript>
<title>Fuse React - Material Design Admin Template</title>
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root" class="flex">
<!-- FUSE Splash Screen -->
<div id="fuse-splash-screen">
<div class="center">
<div class="logo">
<img width="128" src="assets/images/logos/fuse.svg" alt="logo" />
</div>
<!-- Material Design Spinner -->
<div class="spinner-wrapper">
<div class="spinner">
<div class="inner">
<div class="gap"></div>
<div class="left">
<div class="half-circle"></div>
</div>
<div class="right">
<div class="half-circle"></div>
</div>
</div>
</div>
</div>
<!-- / Material Design Spinner -->
</div>
</div>
<!-- / FUSE Splash Screen -->
</div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
And this is my webpack config file
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const PUBLIC_DIR = path.join(__dirname, './public');
const PUBLIC_URL = process.env.PUBLIC_URL || '/';
const HTML_TEMPLATE = 'index.html';
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, '/dist'),
filename: 'index_bundle.js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.(jpg|jpeg|png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
},
{
test: /\.css$/,
use: [
'style-loader',
// MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [require('tailwindcss'), require('autoprefixer')]
}
}
]
}
]
},
plugins: [
// new HtmlWebpackPlugin(),
new HtmlWebpackPlugin({
// template: `${PUBLIC_DIR}/${HTML_TEMPLATE}`,
template: './public/index.html',
filename: 'index.html',
templateParameters: {
PUBLIC_URL
}
})
// new MiniCssExtractPlugin()
],
resolve: {
alias: {
'#fuse': path.resolve(__dirname, './src/#fuse/'),
'#history': path.resolve(__dirname, './src/#history/'),
'#lodash': path.resolve(__dirname, './src/#lodash'),
i18n: path.resolve(__dirname, './src/i18n'),
app: path.resolve(__dirname, './src/app/')
}
}
};
NB: I am using react#17.0.2, webpack#4.43.0
Webpack just loads images that was in the webpack flow... If you want to copy extra assets you will need plugins like copy-webpack-plugin as you say.
loaders:
{
test: /\.(jpg|jpeg|png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
}
Just would copy the *..(jpg|jpeg|png|woff|woff2|eot|ttf|svg) files that are imported in tree generated by the entry (entry: './src/index.js'). In your case the image was imported in the index.html file, which is not in the file tree generated by the webpack entry. If you import that image on './src/index.js' you will see the image in the output folder dist

Webpacker build error, space between the word 'loader' as 'lo ader.js'

I keep getting the same error. I have not touched Webpacker for the past 5 builds, and suddenly getting errors for a small change in some simple code. Really starting to baffle me.
I seem to be getting a space in the word 'loader', on the 'ERROR in Error line (4). I feel that is the cause.
Here is the output error:
WARNING in webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
ERROR in Error: The loader "/usr/src/app/client/node_modules/html-webpack-plugin/lib/lo ader.js!/usr/src/app/client/public/index.html" didn't return html.
- index.js:330 HtmlWebpackPlugin.evaluateCompilationResult
[client]/[html-webpack-plugin]/index.js:330:24
- index.js:237
[client]/[html-webpack-plugin]/index.js:237:22
- runMicrotasks
- task_queues.js:93 processTicksAndRejections
internal/process/task_queues.js:93:5
- async Promise.all
- async Promise.all
webpack 5.22.0 compiled with 1 error and 3 warnings in 38437 ms
Webpack Configuration:
const path = require("path");
const webpack = require('webpack');
const dotenv = require('dotenv');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = function(_env, argv) {
const isProduction = argv.mode === "production";
const isDevelopment = !isProduction;
return {
devtool: isDevelopment && "cheap-module-source-map",
entry: "./src/index.js",
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
options: {
limit: 10000,
},
},
],
},
{
test: /\.(woff(2)?|png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
]
},
plugins: [new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "./index.html"
}),
new webpack.DefinePlugin({
'process.env': JSON.stringify(dotenv.config().parsed) // it will automatically pick up key values from .env file
})],
};
};
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-TBNHVKT');</script>
<!-- End Google Tag Manager -->
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<script src="https://js.stripe.com/v3/"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>CarXpert</title>
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-TBNHVKT"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Just got the same error, even though everything was locked down with package-lock.json files, and was building successfully 2 days ago.
Updating html-webpack-plugin and webpack helped:
npm install webpack#latest
npm install html-webpack-plugin#latest

How to make webpack to inject script links into HTML server file?

My application is Flask-based and I'm using webpack to build JS (React is used for frontend).
When I was trying to use dynamic import I faced the problem it can't find 0.bundle.js file. It's pretty obvious, why: because I didn't include it. My html file is loaded from the server:
<!DOCTYPE html>
<html>
<head>
<title>Main</title>
<link rel="icon" type="image/x-icon" href="{{ url_for("static", filename="favicon.ico") }}" />
</head>
<body class="main">
<div id="root"></div>
<script src="{{ url_for("static", filename="dist/main.bundle.js")}}"></script>
</body>
</html>
And the webpack config fragment:
entry: {
main: './src/app/dashboard/main.jsx'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'static/dist')
},
Of course, if I add the following line everything is working:
<script src="{{ url_for("static", filename="dist/0.bundle.js")}}"></script>
But it's not good because I don't want to guess what will be the next chink if any.
How to configure it properly?
This example https://github.com/thatisuday/js-plugin-starter looks pretty much the same but I can't figure out how they handle this problem.
I also found that this plugin can help 'html-webpack-plugin' but not sure how to configure it (at least I didn't succeed yet).
I had to add the publicPath into webpack config:
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'static/dist'),
publicPath: 'static/dist/',
chunkFilename: '[name].bundle.js',
},

Webpack Not Serving React Component

I have created my webpack config file below:
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: '/node_modules/',
use: [
{
loader: 'babel-loader'
}
]
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: {minimize: true}
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
filename: './index.html'
})
]
};
and added all the necessary packages babel with env and react presets. I have my index.html file and TestComponent like below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React 16 Webpack Setup</title>
</head>
<body>
<script src="bundle.js" type="text/javascript"></script>
<div id="test">
</div>
</body>
</html>
and component code:
import React, { Component } from 'react';
export default class TestComponent extends Component {
render(){
return (
<div>
<h2>React Setup</h2>
</div>
)
}
}
Here's my main.js file where I'm hosting the component:
import React from "react";
import ReactDOM from "react-dom";
import Test from './TestComponent';
ReactDOM.render(<Test/>, document.getElementById("test"));
The problem is that when I run this script from package.json, I don't get any output/dist folder and also the component doesn't render in the browser. On which url do I have to visit to see the output just like with create-react-app?
Import your <script> at the bottom of the <body> tag in the HTML.
In your case, the browser is reading through the DOM and finding the <script> tag before it is finding the <div id="text"> node. What this means is that the browser will read through your script, and then try and render your <Test/> component into an HTML node with the id="test". The browser can't find the HTML node with the id="test" though because it hasn't read it yet, so it fails.
Make sense? See below...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React 16 Webpack Setup</title>
</head>
<body>
<div id="test"></div>
{* import scripts at the bottom of the body *}
<script src="bundle.js" type="text/javascript"></script>
</body>
</html>
Hope this helps, let me know if you're still running into issues.

Resources