Issue loading dynamic chunk in React application using webpack - reactjs

I am facing one issue where my react app is not able to load the lazily loaded chunk(Error: loading chunk 0 failed). Upon checking, I found the chunk is being requested from the relative url that is localhost.com:8000/chunk.js, instead of requesting it from the actual path that is set in the webpack config. My webpack config looks like below:
{
...
output: {
filename: '[name].client.bundle.js',
chunkFilename: 'chunk.js',
path: path.resolve(__dirname, '..', '.build', 'js'),
},
...
}
The other file that is bundle.js loads correctly from localhost.com:8000/build/js/bundle.js. It's just the problem with this chunk that it's not loading from the builds directory. I would really appreciate any help on this. Thanks a ton in advance :)

I just needed to set publicUrl in the output config and point it to /js. It works now! :)

Related

Rails 7, React & Esbuild - Static assets not served in production

I have created a simple new Rails 7 project from scratch with Esbuild and React to get to know these, and they indeed feel like a step up from Webpack, except I can't manage to have my static files (ie image) served in production.
I have an Esbuild config file:
// esbuild.config.js
const path = require('path');
require("esbuild").build({
entryPoints: ["application.jsx"],
bundle: true,
outdir: path.join(process.cwd(), "app/assets/builds"),
absWorkingDir: path.join(process.cwd(), "app/javascript"),
publicPath: "assets",
sourcemap: true,
watch: process.argv.includes('--watch'),
plugins: [],
loader: {
'.js': 'jsx',
'.jpg': 'file',
'.png': 'file',
'.MOV': 'file'
},
}).catch(() => process.exit(1));
I store my images in the app/javascript/images/ folder, and import and use them in a React component like that (for example):
import MyImage from "./images/myimage.jpg"
import styled from "styled-components";
//...
const SomeStyledComponent = styled.div`
background-image: url(${MyImage});
`
In development, everything works fine, Esbuild copies the images in the app/assets/builds/ folder, fingerprints them, and prepends all the images url with the publicPath property of my Esbuild config. The above image for example then has the relative url assets/myimage-FINGERPRINT.jpg which is served correctly in development.
Then things get complicated in production (production here being just a Docker container built for production - I don't add the Dockerfile to keep things simple as I don't think it would help, but happy to provide it of course).
In my production.rb I have added the following:
config.public_file_server.enabled = true
(which will be replaced by an environment variable later)
The assets precompiling succeeds, and my images are in the app/public/assets/ folder, fingerprinted once more by Sprockets this time (from what I understand), but now I get 404. I have tried changing Esbuild publicPath and have tried to get the images directly in my browser, but whatever I try (assets, public, public/assets), nothing work and I am running out of ideas.
I have temporary fix which is to change the loader for images to dataurl, but that does not feel like a good practice, as my compiled javascript is going to explode.
Thank you for your help!
I ran into a similar issue, and by looking at the answers to https://github.com/rails/jsbundling-rails/issues/76 and this PR: https://github.com/rails/sprockets/pull/726/files
I was able to figure out the proper setup that works.
in the build options, I changed
publicPath: "assets",
to
publicPath: "/assets",
(included the leading /, which was missing before and causing the wrong path to be used)
and then added the following option
assetNames: "[name]-[hash].digested",
which, as you might be able to tell from the linked PR, would prevent Sprockets from adding an additional layer of fingerprinting.
I hope that helps.

How to create multiple entry points(index.js) for a single react application?

I want to create two different builds for a single application. When I do an npm run build, it runs webpack and generates a build, and injects that build into the index.html file. What I ideally want to do is tell webpack to create one build from index.js and another build from index2.js. How do I achieve this? Looked into module federation, but wasn't able to figure out how to do this in a single application.
You can do this settings in webpack.config.js.
module.exports = {
entry: {
bundle1: "path for index1.js",
bundle2: "path for index2.js"
},
output: {
// `filename` provides a template for naming your bundles (remember to use `[name]`)
filename: '[name].js'
publicPath: 'Path for saving directory'
}};

