creamidea / creamidea.github.com

冰糖火箭筒&&蜂蜜甜甜圈
https://creamidea.github.io/
4 stars 4 forks source link

webpack 的 __webpack_public_path__ 工作原理 #41

Open creamidea opened 2 years ago

creamidea commented 2 years ago

前置知识

JS 的全局变量和局部变量

Webpack 对 publicPath 的解释

Webpack 的 bootstrap 过程

记录

运行时,webpack bootstrap 代码中,对于需要加载的 JS/CSS 会增加 webpack_require.p 前缀,如

// manifest.js
    // ...

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "http://xx.com/public/"; // 赋值publicPath的值
    //...

/******/    script.src = __webpack_require__.p + "" + ({"0":"A","1":"B"}[chunkId]||chunkId) + ".js";
    // ...

编译时,webpack 会分析代码,如果识别到 __webpack_public_path__="http://xx.com/public/",则会处理成 __webpack_require__.p = "http://xx.com/public/" (这里也解释了,为什么 window.__webpack_public_path__ 不起作用,原因就在这里:webpack 分析失败。)

// expr 数据结构
// https://juejin.cn/post/7062971609862111239
{
  type: "Identifier",
  start: 0,
  end: 100,
  loc: {
    start: { line: 1, column: 0 },
    end: { line: 1, column :100},
  },
  range:[0, 100],
  name: "__webpack_public_path__",
}

总结

__webpack_public_path__ 不是简单的 JS 变量,它会在 webpack 处理阶段被转码成

// 某模块内
function(module, __webpack_exports__, __webpack_require__) {
  // ...
  __webpack_require__.p = __webpack_public_path__ 配置的地址  
  // ...
}

这里也就没有全局变量、局部变量等概念,也不能画蛇添足,在 __webpack_public_path__ 前面增加 window

又因为 import 作用于提升,代码运行存在时机问题。为了保证 __webpack_public_path__ 配置生效,就必须要保证代码能在尽可能前的地方运行。所以最好的方式: 创建 public-path.js 文件,文件内容 __webpack_public_path__ = xxx。并且在工程的第一行引入 import 'public-path.js';

其他参考