jsbundling-rails
jsbundling-rails copied to clipboard
Assets:precomipile task has to be run twice
We are facing an interesting issue...
$ app/assets/builds # Empty
$ public/assets # Empty
$ bin/rails assets:precompile
yarn install
yarn build
and
I, [2023-07-03T10:50:06.731882 #1] INFO -- : Writing /web/public/assets/manifest-75a11da44c802486bc6f65640aa48a730f0f684c5c07a42ba3cd1735eb3fb070.js
I, [2023-07-03T10:50:06.732456 #1] INFO -- : Writing /web/public/assets/manifest-75a11da44c802486bc6f65640aa48a730f0f684c5c07a42ba3cd1735eb3fb070.js.gz
I, [2023-07-03T10:50:06.732856 #1] INFO -- : Writing /web/public/assets/nothing-uploaded-060da73a715f4a9d56da08aa5ce51d4e845eea67c11c911c6fb830726653ed2a.png
So the output is:
$ app/assets/builds
- application.js ... and more files
$ public/assets
- manifests.js
- manifest.js.gz
- nothing-uploaded.png
If we run the task for the 2nd time:
$ bin/rails assets:precompile
yarn install
yarn build
and
I, [2023-07-03T10:50:06.731882 #1] INFO -- : Writing /web/public/assets/manifest-75a11da44c802486bc6f65640aa48a730f0f684c5c07a42ba3cd1735eb3fb070.js
I, [2023-07-03T10:50:06.732456 #1] INFO -- : Writing /web/public/assets/manifest-75a11da44c802486bc6f65640aa48a730f0f684c5c07a42ba3cd1735eb3fb070.js.gz
I, [2023-07-03T10:50:06.732856 #1] INFO -- : Writing /web/public/assets/nothing-uploaded-060da73a715f4a9d56da08aa5ce51d4e845eea67c11c911c6fb830726653ed2a.png
I, [2023-07-03T10:50:06.732856 #1] INFO -- : Writing /web/public/assets/applications.js
... and the rest of the files
It will do what it should do, it will use the files from app/assets/builds
to the public/assets
and create a proper manifest.js
. The first pass just creates an empty manifest. This is problematic, especially with empty docker builds.
Hi, I have the same behavior. I'm new to RoR so I was thinking it was my fault, and posted a stackoverflow request here: https://stackoverflow.com/questions/76639570/forced-to-run-assetsprecompile-two-times-to-get-the-webpack-builds-copied-to-pu
You mentioned app/assets/builds
is empty. But does it exist? I've only seem this specific behavior when the folder itself had been deleted.
Hi @brenogazzola
For my tests, the first thing I do is to delete this folder. In the assets:precompile
task, the first step is yarn install
, the second one is yarn run webpack
(or something similar), so at this time the directory is created and populated by webpack. Finally, these files are (not) copied by the assets:precompile
task to the public folder.
When I run the task the second time, without deleting theapp/assets/builds
folder this time, the same process is executed but the builded (by webpack) files are correctly copied to the public folder.
By this facts, we can suppose that the copy occurs before webpack compile, but this is not the case as we see in the console output 🤷♂️ A parallel execution or a docker filesystem latency could be the cause?
I'm not sure, as I don't use Docker myself. But best way to handle this is to delete the files inside the folder, but keep the folder (and make sure you have a .keep
file there so it gets commit to git and not removed by accident).
I'm not sure, as I don't use Docker myself. But best way to handle this is to delete the files inside the folder, but keep the folder (and make sure you have a
.keep
file there so it gets commit to git and not removed by accident).
The behavior is Docker-independent, it is doing the same thing locally, even on clean installation of rails. Looks like manifest.js
is executed and cached before the yarn build
? 🤔
@brenogazzola Yeah if I leave .keep file, I did not have to precompile twice. Thanks.
Thank you, same thing for me. I've understood why the .keep file was removed:
output: {
path: path.resolve(__dirname, "app/assets/builds/"),
clean: true,
}
So webpack remove the whole content of the directory on build... 😏
I've noticed something interesting that might be the cause of this issue. In the Rails console:
> Rails.application.load_tasks
> Rake::Task['assets:precompile'].prereqs
=> ["environment", "javascript:build"]
The interesting thing to notice here is that the assets:precompile
task depends first on environment
and then on javascript:build
task.
The environment
task spins up the entire Rails environment, including Sprockets. And look at what Sprockets does when it's loaded:
https://github.com/rails/sprockets-rails/blob/065cbe83989c44019eca7161782ed4fdb6473517/lib/sprockets/railtie.rb#L48-L54
I feel that the caching on the Sprockets side might be the reason Sprockets cannot find the builds
folder if it has been created after running the environment
task.
So we should try to change the order of the dependencies of the assets:precompile
task (javascript:build
before environment
) and see what happens...
Update: I've tried to make the javascript:build
task run before environment
by changing the following line
https://github.com/rails/jsbundling-rails/blob/7faf59f85303d44f39e78cfce21db09dbe48d60a/lib/tasks/jsbundling/build.rake#L66
to Rake::Task["assets:precompile"].prereqs.prepend("javascript:build")
, but it didn't fix the issue as I hoped.