how to control webpack-dev-server generate script src like localhost:3000/static/js/xxx.js?

when I use cra create a react app and npm run start, I see the dom tree like beblow
but for some special reason I hope it should be like
does anybody know how to change the webpackDevServer.config.js to achieve my goal?
change publicPath doesn't work o(╥﹏╥)o
Have you tried already to modify the base-href value in your index.html?
<base href="./">
With this, it will take the files from whatever server or directory you run your app from.
Also, if you need it set to that always, you could try:
<base href="http://localhost:3000/">
You could achieve that by using output property in your webpack.config.js file.
You can do something like this,
const BUILD_DIR = path.resolve(__dirname, 'point_to_static_folder')
output: {
path: BUILD_DIR,
filename: 'bundle.js',
publicPath: "http://localhost:3000/static/",
}
For your other files you can define rules to have those files as well.

Shipping a React application as a singular JS file

I have an application created with create-react-app which needs to be shipped as a singular .js file, complete with its components and CSS style sheets. How can it be done? Without ejecting, if possible. The standard npm run build command only provides source code split into chunks.
Tried solving this issue with with react-rewire-app, but the build failed to complete.
My config-override.js is as follows:
const path = require('path');
module.exports = function override(config, env) {
config.entry = {
'my-app': './src/index.js'
}
config.module.output = {
path: path.resolve(__dirname, '../target/classes/static/'),
filename: '[name].js',
publicPath: '/'
}
return config
}
``
You're looking to make a widget or a library, likely, not an application, so CRA is the wrong tool. CRA is a tool for applications, where you definitely don't want everything bundled into a single file like you're asking for, as that would be very poor user experience.
For library/widget bundlers, I'd take a look at something like Microbundle: https://github.com/developit/microbundle. Should be very little config.
That being said, you cannot include CSS style sheets in JS. You can't even import them into JS. You need to ship them along with your JS and let your user handle importing it through HTML or what have you.

How to point assets and html angular templates folder after building angularjs with webpack?

i am new to webpack, i have configured webpack to a working condition where my index.html file and budle.js file comes to /dist folder. iam aware that i can build css files too but for now i want to build js and run the app. please check the attached images for better understanding of the directory structure and the webpack build configuration.
My doubt is that if i run app from dist folder i would lose all the path of angular templates and image paths etc. how can i overcome this situation? any help is appreciated.
First of all, you need to know that the goal is to have a fully runnable stand alone application inside ./dist/ after build. All sourcefiles which are needed to run your application should be placed there. In that way you will be able to distribute your application by copy/upload/or-what-ever based on your ./dist/ directory. All other directories in your project are just for development. Those will be not a part of your distribution package.
Wrong approach: Trying to change the include path's in your application.
You need to copy or concat your sourcefiles (static files) into your distribution folder. I realy don't know why your views/templates are not stored in ./app/assets/ and not in ./app/views/ because ./app/views/ should be the correct path to store your views. Well, you need to copy your static sourcefiles. For example: You could use copy-webpack-plugin.
Your webpack config could look like this in the end:
var CopyWebpackPlugin = require('copy-webpack-plugin');
var path = require('path');
module.exports = {
context: path.join(__dirname, 'app'),
devServer: {
// This is required for older versions of webpack-dev-server
// if you use absolute 'to' paths. The path should be an
// absolute path to your build destination.
outputPath: path.join(__dirname, 'dist')
},
plugins: [
new CopyWebpackPlugin([
{
from: 'assets/**/*',
to: 'assets/'
},
{
from: 'views/**/*',
to: 'views/'
},
], {
ignore: [
],
// By default, we only copy modified files during
// a watch or webpack-dev-server build. Setting this
// to `true` copies all files.
copyUnmodified: true
})
]
};

Resources