背景

項目使用vue-cli-service@4打包一個bundle.js
希望bundle引用的文件使用cdn,但是發現publicPath設置無效:

我們打印了最終生成的webpack config

// 打印 config
api.configureWebpack(config => {
    console.log('hyhy', config);
});

// 打印結果
{
    ...
    output: {
        path: '/ks-puzzle/custom-widgets/customization-table/dist',
        filename: '[name].js',
        publicPath: 'https://hyhyhy.com',
        libraryTarget: 'umd'
     },
    ...
}

可以看到我們設置的publicPath是生效的;但是生成的打包產物中publicPath未生效,如下:

...
/******/     // Object.prototype.hasOwnProperty.call
/******/     __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/     // __webpack_public_path__
/******/     __webpack_require__.p = "";
/******/
/******/     // on error function for async loading
/******/     __webpack_require__.oe = function(err) { console.error(err); throw err; };
...

這裏的__webpack_require__.p就是publicPath,值是空字符串,設置無效。

遇到問題後首先百度谷歌了一下publicPath not work等相關關鍵字,一段時間後未找到答案,開始進入源碼找原因。

切入點:__webpack_require__.p

我們來到webpack中設置__webpack_require__.p的地方;

webpack配置publicPath無效問題_bundle

可以看到這裏設置得publicPath為空字符串。以這裏為起點開始追查

webpack入口

一直追溯到了webpack的起點

webpack配置publicPath無效問題_搜索_02

可以看到webpack接收到的publicPath就是空值,那麼問題可能出在上一層也就是vue-cli-service這一層

vue-cli-servicepublicPath的處理

在包@vue/cli-service中搜索publicPath,找到了下面這段代碼

webpack配置publicPath無效問題_bundle_03

可以看到當使用vue-cli-service進行lib方式打包時,publicPath會恆置為空。問題定位到了

解決方案

獲取到了進一步的信息後,重新進入谷歌搜索vue-cli-service target lib publicPath not work

找到了社區解決方法:https://github.com/vuejs/vue-cli/issues/4896#issuecomment-569001811

使用自定義webpack plugin,在beforeRun的時候重新修改publicPath,明細如下:

function PublicPathWebpackPlugin() {}

PublicPathWebpackPlugin.prototype.apply = function (compiler) {
    compiler.hooks.beforeRun.tap('PublicPathWebpackPlugin', compiler => {
        compiler.options.output.publicPath = 'https://hyhyhy.com';
    });
};
api.configureWebpack(config => {
    config.plugins.unshift(new PublicPathWebpackPlugin());
});

打包後發現__webpack_require__.p設置正常,問題解決,done

PS

libraryTarget

追查問題過程中發現libraryTarget設置也是無效的

...
const configMap = {
    commonjs: genConfig('commonjs2', 'common'),
    umd: genConfig('umd', undefined, true),
    'umd-min': genConfig('umd', 'umd.min')
}

function genConfig(format, postfix = format, genHTML) {
    ...
    // set output target before user configureWebpack hooks are applied
    config.output.libraryTarget(format)

    // set entry/output after user configureWebpack hooks are applied
    const rawConfig = api.resolveWebpackConfig(config)
    ...
}

可以看到使用vue-cli-service打包必然打出3種包commonjs;umd;umd.min;

解決思路

總結下日常解決項目中問題的思路

  1. 首先使用百度Googlechatgpt查詢,看是否有人遇到過類似問題,如果查到了那麼問題解決,如果沒查到可能有以下幾種原因:
  • 有人遇到過類似的問題
  • 關鍵字設置的有誤導致答案沒有搜索出來;修改關鍵字或者添加關鍵字。
  • 根據當前信息無法推導出有效關鍵字。
  • 無人遇到過這個問題;
  • 超過1小時未解決,進入第2步
  1. 進入源碼尋找答案
  • 找到問題切入點(最難)
  • 向上層源碼追溯問題原因
  • 根據問題具體原因,重新搜索解法或者自定義解法