Issue
For years I have been building apps with Vue-CLI which bundles Webpack. I see this prefix (protocol?) webpack://
but I don't actually know what it means.
For instance, in the generated source map for an app.xxx.js.map, I see:
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/App.vue?797c",...
So what does that webpack://
mean, exactly? It's obviously not a real protocol that the browser can resolve. So resolves it? And how?
The particular problem I'm having that leads me to want to understand this is that my generated chunk-vendors.8c348425.js.map
begins like this:
{"version":3,"sources":["webpack:///js/chunk-vendors.68249437.js"],...
In this case, there is no generated chunk-vendors.68249437.js
file anywhere. Should there be? Or is that an abstract generated name that doesn't actually refer to a real file?
I'm seeing errors in FireFox that I'm having a bit of trouble interpreting:
I think it's saying that it's (somehow) running that non-existent chunk-vendors.68249437.js file, and that is failing to fetch some (unidentified) resource?
Solution
tl;dr - webpack://
is an arbitrary protocol name to play nicely with browsers' source map viewers. Nesting each file name under this prefix displays them in a separate dropdown (webpack-demo
in this case):
Webpack (most JS bundlers, really) take some number of uncompressed source files and combine them into a single* compressed** bundle file that can be loaded by a browser in a single network request.
At a high level, source maps exist to allow developers to easily translate console messages and stack traces from their file line/column number in the bundle back to their original position in a source file. This may be something as simple as "line 1001 in the bundle was actually line 500 in foo.js", or something more tricky like "lines 1001-1021 were part of the compilation output from line 20 in MyComponent.vue". You can read the latest spec for source maps, but in essence they contain three things:
- Name of the output bundle file
- Name of the input file(s) used to generate the bundle
- Encoded mapping data connecting each line in (1) back to a file in (2)
The simplest source map looks something like this (omitted all but the relevant parts):
{
"file": "bundle.js",
"sourceRoot": "/",
"sources": ["foo.js", "bar.js"],
"mappings": "..."
}
This mapping is generated when two source files, foo.js
and bar.js
, are combined into a single bundle file, bundle.js
. When a browser renders this source map, it expects to find the original source files at /foo.js
and /bar.js
, respectively.
Instead of hosting the files individually, a source map may instead contain the files' contents itself:
{
"file": "bundle.js",
"sources": ["foo.js", "bar.js"],
"sourcesContent": ["/* foo.js contents */", "/* bar.js contents */"],
"mappings": "..."
}
When rendering this source map, the browser just reads the file contents directly, instead of making a request to another URL. File names in sources
are expected to be in the same order as sourcesContent
.
Alright, we're almost there.
So long as the files are inlined in the source map (sourcesContent
is set), the file names are arbitrary. In other words, foo.js
doesn't have to correspond to a real file named foo.js
, you could just as easily call it foo/bar/baz/garply.xyz
and any source map viewer would have no issue rendering it (remember, the file contents are stored by array index).
Most source map viewers (I've checked Chrome and Firefox specifically) will display sources in a separate dropdown based on their protocol prefix. The screenshot above shows a number of files nested under webpack-demo
; all of their sources
entries begin with webpack://webpack-demo/...
. It doesn't matter what the protocol is; foobar://
works just as well, with the caveat that each unique protocol prefix will get its own dropdown in the source map filetree. In fact, you can customize this prefix by setting devtoolModuleFilenameTemplate
(see here).
So, in short - webpack://
is an arbitrary, unique prefix used to nest source files in their own dropdown in the source map filetree. The filenames that follow webpack://
are usually 1:1 with actual files in the filesystem, but that's not always the case***.
* OK, code splitting is a thing, but single bundle file in the simple case.
** A bundle file doesn't have to be compressed, it can simply be every source file concatenated one after the other, but in practice bundles are usually run through one or more minficiation/uglification passes.
*** Webpack may perform one or more intermediate compression passes, combining sets of vendor files from node_modules
into chunks. I'm not 100% on the specifics here, but one way to avoid this is to use a different devtool
(see here).
Answered By - superhawk610 Answer Checked By - David Goodson (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.