webpack:// 到底是什么意思?

What exactly does webpack:// mean?

多年来,我一直在使用捆绑了 Webpack 的 Vue-CLI 构建应用程序。我看到这个前缀(协议?)webpack://,但我实际上不知道它是什么意思。

例如,在为 app.xxx.js.map 生成的源映射中,我看到:

{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/App.vue?797c",...

那么 webpack:// 到底是什么意思呢?这显然不是浏览器可以解析的真正协议。那么解决了吗?以及如何?

我遇到的特殊问题让我想了解这是我生成的 chunk-vendors.8c348425.js.map 开始是这样的:

{"version":3,"sources":["webpack:///js/chunk-vendors.68249437.js"],...

在这种情况下,任何地方都没有生成 chunk-vendors.68249437.js 文件。应该有吗?或者这是一个抽象生成的名称,实际上并不引用真实文件?

我在 FireFox 中看到错误,我在解释时遇到了一些问题:

我认为它是说(不知何故)运行 那个不存在的 chunk-vendors.68249437.js 文件,并且无法获取某些(未识别的)资源?

tl;dr - webpack:// 是一个任意的协议名称,可以很好地与浏览器的源地图查看器一起使用。将每个文件名嵌套在此前缀下,将它们显示在单独的下拉列表中(在本例中为 webpack-demo):

Webpack(实际上是大多数 JS 打包器)获取一些未压缩的源文件,并将它们组合成一个*压缩**包文件,浏览器可以在单个网络请求中加载该文件。

在高层次上,源映射的存在允许开发人员轻松地将控制台消息和堆栈跟踪从他们的文件包中的 line/column 编号转换回源文件中的原始位置。这可能像“包中的第 1001 行实际上是 foo.js 中的第 500 行”一样简单,或者像“第 1001-1021 行是 MyComponent.vue 中第 20 行的编译输出的一部分一样更棘手” ”。您可以阅读源映射的 latest spec,但本质上它们包含三件事:

  1. 输出包文件的名称
  2. 用于生成包的输入文件的名称
  3. 将 (1) 中的每一行连接回 (2) 中的文件的编码映射数据

最简单的 source map 看起来像这样(除了相关部分,其他都省略):

{
  "file": "bundle.js",
  "sourceRoot": "/",
  "sources": ["foo.js", "bar.js"],
  "mappings": "..."
}

此映射是在两个源文件 foo.jsbar.js 合并为一个包文件 bundle.js 时生成的。当浏览器呈现此源映射时,它希望分别在 /foo.js/bar.js 找到原始源文件。

源映射可能包含文件内容本身,而不是单独托管文件:

{
  "file": "bundle.js",
  "sources": ["foo.js", "bar.js"],
  "sourcesContent": ["/* foo.js contents */", "/* bar.js contents */"],
  "mappings": "..."
}

渲染这个源映射时,浏览器直接读取文件内容,而不是向另一个URL发出请求。 sources 中的文件名应与 sourcesContent.

中的文件名顺序相同

好的,我们快到了。

只要文件在源映射中内联(设置了sourcesContent),文件名是任意的。换句话说,foo.js 不必对应于名为 foo.js 的真实文件,您可以轻松地将其命名为 foo/bar/baz/garply.xyz,并且任何源地图查看器都可以毫无问题地呈现它(请记住,文件内容按数组索引存储)。

大多数源地图查看器(我已经检查过 Chrome 和 Firefox)将根据其协议前缀在单独的下拉列表中显示源。上面的屏幕截图显示了 webpack-demo 下嵌套的一些文件;他们的所有 sources 条目都以 webpack://webpack-demo/... 开头。 协议是什么并不重要; foobar:// 同样有效,但需要注意的是每个唯一的协议前缀将在源映射文件树中获得自己的下拉列表。事实上,您可以通过设置 devtoolModuleFilenameTemplate 来自定义此前缀(参见 here)。

所以,简而言之 - webpack:// 是一个任意的唯一前缀,用于将源文件嵌套在源映射文件树中它们自己的下拉列表中。 webpack:// 之后的文件名通常是 1:1 文件系统中的实际文件,但情况并非总是如此***。

* 好的,code splitting 是一个东西,但在简单的情况下是单个捆绑文件。

** 一个 bundle 文件不必压缩,它可以简单地将每个源文件一个接一个地连接起来,但实际上 bundle 通常是 运行 通过一个或多个 minficiation/uglification 通过。

*** Webpack 可能会执行一个或多个中间压缩过程,将 node_modules 中的供应商文件集组合成块。我不是 100% 了解这里的细节,但避免这种情况的一种方法是使用不同的 devtool(参见 here)。