[Bug]: Component "XXXX" has not been bundled
Contact Details
No response
What happened?
Hello, Suddenly the error Component "XXXX" has not been bundled appeared for all of my components.
In dev mode it's working properly. But when it's in prod I have the following error at startup : "Expression expected in /app/dist/admin/components/dashboard.js"
This is my config :
components.ts : `import { ComponentLoader } from 'adminjs'
const componentLoader = new ComponentLoader()
const Components = { Dashboard: componentLoader.add('Dashboard', './components/dashboard'), ArticlePicture: componentLoader.add('ArticlePicture', './components/articlePicture'), UserPicture: componentLoader.add('UserPicture', './components/userPicture'), }
export { componentLoader, Components }`
adminjs.ts :
` admin = new AdminJS({
assets:
{
styles:['/main.css'],
},
componentLoader,
branding:{
//my branding
},
locale: {
//code for locales
},
resources: [
///my resources
],
dashboard: {
component: Components.Dashboard,
},
})
admin.watch() `
tsconfig.json :
{ "compilerOptions": { "jsx": "preserve", "target": "ESNext", "module": "NodeNext", "moduleResolution": "NodeNext", "resolveJsonModule": true, "removeComments": true, "allowJs": true, "outDir": "./dist", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, }, "include": [ "src/**/*", "src/**/*.json" ], "exclude": [ "node_modules", "src/migrations" ] }
Bug prevalence
Every time
AdminJS dependencies version
"@adminjs/express": "^6.1.1",
"@adminjs/sequelize": "^4.0.0",
"adminjs": "^7.8.15",
What browsers do you see the problem on?
Firefox
Relevant log output
Expression expected in /app/dist/admin/components/dashboard.js
Component "XXXX" has not been bundled
Relevant code that's giving you issues
components.ts :
import { ComponentLoader } from 'adminjs'
const componentLoader = new ComponentLoader()
const Components = {
Dashboard: componentLoader.add('Dashboard', './components/dashboard'),
ArticlePicture: componentLoader.add('ArticlePicture', './components/articlePicture'),
UserPicture: componentLoader.add('UserPicture', './components/userPicture'),
}
export { componentLoader, Components }
adminjs.ts :
admin = new AdminJS({
assets:
{
styles:['/main.css'],
},
componentLoader,
branding:{
//my branding
},
locale: {
//code for locales
},
resources: [
///my resources
],
dashboard: {
component: Components.Dashboard,
},
})
admin.watch()
tsconfig.json :
{
"compilerOptions": {
"jsx": "preserve",
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"resolveJsonModule": true,
"removeComments": true,
"allowJs": true,
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
},
"include": [
"src/**/*",
"src/**/*.json"
],
"exclude": [
"node_modules",
"src/migrations"
]
}
dashboard:
import React, { useState, useEffect } from 'react'
const Dashboard = () =>
{
const [usersCount, setuserCount] = useState(0);
useEffect(() =>
{
fetch('/admin/users-count')
.then((response) => response.json())
.then((data) => setuserCount(data.usersCount))
.catch((error) => console.error('Err : ', error));
}, []);
return(
<div className='admin-dashboard-box-container'>
<p><span style={{fontSize: 25, fontWeight: 'bold'}}>{usersCount}</span></p>
<p>test</p>
</div>
)
}
export default Dashboard
Where do you host your app?
Where do you host your app?
On a VPS in a docker container
Can you check if:
.adminjsfolder is created in your docker image when the server starts? Unless you use@adminjs/bundler, the custom components bundle is generated when the server starts.- Changing
jsxtoreactintsconfig.jsonsolves the issue? - Using absolute paths via
path.joinsolves the issue?
Are your components using jsx, tsx or js extensions?
Can you check if:
1. `.adminjs` folder is created in your docker image when the server starts? Unless you use `@adminjs/bundler`, the custom components bundle is generated when the server starts. 2. Changing `jsx` to `react` in `tsconfig.json` solves the issue? 3. Using absolute paths via `path.join` solves the issue?Are your components using
jsx,tsxorjsextensions?
- .adminjs folder is ship in the container from the dev environment.
- No change
- No change
My components are jsx.
In dev it's working. Not in prod. Note that it used to work in prod, but not anymore for a reason I can't explain. I didn't remember changing something in specific
Re: 1. Ideally, .adminjs folder should be generated in the environment where the AJS will be running. It means you shouldn't commit that folder and it should be recreated in your Docker container when you start the application. Or, if you use @adminjs/bundler you can pregenerate all bundle files and upload them to some kind of storage. Not sure if this is related, if you run your local/dev app and a prod app in a Docker container, it should probably work regardless.
You could have a look at .adminjs folder contents:
.adminjs/.entry.jsshould containAdminJS.UserComponentsmappings. Check if all of your components are there and if their import paths are correct. If the paths are relative, they should be relative to the file inside of.adminjsfolder and corresponding files should exist..adminjs/bundle.jsshould contain the actual bundle generated from files in.entry.js. This file might actually not exist if you're running the admin panel in dev/watch mode since then the bundle is served dynamically.
Other thing to consider is:
You use admin.watch(). This method starts the bundler in watch mode where whenever any file changes occur, it will recreate the custom components.bundle.js. If your NODE_ENV is set to production, this command does nothing.
Instead, you should use initialize:
if (process.env.NODE_ENV === 'production') await admin.initialize();
else admin.watch();
Also make sure you use production for remote environments since otherwise the bundles served won't be minified.
Extra questions:
- When production environment starts, do the logs say that AdminJS is bundling files and afterwards how many files had been bundled?
- Could you share a screenshot of your browser's
Consoletab with the exact error?
Re: 1. Ideally,
.adminjsfolder should be generated in the environment where the AJS will be running. It means you shouldn't commit that folder and it should be recreated in your Docker container when you start the application. Or, if you use@adminjs/bundleryou can pregenerate all bundle files and upload them to some kind of storage. Not sure if this is related, if you run your local/dev app and a prod app in a Docker container, it should probably work regardless.You could have a look at
.adminjsfolder contents:* `.adminjs/.entry.js` should contain `AdminJS.UserComponents` mappings. Check if all of your components are there and if their import paths are correct. If the paths are relative, they should be relative to the file inside of `.adminjs` folder and corresponding files should exist. * `.adminjs/bundle.js` should contain the actual bundle generated from files in `.entry.js`. This file might actually not exist if you're running the admin panel in dev/watch mode since then the bundle is served dynamically.Other thing to consider is:
You use
admin.watch(). This method starts the bundler in watch mode where whenever any file changes occur, it will recreate the customcomponents.bundle.js. If yourNODE_ENVis set toproduction, this command does nothing. Instead, you should useinitialize:if (process.env.NODE_ENV === 'production') await admin.initialize(); else admin.watch();
Also make sure you use
productionfor remote environments since otherwise the bundles served won't be minified.Extra questions:
1. When production environment starts, do the logs say that AdminJS is bundling files and afterwards how many files had been bundled? 2. Could you share a screenshot of your browser's `Console` tab with the exact error?
Hello, Thank you for trying to help me, really appreciate.
Following your advice I added .adminjs in my gitignore and dockerignore.
I also added this code :
if(process.env.NODE_ENV === 'production'){ admin.initialize() }else{ admin.watch() }
Now when I start my app in prod I'm getting the following logs :
AdminJS: bundling user components... AdminJS: bundling user components... App listening at port 3000
And when I'm going to my admin page my components are still not showing up and I have this log error (on the server) :
api-app-1 | NotFoundError: Not Found api-app-1 | at createHttpError (/app/node_modules/send/index.js:864:12) api-app-1 | at SendStream.error (/app/node_modules/send/index.js:169:31) api-app-1 | at SendStream.pipe (/app/node_modules/send/index.js:469:14) api-app-1 | at sendfile (/app/node_modules/express/lib/response.js:988:8) api-app-1 | at ServerResponse.sendFile (/app/node_modules/express/lib/response.js:397:3) api-app-1 | at file:///app/node_modules/@adminjs/express/lib/buildRouter.js:61:17 api-app-1 | at Layer.handleRequest (/app/node_modules/router/lib/layer.js:145:17) api-app-1 | at next (/app/node_modules/router/lib/route.js:160:13) api-app-1 | at Route.dispatch (/app/node_modules/router/lib/route.js:120:3) api-app-1 | at handle (/app/node_modules/router/index.js:427:11) api-app-1 | at Layer.handleRequest (/app/node_modules/router/lib/layer.js:145:17) api-app-1 | at /app/node_modules/router/index.js:292:15 api-app-1 | at processParams (/app/node_modules/router/index.js:574:12) api-app-1 | at next (/app/node_modules/router/index.js:288:5) api-app-1 | at /app/node_modules/express-formidable/lib/middleware.js:36:7 api-app-1 | at IncomingForm.<anonymous> (/app/node_modules/formidable/lib/incoming_form.js:107:9) api-app-1 | at IncomingForm.emit (node:events:518:28) api-app-1 | at IncomingForm._maybeEnd (/app/node_modules/formidable/lib/incoming_form.js:563:8) api-app-1 | at Object.end (/app/node_modules/formidable/lib/incoming_form.js:251:12) api-app-1 | at IncomingMessage.<anonymous> (/app/node_modules/formidable/lib/incoming_form.js:132:30) api-app-1 | at IncomingMessage.emit (node:events:518:28) api-app-1 | at endReadableNT (node:internal/streams/readable:1698:12) api-app-1 | at process.processTicksAndRejections (node:internal/process/task_queues:90:21) api-app-1 | NotFoundError: Not Found api-app-1 | at createHttpError (/app/node_modules/send/index.js:864:12) api-app-1 | at SendStream.error (/app/node_modules/send/index.js:169:31) api-app-1 | at SendStream.pipe (/app/node_modules/send/index.js:469:14) api-app-1 | at sendfile (/app/node_modules/express/lib/response.js:988:8) api-app-1 | at ServerResponse.sendFile (/app/node_modules/express/lib/response.js:397:3) api-app-1 | at file:///app/node_modules/@adminjs/express/lib/buildRouter.js:61:17 api-app-1 | at Layer.handleRequest (/app/node_modules/router/lib/layer.js:145:17) api-app-1 | at next (/app/node_modules/router/lib/route.js:160:13) api-app-1 | at Route.dispatch (/app/node_modules/router/lib/route.js:120:3) api-app-1 | at handle (/app/node_modules/router/index.js:427:11) api-app-1 | at Layer.handleRequest (/app/node_modules/router/lib/layer.js:145:17) api-app-1 | at /app/node_modules/router/index.js:292:15 api-app-1 | at processParams (/app/node_modules/router/index.js:574:12) api-app-1 | at next (/app/node_modules/router/index.js:288:5) api-app-1 | at /app/node_modules/express-formidable/lib/middleware.js:36:7 api-app-1 | at IncomingForm.<anonymous> (/app/node_modules/formidable/lib/incoming_form.js:107:9) api-app-1 | at IncomingForm.emit (node:events:518:28) api-app-1 | at IncomingForm._maybeEnd (/app/node_modules/formidable/lib/incoming_form.js:563:8) api-app-1 | at Object.end (/app/node_modules/formidable/lib/incoming_form.js:251:12) api-app-1 | at IncomingMessage.<anonymous> (/app/node_modules/formidable/lib/incoming_form.js:132:30) api-app-1 | at IncomingMessage.emit (node:events:518:28) api-app-1 | at endReadableNT (node:internal/streams/readable:1698:12) api-app-1 | at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
And on my browser I have this error :
The resource at “https://myprodurl/admin/frontend/assets/components.bundle.js” was blocked due to an incorrect MIME type (“text/html”) (X-Content-Type-Options: nosniff).
I went into the container to see the files, I have no admin/frontend/assets folder
$ ls README.md dist jest.config.ts nodemon.json package.json src __tests__ docs node_modules package-lock.json public tsconfig.json
my build is in dist folder. There's no admin folder in public folder
/app/dist/admin# ls adminjsconfig.js components components.js.map adminjsconfig.js.map components.js
Have a nice day
Hello, any news about it?
Hello, I really need help because it's for professional use. Do you need more information about my repo ?
Do you use a CDN? https://expressjs.com/en/guide/behind-proxies.html
Do you use a CDN? https://expressjs.com/en/guide/behind-proxies.html
I don't have a CDN but in my index I have app.set('trust proxy', 1);
if you get Content-Type: text/html error, it usually means you get error page instead of the file
see what you get from the response:
curl -I https://myprodurl/admin/frontend/assets/components.bundle.js
are you using some reverse proxy? Maybe it's misconfigured?
if you get Content-Type: text/html error, it usually means you get error page instead of the file
see what you get from the response:
curl-Ihttps://myprodurl/admin/frontend/assets/components.bundle.jsare you using some reverse proxy? Maybe it's misconfigured?
I'm using a reverse proxy with nginx. This is the config :
`server {
server_name xxxxx;
server_tokens off;
# Block wget user agent
if ($http_user_agent ~* (wget|curl) ) {
return 403;
}
location /images/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 10M;
}
location / {
limit_req zone=xxxxxxx burst=12 nodelay;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 10M;
}
location ~* \.(jpg|jpeg|png|gif|ico)$ {
expires 20d;
add_header Cache-Control "public, no-transform";
}
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_static on;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/xxxxx/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/xxxxxx/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
} `
Any idea?
Hi @serolgames,
I hope I'm not too late to help.
I ran into the same issue and found your question while troubleshooting. I spent around 5–6 hours reading and debugging the source code of both adminjs and @adminjs/express, and I finally found a workaround — though I haven't yet identified the root cause, and I'm honestly too tired and sleepy to keep digging for now.
The issue seems to be with the default .adminjs folder used for bundling. Express (res.send) appears to have trouble serving files from directories that start with a dot (like .adminjs).
The workaround is to use a custom directory that doesn’t start with a dot, like adminjs-temp or any other non-hidden folder.
You can fix it by setting the ADMIN_JS_TMP_DIR environment variable. For example:
ADMIN_JS_TMP_DIR=./node_modules/tmp/adminjs
This resolved the issue on my end. Hope it helps anyone else facing the same problem!
Solution from @hameda169 works (thank you!). I had that error when running the app on render.com and locally (with NODE_ENV=production). Changing the folder location fixed it.
Hi @serolgames, I hope I'm not too late to help.
I ran into the same issue and found your question while troubleshooting. I spent around 5–6 hours reading and debugging the source code of both
adminjsand@adminjs/express, and I finally found a workaround — though I haven't yet identified the root cause, and I'm honestly too tired and sleepy to keep digging for now.The issue seems to be with the default
.adminjsfolder used for bundling. Express (res.send) appears to have trouble serving files from directories that start with a dot (like.adminjs).The workaround is to use a custom directory that doesn’t start with a dot, like
adminjs-tempor any other non-hidden folder.You can fix it by setting the
ADMIN_JS_TMP_DIRenvironment variable. For example:ADMIN_JS_TMP_DIR=./node_modules/tmp/adminjs
This resolved the issue on my end. Hope it helps anyone else facing the same problem!
Not working for me, tried ./node_modules/tmp/adminjs, /tmp/adminjs and so on, still for some reason only behind reverse proxy custom components are inaccessible
Hi @serolgames, I hope I'm not too late to help. I ran into the same issue and found your question while troubleshooting. I spent around 5–6 hours reading and debugging the source code of both
adminjsand@adminjs/express, and I finally found a workaround — though I haven't yet identified the root cause, and I'm honestly too tired and sleepy to keep digging for now. The issue seems to be with the default.adminjsfolder used for bundling. Express (res.send) appears to have trouble serving files from directories that start with a dot (like.adminjs). The workaround is to use a custom directory that doesn’t start with a dot, likeadminjs-tempor any other non-hidden folder. You can fix it by setting theADMIN_JS_TMP_DIRenvironment variable. For example: ADMIN_JS_TMP_DIR=./node_modules/tmp/adminjs This resolved the issue on my end. Hope it helps anyone else facing the same problem!Not working for me, tried ./node_modules/tmp/adminjs, /tmp/adminjs and so on, still for some reason only behind reverse proxy custom components are inaccessible
/admin/frontend/assets/components.bundle.js just redirecting to /admin/login
@terminaate Could you please explain more what did you actually do to apply my solution?