create-react-app: asset-manifest.json generated by CRA2 is not useful
As mentioned in the discussion in #5306, asset-manifest.json
generated by CRA2 is less than useful. As an example, this is asset-manifest.json
as generated by yarn build
for my project:
{
"main.css": "/static/css/main.7263860d.chunk.css",
"main.js": "/static/js/main.1d09f064.chunk.js",
"main.js.map": "/static/js/main.1d09f064.chunk.js.map",
"static/css/1.a7cf09a2.chunk.css": "/static/css/1.a7cf09a2.chunk.css",
"static/js/1.f5aeaa31.chunk.js": "/static/js/1.f5aeaa31.chunk.js",
"static/js/1.f5aeaa31.chunk.js.map": "/static/js/1.f5aeaa31.chunk.js.map",
"runtime~main.js": "/static/js/runtime~main.229c360f.js",
"runtime~main.js.map": "/static/js/runtime~main.229c360f.js.map",
"static/css/1.a7cf09a2.chunk.css.map": "/static/css/1.a7cf09a2.chunk.css.map",
"static/css/main.7263860d.chunk.css.map": "/static/css/main.7263860d.chunk.css.map",
"index.html": "/index.html",
"precache-manifest.981d9ec8b3a8232e0184126d691edb97.js": "/precache-manifest.981d9ec8b3a8232e0184126d691edb97.js",
"service-worker.js": "/service-worker.js"
}
It was quite an unpleasant surprise when I upgraded to CRA2. Here are some obvious problems with this file:
- it contains no information on which files are chunks of the same package
- there is no way to identify chunks (except the ‘main’ chunk) by key (random strings in keys? seriously?)
- there is absolutely no information on the order in which chunks are to be loaded
It can of course still be parsed by pattern matching file names but there are obvious disadvantages:
- any such parsing will rely on heuristics
- parsing will break if file naming scheme is ever changed
- what is the point of having this file at all? you could
listdir()
the build directory and obtain basically the same information
Here is a suggested asset-manifest.json
format that could make it usable:
{
"main.js": [
"/static/js/1.f5aeaa31.chunk.js", // <-- order is significant
"/static/js/main.1d09f064.chunk.js",
],
"main.js.map": [
"static/js/1.f5aeaa31.chunk.js.map", // <-- same order as in "main.js"
"/static/js/main.1d09f064.chunk.js.map",
]
"runtime~main.js": "/static/js/runtime~main.229c360f.js",
"runtime~main.js.map": "/static/js/runtime~main.229c360f.js.map",
"precache-manifest.js": "/precache-manifest.981d9ec8b3a8232e0184126d691edb97.js",
"service-worker.js": "/service-worker.js"
"main.css": [
"/static/css/1.a7cf09a2.chunk.css"
"/static/css/main.7263860d.chunk.css"
],
"main.css.map": [
"/static/css/1.a7cf09a2.chunk.css.map"
"/static/css/main.7263860d.chunk.css.map"
],
}
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 21
- Comments: 16 (4 by maintainers)
I think we should just change it to only include “initial” scripts in the order they should be in HTML. Since the only purpose of this file is to reconstruct the HTML.
Does that make sense?
Sad to see #5955 and similar pull requests and issues being closed by stale bot. Is parsing the generated index.html file the only option forward when including CRA components on a site with a backend?
I’ve created a small script (gist) that you can run in your pipeline or with
npm run build && node ./[scriptFileName].js
.It generates something like this, containing only the paths that you need in your html in the correct order.
Which your backend can then use to generate the
link
andscript
tags.I’m looking forward to a proper v3.x implementation by CRA though 😃
We also just got this problem when trying to add React components to an existing ASP.NET MVC page.
We solved it similar to @mdecorte. I created a node script that uses
node-html-parser
to parse theindex.html
file. It then creates a new json file that we can parse in the backend of our ASP.NET MVC site and basically recreate theindex.html
file CRA built.I definitely think there should be an option of building a CRA React app optimized for embedding in existing pages, must be a pretty common scenario when slowly migrating to React.
Having the asset-manifest only include the “initial” scripts would meet our needs. We have two main ways we use our react app: whole-page and partial-page. The “whole-page” use case can just use the index.html from the build (with some dynamic replacements), but in the “partial-page” case (typically a button or icon that opens a modal dialog rendered via the react app) we don’t use the index.html at all and instead leverage the asset-manifest to pull in the main js and css files. Now with CRA 2, the index.html is also including a “15.<hash>.chunk.js” and of course I have no guarantee that this main vendor chunk will still begin with “15” on my next build.
Another possible (and much quicker to implement) way to address this would be to support a boolean environment variable such as
process.env.ASYNC_CHUNKS_ONLY
to control setting the chunks value inoptimization: { splitChunks: { chunks: 'all'} }
to be “async” instead of “all”. This avoids having a separate vendor chunk referenced in index.html (it gets baked into main.js like before). I don’t have much of an understanding for the reasons for CRA defaulting tochunks: 'all'
, but I’d be willing to do a pull request for this alternative approach if it is considered worthwhile.I see this proposal is removed from 2.x milestone. What’s the plan for now? @Timer
We are hoping to add an
entrypoints
key to the asset manifest. That’s why we moved the list of files under its own key in 3.0. That plugin looks like it could be a good way to do that. Thanks.As far as I understand, enabling to extend the asset-manifest eventually allows adding the content of html-manifest to that singular manifest.
@zastavnitskiy I think https://github.com/facebook/create-react-app/pull/5955 show how you to reconstruct the HTML?
I evaluated
Webpack Manifest Plugin
andwebpack-assets-manifest
to understand if it’s possible to generate asset manifest that will allow users to reconstruct html.Both allow customization of generated manifest, either via
generate
function ofwebpack-manifest-plugin
, or viatranform
orcustomize
hooks in case ofwebpack-assets-manifest
.However, the data exposed in customisation hooks lacks either the information about the order of the chunks, or whether the chunks needs to be included on the page or are asynchronous.
CRA generates
index.html
usinghtml-webpack-plugin
, and that one taps into the emit hook and then builds the list of files for the given entrypoint: by callingcompilation.entrypoints.get(entryName).getFiles()
In order to allow users build their custom html based on manifest, we will have to follow similar approach.
@iansu You mentioned adding entrypoints key to the manifest — does it imply that CRA is planning to support multiple entrypoints? Or we can assume a single index.html for now?
Does anyone work on this story already?